1*eabc0478Schristos /* $NetBSD: ntp_config.c,v 1.26 2024/08/18 20:47:17 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* ntp_config.c 4abb0f93cSkardel * 5abb0f93cSkardel * This file contains the ntpd configuration code. 6abb0f93cSkardel * 7abb0f93cSkardel * Written By: Sachin Kamboj 8abb0f93cSkardel * University of Delaware 9abb0f93cSkardel * Newark, DE 19711 10abb0f93cSkardel * Some parts borrowed from the older ntp_config.c 11abb0f93cSkardel * Copyright (c) 2006 12abb0f93cSkardel */ 13abb0f93cSkardel 14abb0f93cSkardel #ifdef HAVE_CONFIG_H 15abb0f93cSkardel # include <config.h> 16abb0f93cSkardel #endif 17abb0f93cSkardel 18abb0f93cSkardel #ifdef HAVE_NETINFO 19abb0f93cSkardel # include <netinfo/ni.h> 20abb0f93cSkardel #endif 21abb0f93cSkardel 22abb0f93cSkardel #include <stdio.h> 23abb0f93cSkardel #include <ctype.h> 24abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H 25abb0f93cSkardel # include <sys/param.h> 26abb0f93cSkardel #endif 27abb0f93cSkardel #include <signal.h> 28abb0f93cSkardel #ifndef SIGCHLD 29abb0f93cSkardel # define SIGCHLD SIGCLD 30abb0f93cSkardel #endif 31abb0f93cSkardel #ifdef HAVE_SYS_WAIT_H 32abb0f93cSkardel # include <sys/wait.h> 33abb0f93cSkardel #endif 34cdfa2a7eSchristos #include <time.h> 35abb0f93cSkardel 362950cc38Schristos #include <isc/net.h> 372950cc38Schristos #include <isc/result.h> 38abb0f93cSkardel 392950cc38Schristos #include "ntp.h" 402950cc38Schristos #include "ntpd.h" 412950cc38Schristos #include "ntp_io.h" 422950cc38Schristos #include "ntp_unixtime.h" 432950cc38Schristos #include "ntp_refclock.h" 44*eabc0478Schristos #include "ntp_clockdev.h" 452950cc38Schristos #include "ntp_filegen.h" 462950cc38Schristos #include "ntp_stdlib.h" 472950cc38Schristos #include "ntp_assert.h" 482950cc38Schristos #include "ntp_random.h" 49abb0f93cSkardel /* 50abb0f93cSkardel * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS 51abb0f93cSkardel * so #include these later. 52abb0f93cSkardel */ 53abb0f93cSkardel #include "ntp_config.h" 54abb0f93cSkardel #include "ntp_cmdargs.h" 55abb0f93cSkardel #include "ntp_scanner.h" 56abb0f93cSkardel #include "ntp_parser.h" 572950cc38Schristos #include "ntpd-opts.h" 58abb0f93cSkardel 5903cfe0ffSchristos #ifndef IGNORE_DNS_ERRORS 6003cfe0ffSchristos # define DNSFLAGS 0 6103cfe0ffSchristos #else 6203cfe0ffSchristos # define DNSFLAGS GAIR_F_IGNDNSERR 6303cfe0ffSchristos #endif 6403cfe0ffSchristos 6568dbbb44Schristos extern int yyparse(void); 6668dbbb44Schristos 67af12ab5eSchristos /* Bug 2817 */ 68af12ab5eSchristos #if defined(HAVE_SYS_MMAN_H) 69af12ab5eSchristos # include <sys/mman.h> 70af12ab5eSchristos #endif 71ea66d795Schristos 72a3a68b73Sjoerg /* 73a3a68b73Sjoerg * Poll Skew List 74a3a68b73Sjoerg */ 75a3a68b73Sjoerg 76a3a68b73Sjoerg static psl_item psl[17-3+1]; /* values for polls 3-17 */ 77a3a68b73Sjoerg /* To simplify the runtime code we */ 78a3a68b73Sjoerg /* don't want to have to special-case */ 79a3a68b73Sjoerg /* dealing with a default */ 80a3a68b73Sjoerg 81a3a68b73Sjoerg 822950cc38Schristos /* list of servers from command line for config_peers() */ 832950cc38Schristos int cmdline_server_count; 842950cc38Schristos char ** cmdline_servers; 852950cc38Schristos 86af12ab5eSchristos /* Current state of memory locking: 87af12ab5eSchristos * -1: default 88af12ab5eSchristos * 0: memory locking disabled 89af12ab5eSchristos * 1: Memory locking enabled 90af12ab5eSchristos */ 91af12ab5eSchristos int cur_memlock = -1; 922950cc38Schristos 93abb0f93cSkardel /* 94abb0f93cSkardel * "logconfig" building blocks 95abb0f93cSkardel */ 96abb0f93cSkardel struct masks { 973123f114Skardel const char * const name; 983123f114Skardel const u_int32 mask; 99abb0f93cSkardel }; 100abb0f93cSkardel 101abb0f93cSkardel static struct masks logcfg_class[] = { 102abb0f93cSkardel { "clock", NLOG_OCLOCK }, 103abb0f93cSkardel { "peer", NLOG_OPEER }, 104abb0f93cSkardel { "sync", NLOG_OSYNC }, 105abb0f93cSkardel { "sys", NLOG_OSYS }, 1063123f114Skardel { NULL, 0 } 107abb0f93cSkardel }; 108abb0f93cSkardel 1093123f114Skardel /* logcfg_noclass_items[] masks are complete and must not be shifted */ 1103123f114Skardel static struct masks logcfg_noclass_items[] = { 1113123f114Skardel { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK }, 112abb0f93cSkardel { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO }, 113abb0f93cSkardel { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT }, 114abb0f93cSkardel { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS }, 115abb0f93cSkardel { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST }, 1163123f114Skardel /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */ 117abb0f93cSkardel { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK }, 118abb0f93cSkardel { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER }, 119abb0f93cSkardel { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS }, 120abb0f93cSkardel { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC }, 1213123f114Skardel { NULL, 0 } 1223123f114Skardel }; 1233123f114Skardel 1243123f114Skardel /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */ 1253123f114Skardel static struct masks logcfg_class_items[] = { 1263123f114Skardel { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST }, 1273123f114Skardel { "info", NLOG_INFO }, 1283123f114Skardel { "events", NLOG_EVENT }, 1293123f114Skardel { "status", NLOG_STATUS }, 1303123f114Skardel { "statistics", NLOG_STATIST }, 1313123f114Skardel { NULL, 0 } 132abb0f93cSkardel }; 133abb0f93cSkardel 1342950cc38Schristos typedef struct peer_resolved_ctx_tag { 1352950cc38Schristos int flags; 1362950cc38Schristos int host_mode; /* T_* token identifier */ 1372950cc38Schristos u_short family; 1382950cc38Schristos keyid_t keyid; 1392950cc38Schristos u_char hmode; /* MODE_* */ 1402950cc38Schristos u_char version; 1412950cc38Schristos u_char minpoll; 1422950cc38Schristos u_char maxpoll; 1432950cc38Schristos u_int32 ttl; 1442950cc38Schristos const char * group; 145*eabc0478Schristos int was_initializing; 1462950cc38Schristos } peer_resolved_ctx; 1472950cc38Schristos 148abb0f93cSkardel /* Limits */ 149abb0f93cSkardel #define MAXPHONE 10 /* maximum number of phone strings */ 150abb0f93cSkardel #define MAXPPS 20 /* maximum length of PPS device string */ 151abb0f93cSkardel 152abb0f93cSkardel /* 153*eabc0478Schristos * Poll Skew List array has an entry for each supported poll 154*eabc0478Schristos * interval. 15550c1baceSchristos */ 156*eabc0478Schristos #define PSL_ENTRIES (NTP_MAXPOLL - NTP_MINPOLL + 1) 157*eabc0478Schristos static psl_item psl[PSL_ENTRIES]; 15850c1baceSchristos 15950c1baceSchristos /* 160abb0f93cSkardel * Miscellaneous macros 161abb0f93cSkardel */ 162abb0f93cSkardel #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0') 163abb0f93cSkardel #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 164abb0f93cSkardel 1657476e6e4Schristos #define _UC(str) ((char *)(intptr_t)(str)) 1667476e6e4Schristos 167abb0f93cSkardel /* 168abb0f93cSkardel * Definitions of things either imported from or exported to outside 169abb0f93cSkardel */ 170abb0f93cSkardel extern int yydebug; /* ntp_parser.c (.y) */ 1712950cc38Schristos config_tree cfgt; /* Parser output stored here */ 172cdfa2a7eSchristos config_tree *cfg_tree_history; /* History of configs */ 173abb0f93cSkardel char * sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */ 174abb0f93cSkardel char default_keysdir[] = NTP_KEYSDIR; 175abb0f93cSkardel char * keysdir = default_keysdir; /* crypto keys directory */ 176abb0f93cSkardel char * saveconfigdir; 177abb0f93cSkardel #if defined(HAVE_SCHED_SETSCHEDULER) 178abb0f93cSkardel int config_priority_override = 0; 179abb0f93cSkardel int config_priority; 180abb0f93cSkardel #endif 181abb0f93cSkardel 182abb0f93cSkardel const char *config_file; 183ea66d795Schristos static char default_ntp_signd_socket[] = 184abb0f93cSkardel #ifdef NTP_SIGND_PATH 185abb0f93cSkardel NTP_SIGND_PATH; 186abb0f93cSkardel #else 187abb0f93cSkardel ""; 188abb0f93cSkardel #endif 189abb0f93cSkardel char *ntp_signd_socket = default_ntp_signd_socket; 190abb0f93cSkardel #ifdef HAVE_NETINFO 191abb0f93cSkardel struct netinfo_config_state *config_netinfo = NULL; 192abb0f93cSkardel int check_netinfo = 1; 193abb0f93cSkardel #endif /* HAVE_NETINFO */ 194abb0f93cSkardel #ifdef SYS_WINNT 195abb0f93cSkardel char *alt_config_file; 196abb0f93cSkardel LPTSTR temp; 197abb0f93cSkardel char config_file_storage[MAX_PATH]; 198abb0f93cSkardel char alt_config_file_storage[MAX_PATH]; 199abb0f93cSkardel #endif /* SYS_WINNT */ 200abb0f93cSkardel 201abb0f93cSkardel #ifdef HAVE_NETINFO 202abb0f93cSkardel /* 203abb0f93cSkardel * NetInfo configuration state 204abb0f93cSkardel */ 205abb0f93cSkardel struct netinfo_config_state { 206abb0f93cSkardel void *domain; /* domain with config */ 207abb0f93cSkardel ni_id config_dir; /* ID config dir */ 208abb0f93cSkardel int prop_index; /* current property */ 209abb0f93cSkardel int val_index; /* current value */ 210abb0f93cSkardel char **val_list; /* value list */ 211abb0f93cSkardel }; 212abb0f93cSkardel #endif 213abb0f93cSkardel 214abb0f93cSkardel struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and 215abb0f93cSkardel pointer info */ 216abb0f93cSkardel int old_config_style = 1; /* A boolean flag, which when set, 217abb0f93cSkardel * indicates that the old configuration 218abb0f93cSkardel * format with a newline at the end of 219abb0f93cSkardel * every command is being used 220abb0f93cSkardel */ 221abb0f93cSkardel int cryptosw; /* crypto command called */ 222abb0f93cSkardel 223abb0f93cSkardel extern char *stats_drift_file; /* name of the driftfile */ 224abb0f93cSkardel 225abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 226abb0f93cSkardel /* 227abb0f93cSkardel * backwards compatibility flags 228abb0f93cSkardel */ 229abb0f93cSkardel bc_entry bc_list[] = { 230abb0f93cSkardel { T_Bc_bugXXXX, 1 } /* default enabled */ 231abb0f93cSkardel }; 232abb0f93cSkardel 233abb0f93cSkardel /* 234abb0f93cSkardel * declare an int pointer for each flag for quick testing without 235abb0f93cSkardel * walking bc_list. If the pointer is consumed by libntp rather 236abb0f93cSkardel * than ntpd, declare it in a libntp source file pointing to storage 237abb0f93cSkardel * initialized with the appropriate value for other libntp clients, and 238abb0f93cSkardel * redirect it to point into bc_list during ntpd startup. 239abb0f93cSkardel */ 240abb0f93cSkardel int *p_bcXXXX_enabled = &bc_list[0].enabled; 241abb0f93cSkardel #endif 242abb0f93cSkardel 243abb0f93cSkardel /* FUNCTION PROTOTYPES */ 244abb0f93cSkardel 2452950cc38Schristos static void init_syntax_tree(config_tree *); 2462950cc38Schristos static void apply_enable_disable(attr_val_fifo *q, int enable); 247abb0f93cSkardel 248abb0f93cSkardel #ifdef FREE_CFG_T 2492950cc38Schristos static void free_auth_node(config_tree *); 250ea66d795Schristos static void free_all_config_trees(void); 251abb0f93cSkardel 2522950cc38Schristos static void free_config_access(config_tree *); 2532950cc38Schristos static void free_config_auth(config_tree *); 2542950cc38Schristos static void free_config_fudge(config_tree *); 255*eabc0478Schristos static void free_config_device(config_tree *); 2562950cc38Schristos static void free_config_logconfig(config_tree *); 2572950cc38Schristos static void free_config_monitor(config_tree *); 2582950cc38Schristos static void free_config_nic_rules(config_tree *); 2592950cc38Schristos static void free_config_other_modes(config_tree *); 2602950cc38Schristos static void free_config_phone(config_tree *); 2612950cc38Schristos static void free_config_reset_counters(config_tree *); 2622950cc38Schristos static void free_config_rlimit(config_tree *); 2632950cc38Schristos static void free_config_setvar(config_tree *); 2642950cc38Schristos static void free_config_system_opts(config_tree *); 2652950cc38Schristos static void free_config_tinker(config_tree *); 2662950cc38Schristos static void free_config_tos(config_tree *); 2672950cc38Schristos static void free_config_trap(config_tree *); 2682950cc38Schristos static void free_config_ttl(config_tree *); 2692950cc38Schristos static void free_config_vars(config_tree *); 2702950cc38Schristos 271abb0f93cSkardel #ifdef SIM 2722950cc38Schristos static void free_config_sim(config_tree *); 273*eabc0478Schristos #else /* !SIM follows */ 274*eabc0478Schristos static void free_config_peers(config_tree *); 275*eabc0478Schristos static void free_config_unpeers(config_tree *); 276*eabc0478Schristos static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode); 277*eabc0478Schristos #endif /* !SIM */ 2782950cc38Schristos static void destroy_address_fifo(address_fifo *); 2792950cc38Schristos #define FREE_ADDRESS_FIFO(pf) \ 2802950cc38Schristos do { \ 2812950cc38Schristos destroy_address_fifo(pf); \ 2822950cc38Schristos (pf) = NULL; \ 2832950cc38Schristos } while (0) 284abb0f93cSkardel void free_all_config_trees(void); /* atexit() */ 2852950cc38Schristos static void free_config_tree(config_tree *ptree); 286abb0f93cSkardel #endif /* FREE_CFG_T */ 287abb0f93cSkardel 2882950cc38Schristos static void destroy_restrict_node(restrict_node *my_node); 2895d681e99Schristos static void save_and_apply_config_tree(int/*BOOL*/ from_file); 2902950cc38Schristos static void destroy_int_fifo(int_fifo *); 2912950cc38Schristos #define FREE_INT_FIFO(pf) \ 2922950cc38Schristos do { \ 2932950cc38Schristos destroy_int_fifo(pf); \ 2942950cc38Schristos (pf) = NULL; \ 2952950cc38Schristos } while (0) 2962950cc38Schristos static void destroy_string_fifo(string_fifo *); 2972950cc38Schristos #define FREE_STRING_FIFO(pf) \ 2982950cc38Schristos do { \ 2992950cc38Schristos destroy_string_fifo(pf); \ 3002950cc38Schristos (pf) = NULL; \ 3012950cc38Schristos } while (0) 3022950cc38Schristos static void destroy_attr_val_fifo(attr_val_fifo *); 3032950cc38Schristos #define FREE_ATTR_VAL_FIFO(pf) \ 3042950cc38Schristos do { \ 3052950cc38Schristos destroy_attr_val_fifo(pf); \ 3062950cc38Schristos (pf) = NULL; \ 3072950cc38Schristos } while (0) 3082950cc38Schristos static void destroy_filegen_fifo(filegen_fifo *); 3092950cc38Schristos #define FREE_FILEGEN_FIFO(pf) \ 3102950cc38Schristos do { \ 3112950cc38Schristos destroy_filegen_fifo(pf); \ 3122950cc38Schristos (pf) = NULL; \ 3132950cc38Schristos } while (0) 3142950cc38Schristos static void destroy_restrict_fifo(restrict_fifo *); 3152950cc38Schristos #define FREE_RESTRICT_FIFO(pf) \ 3162950cc38Schristos do { \ 3172950cc38Schristos destroy_restrict_fifo(pf); \ 3182950cc38Schristos (pf) = NULL; \ 3192950cc38Schristos } while (0) 3202950cc38Schristos static void destroy_setvar_fifo(setvar_fifo *); 3212950cc38Schristos #define FREE_SETVAR_FIFO(pf) \ 3222950cc38Schristos do { \ 3232950cc38Schristos destroy_setvar_fifo(pf); \ 3242950cc38Schristos (pf) = NULL; \ 3252950cc38Schristos } while (0) 3262950cc38Schristos static void destroy_addr_opts_fifo(addr_opts_fifo *); 3272950cc38Schristos #define FREE_ADDR_OPTS_FIFO(pf) \ 3282950cc38Schristos do { \ 3292950cc38Schristos destroy_addr_opts_fifo(pf); \ 3302950cc38Schristos (pf) = NULL; \ 3312950cc38Schristos } while (0) 332abb0f93cSkardel 3332950cc38Schristos static void config_logconfig(config_tree *); 3342950cc38Schristos static void config_monitor(config_tree *); 3352950cc38Schristos static void config_rlimit(config_tree *); 3362950cc38Schristos static void config_system_opts(config_tree *); 3372950cc38Schristos static void config_tinker(config_tree *); 3382950cc38Schristos static void config_tos(config_tree *); 3392950cc38Schristos static void config_vars(config_tree *); 340abb0f93cSkardel 341abb0f93cSkardel #ifdef SIM 3422950cc38Schristos static sockaddr_u *get_next_address(address_node *addr); 3432950cc38Schristos static void config_sim(config_tree *); 3442950cc38Schristos static void config_ntpdsim(config_tree *); 3452950cc38Schristos #else /* !SIM follows */ 3465d681e99Schristos static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file); 3472950cc38Schristos static void config_other_modes(config_tree *); 3482950cc38Schristos static void config_auth(config_tree *); 349*eabc0478Schristos static void attrtopsl(u_char log2_poll, attr_val *avp); 3502950cc38Schristos static void config_access(config_tree *); 351a04a202dSchristos static void config_mdnstries(config_tree *); 3522950cc38Schristos static void config_phone(config_tree *); 3532950cc38Schristos static void config_setvar(config_tree *); 354*eabc0478Schristos static int config_tos_clock(config_tree *); 3552950cc38Schristos static void config_ttl(config_tree *); 3562950cc38Schristos static void config_trap(config_tree *); 3572950cc38Schristos static void config_fudge(config_tree *); 358*eabc0478Schristos static void config_device(config_tree *); 3592950cc38Schristos static void config_peers(config_tree *); 3602950cc38Schristos static void config_unpeers(config_tree *); 3615d681e99Schristos static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file); 3622950cc38Schristos static void config_reset_counters(config_tree *); 3632950cc38Schristos static u_char get_correct_host_mode(int token); 3642950cc38Schristos static int peerflag_bits(peer_node *); 3652950cc38Schristos 3662950cc38Schristos #ifdef WORKER 367ea66d795Schristos static void peer_name_resolved(int, int, void *, const char *, const char *, 3682950cc38Schristos const struct addrinfo *, 3692950cc38Schristos const struct addrinfo *); 370ea66d795Schristos static void unpeer_name_resolved(int, int, void *, const char *, const char *, 3712950cc38Schristos const struct addrinfo *, 3722950cc38Schristos const struct addrinfo *); 373ea66d795Schristos static void trap_name_resolved(int, int, void *, const char *, const char *, 3742950cc38Schristos const struct addrinfo *, 3752950cc38Schristos const struct addrinfo *); 376*eabc0478Schristos #endif /* WORKER */ 377*eabc0478Schristos #endif /* !SIM */ 378abb0f93cSkardel 379abb0f93cSkardel enum gnn_type { 380abb0f93cSkardel t_UNK, /* Unknown */ 381abb0f93cSkardel t_REF, /* Refclock */ 382abb0f93cSkardel t_MSK /* Network Mask */ 383abb0f93cSkardel }; 384abb0f93cSkardel 385ea66d795Schristos static void ntpd_set_tod_using(const char *); 3862950cc38Schristos static char * normal_dtoa(double); 3873123f114Skardel static u_int32 get_pfxmatch(const char **, struct masks *); 3883123f114Skardel static u_int32 get_match(const char *, struct masks *); 3893123f114Skardel static u_int32 get_logmask(const char *); 390ccc794f0Schristos static int/*BOOL*/ is_refclk_addr(const address_node * addr); 391ccc794f0Schristos 392abb0f93cSkardel static int getnetnum(const char *num, sockaddr_u *addr, int complain, 393abb0f93cSkardel enum gnn_type a_type); 394abb0f93cSkardel 395ccc794f0Schristos #if defined(__GNUC__) /* this covers CLANG, too */ 396*eabc0478Schristos static void __attribute__((__noreturn__,format(printf,1,2))) fatal_error(const char *fmt, ...) 397ccc794f0Schristos #elif defined(_MSC_VER) 398ccc794f0Schristos static void __declspec(noreturn) fatal_error(const char *fmt, ...) 399ccc794f0Schristos #else 400ccc794f0Schristos static void fatal_error(const char *fmt, ...) 401ccc794f0Schristos #endif 402ccc794f0Schristos { 403ccc794f0Schristos va_list va; 404ccc794f0Schristos 405ccc794f0Schristos va_start(va, fmt); 406ccc794f0Schristos mvsyslog(LOG_EMERG, fmt, va); 407ccc794f0Schristos va_end(va); 408ccc794f0Schristos _exit(1); 409ccc794f0Schristos } 410ccc794f0Schristos 411abb0f93cSkardel 412abb0f93cSkardel /* FUNCTIONS FOR INITIALIZATION 413abb0f93cSkardel * ---------------------------- 414abb0f93cSkardel */ 415abb0f93cSkardel 416abb0f93cSkardel #ifdef FREE_CFG_T 417abb0f93cSkardel static void 418abb0f93cSkardel free_auth_node( 4192950cc38Schristos config_tree *ptree 420abb0f93cSkardel ) 421abb0f93cSkardel { 422abb0f93cSkardel if (ptree->auth.keys) { 423abb0f93cSkardel free(ptree->auth.keys); 424abb0f93cSkardel ptree->auth.keys = NULL; 425abb0f93cSkardel } 426abb0f93cSkardel 427abb0f93cSkardel if (ptree->auth.keysdir) { 428abb0f93cSkardel free(ptree->auth.keysdir); 429abb0f93cSkardel ptree->auth.keysdir = NULL; 430abb0f93cSkardel } 431abb0f93cSkardel 432abb0f93cSkardel if (ptree->auth.ntp_signd_socket) { 433abb0f93cSkardel free(ptree->auth.ntp_signd_socket); 434abb0f93cSkardel ptree->auth.ntp_signd_socket = NULL; 435abb0f93cSkardel } 436abb0f93cSkardel } 437abb0f93cSkardel #endif /* DEBUG */ 438abb0f93cSkardel 439abb0f93cSkardel 440abb0f93cSkardel static void 441abb0f93cSkardel init_syntax_tree( 4422950cc38Schristos config_tree *ptree 443abb0f93cSkardel ) 444abb0f93cSkardel { 4452950cc38Schristos ZERO(*ptree); 446a04a202dSchristos ptree->mdnstries = 5; 447abb0f93cSkardel } 448abb0f93cSkardel 449abb0f93cSkardel 450abb0f93cSkardel #ifdef FREE_CFG_T 451ea66d795Schristos static void 452abb0f93cSkardel free_all_config_trees(void) 453abb0f93cSkardel { 4542950cc38Schristos config_tree *ptree; 4552950cc38Schristos config_tree *pnext; 456abb0f93cSkardel 457abb0f93cSkardel ptree = cfg_tree_history; 458abb0f93cSkardel 459abb0f93cSkardel while (ptree != NULL) { 460abb0f93cSkardel pnext = ptree->link; 461abb0f93cSkardel free_config_tree(ptree); 462abb0f93cSkardel ptree = pnext; 463abb0f93cSkardel } 464abb0f93cSkardel } 465abb0f93cSkardel 466abb0f93cSkardel 467abb0f93cSkardel static void 468abb0f93cSkardel free_config_tree( 4692950cc38Schristos config_tree *ptree 470abb0f93cSkardel ) 471abb0f93cSkardel { 472abb0f93cSkardel #if defined(_MSC_VER) && defined (_DEBUG) 473abb0f93cSkardel _CrtCheckMemory(); 474abb0f93cSkardel #endif 475abb0f93cSkardel 476abb0f93cSkardel if (ptree->source.value.s != NULL) 477abb0f93cSkardel free(ptree->source.value.s); 478abb0f93cSkardel 479abb0f93cSkardel free_config_other_modes(ptree); 480abb0f93cSkardel free_config_auth(ptree); 481abb0f93cSkardel free_config_tos(ptree); 482abb0f93cSkardel free_config_monitor(ptree); 483abb0f93cSkardel free_config_access(ptree); 484abb0f93cSkardel free_config_tinker(ptree); 4852950cc38Schristos free_config_rlimit(ptree); 486abb0f93cSkardel free_config_system_opts(ptree); 487abb0f93cSkardel free_config_logconfig(ptree); 488abb0f93cSkardel free_config_phone(ptree); 489abb0f93cSkardel free_config_setvar(ptree); 490abb0f93cSkardel free_config_ttl(ptree); 491abb0f93cSkardel free_config_trap(ptree); 492abb0f93cSkardel free_config_fudge(ptree); 493*eabc0478Schristos free_config_device(ptree); 494abb0f93cSkardel free_config_vars(ptree); 495abb0f93cSkardel free_config_nic_rules(ptree); 4962950cc38Schristos free_config_reset_counters(ptree); 497abb0f93cSkardel #ifdef SIM 498abb0f93cSkardel free_config_sim(ptree); 499*eabc0478Schristos #else /* !SIM follows */ 500*eabc0478Schristos free_config_peers(ptree); 501*eabc0478Schristos free_config_unpeers(ptree); 502*eabc0478Schristos #endif /* !SIM */ 503abb0f93cSkardel free_auth_node(ptree); 504abb0f93cSkardel 505abb0f93cSkardel free(ptree); 506abb0f93cSkardel 507abb0f93cSkardel #if defined(_MSC_VER) && defined (_DEBUG) 508abb0f93cSkardel _CrtCheckMemory(); 509abb0f93cSkardel #endif 510abb0f93cSkardel } 511abb0f93cSkardel #endif /* FREE_CFG_T */ 512abb0f93cSkardel 513abb0f93cSkardel 514abb0f93cSkardel #ifdef SAVECONFIG 515abb0f93cSkardel /* Dump all trees */ 516abb0f93cSkardel int 517abb0f93cSkardel dump_all_config_trees( 518abb0f93cSkardel FILE *df, 519abb0f93cSkardel int comment 520abb0f93cSkardel ) 521abb0f93cSkardel { 5222950cc38Schristos config_tree * cfg_ptr; 5232950cc38Schristos int return_value; 524cdfa2a7eSchristos time_t now = time(NULL); 525cdfa2a7eSchristos struct tm tm = *localtime(&now); 526cdfa2a7eSchristos 527cdfa2a7eSchristos fprintf(df, "#NTF:D %04d%02d%02d@%02d:%02d:%02d\n", 528cdfa2a7eSchristos tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, 529cdfa2a7eSchristos tm.tm_hour, tm.tm_min, tm.tm_sec); 530cdfa2a7eSchristos fprintf(df, "#NTF:V %s\n", Version); 531abb0f93cSkardel 5322950cc38Schristos return_value = 0; 533abb0f93cSkardel for (cfg_ptr = cfg_tree_history; 534abb0f93cSkardel cfg_ptr != NULL; 535abb0f93cSkardel cfg_ptr = cfg_ptr->link) 536abb0f93cSkardel return_value |= dump_config_tree(cfg_ptr, df, comment); 537abb0f93cSkardel 538abb0f93cSkardel return return_value; 539abb0f93cSkardel } 540abb0f93cSkardel 541abb0f93cSkardel 542abb0f93cSkardel /* The config dumper */ 543abb0f93cSkardel int 544abb0f93cSkardel dump_config_tree( 5452950cc38Schristos config_tree *ptree, 546abb0f93cSkardel FILE *df, 547abb0f93cSkardel int comment 548abb0f93cSkardel ) 549abb0f93cSkardel { 5502950cc38Schristos peer_node *peern; 5512950cc38Schristos unpeer_node *unpeern; 5522950cc38Schristos attr_val *atrv; 5532950cc38Schristos address_node *addr; 5542950cc38Schristos address_node *peer_addr; 5552950cc38Schristos address_node *fudge_addr; 5562950cc38Schristos filegen_node *fgen_node; 5572950cc38Schristos restrict_node *rest_node; 5582950cc38Schristos addr_opts_node *addr_opts; 5592950cc38Schristos setvar_node *setv_node; 560abb0f93cSkardel nic_rule_node *rule_node; 5612950cc38Schristos int_node *i_n; 5622950cc38Schristos int_node *counter_set; 5632950cc38Schristos string_node *str_node; 564abb0f93cSkardel 5652950cc38Schristos const char *s = NULL; 5662950cc38Schristos char *s1; 567abb0f93cSkardel char *s2; 568abb0f93cSkardel char timestamp[80]; 569abb0f93cSkardel int enable; 570abb0f93cSkardel 571abb0f93cSkardel DPRINTF(1, ("dump_config_tree(%p)\n", ptree)); 572abb0f93cSkardel 573abb0f93cSkardel if (comment) { 574abb0f93cSkardel if (!strftime(timestamp, sizeof(timestamp), 575abb0f93cSkardel "%Y-%m-%d %H:%M:%S", 576abb0f93cSkardel localtime(&ptree->timestamp))) 577abb0f93cSkardel timestamp[0] = '\0'; 578abb0f93cSkardel 579abb0f93cSkardel fprintf(df, "# %s %s %s\n", 580abb0f93cSkardel timestamp, 581abb0f93cSkardel (CONF_SOURCE_NTPQ == ptree->source.attr) 582abb0f93cSkardel ? "ntpq remote config from" 583abb0f93cSkardel : "startup configuration file", 584abb0f93cSkardel ptree->source.value.s); 585abb0f93cSkardel } 586abb0f93cSkardel 5874eea345dSchristos /* 5884eea345dSchristos * For options without documentation we just output the name 5894eea345dSchristos * and its data value 5904eea345dSchristos */ 5912950cc38Schristos atrv = HEAD_PFIFO(ptree->vars); 5922950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 5932950cc38Schristos switch (atrv->type) { 5942950cc38Schristos #ifdef DEBUG 595abb0f93cSkardel default: 596abb0f93cSkardel fprintf(df, "\n# dump error:\n" 5972950cc38Schristos "# unknown vars type %d (%s) for %s\n", 5982950cc38Schristos atrv->type, token_name(atrv->type), 599abb0f93cSkardel token_name(atrv->attr)); 600abb0f93cSkardel break; 6012950cc38Schristos #endif 6022950cc38Schristos case T_Double: 6032950cc38Schristos fprintf(df, "%s %s\n", keyword(atrv->attr), 6042950cc38Schristos normal_dtoa(atrv->value.d)); 605abb0f93cSkardel break; 606abb0f93cSkardel 6072950cc38Schristos case T_Integer: 6082950cc38Schristos fprintf(df, "%s %d\n", keyword(atrv->attr), 609abb0f93cSkardel atrv->value.i); 610abb0f93cSkardel break; 611abb0f93cSkardel 6122950cc38Schristos case T_String: 6132950cc38Schristos fprintf(df, "%s \"%s\"", keyword(atrv->attr), 614abb0f93cSkardel atrv->value.s); 6152950cc38Schristos if (T_Driftfile == atrv->attr && 6162950cc38Schristos atrv->link != NULL && 6172950cc38Schristos T_WanderThreshold == atrv->link->attr) { 6182950cc38Schristos atrv = atrv->link; 6192950cc38Schristos fprintf(df, " %s\n", 6202950cc38Schristos normal_dtoa(atrv->value.d)); 621cdfa2a7eSchristos } else if (T_Leapfile == atrv->attr) { 622cdfa2a7eSchristos fputs((atrv->flag 623cdfa2a7eSchristos ? " checkhash\n" 624cdfa2a7eSchristos : " ignorehash\n"), 625cdfa2a7eSchristos df); 6262950cc38Schristos } else { 6272950cc38Schristos fprintf(df, "\n"); 6282950cc38Schristos } 629abb0f93cSkardel break; 630abb0f93cSkardel } 631abb0f93cSkardel } 632abb0f93cSkardel 6332950cc38Schristos atrv = HEAD_PFIFO(ptree->logconfig); 6342950cc38Schristos if (atrv != NULL) { 635abb0f93cSkardel fprintf(df, "logconfig"); 6362950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) 637abb0f93cSkardel fprintf(df, " %c%s", atrv->attr, atrv->value.s); 638abb0f93cSkardel fprintf(df, "\n"); 639abb0f93cSkardel } 640abb0f93cSkardel 641abb0f93cSkardel if (ptree->stats_dir) 642abb0f93cSkardel fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir); 643abb0f93cSkardel 6442950cc38Schristos i_n = HEAD_PFIFO(ptree->stats_list); 6452950cc38Schristos if (i_n != NULL) { 646abb0f93cSkardel fprintf(df, "statistics"); 6472950cc38Schristos for ( ; i_n != NULL; i_n = i_n->link) 6482950cc38Schristos fprintf(df, " %s", keyword(i_n->i)); 649abb0f93cSkardel fprintf(df, "\n"); 650abb0f93cSkardel } 651abb0f93cSkardel 6522950cc38Schristos fgen_node = HEAD_PFIFO(ptree->filegen_opts); 6532950cc38Schristos for ( ; fgen_node != NULL; fgen_node = fgen_node->link) { 6542950cc38Schristos atrv = HEAD_PFIFO(fgen_node->options); 6552950cc38Schristos if (atrv != NULL) { 656abb0f93cSkardel fprintf(df, "filegen %s", 657abb0f93cSkardel keyword(fgen_node->filegen_token)); 6582950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 659abb0f93cSkardel switch (atrv->attr) { 6602950cc38Schristos #ifdef DEBUG 661abb0f93cSkardel default: 662abb0f93cSkardel fprintf(df, "\n# dump error:\n" 663abb0f93cSkardel "# unknown filegen option token %s\n" 664abb0f93cSkardel "filegen %s", 665abb0f93cSkardel token_name(atrv->attr), 666abb0f93cSkardel keyword(fgen_node->filegen_token)); 667abb0f93cSkardel break; 6682950cc38Schristos #endif 669abb0f93cSkardel case T_File: 670abb0f93cSkardel fprintf(df, " file %s", 671abb0f93cSkardel atrv->value.s); 672abb0f93cSkardel break; 673abb0f93cSkardel 674abb0f93cSkardel case T_Type: 675abb0f93cSkardel fprintf(df, " type %s", 676abb0f93cSkardel keyword(atrv->value.i)); 677abb0f93cSkardel break; 678abb0f93cSkardel 679abb0f93cSkardel case T_Flag: 680abb0f93cSkardel fprintf(df, " %s", 681abb0f93cSkardel keyword(atrv->value.i)); 682abb0f93cSkardel break; 683abb0f93cSkardel } 684abb0f93cSkardel } 685abb0f93cSkardel fprintf(df, "\n"); 686abb0f93cSkardel } 6872950cc38Schristos } 688abb0f93cSkardel 6892950cc38Schristos atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 6902950cc38Schristos if (atrv != NULL) { 691abb0f93cSkardel fprintf(df, "crypto"); 6922950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 693abb0f93cSkardel fprintf(df, " %s %s", keyword(atrv->attr), 694abb0f93cSkardel atrv->value.s); 695abb0f93cSkardel } 696abb0f93cSkardel fprintf(df, "\n"); 697abb0f93cSkardel } 698abb0f93cSkardel 699abb0f93cSkardel if (ptree->auth.revoke != 0) 700abb0f93cSkardel fprintf(df, "revoke %d\n", ptree->auth.revoke); 701abb0f93cSkardel 7022950cc38Schristos if (ptree->auth.keysdir != NULL) 703abb0f93cSkardel fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir); 704abb0f93cSkardel 7052950cc38Schristos if (ptree->auth.keys != NULL) 706abb0f93cSkardel fprintf(df, "keys \"%s\"\n", ptree->auth.keys); 707abb0f93cSkardel 7082950cc38Schristos atrv = HEAD_PFIFO(ptree->auth.trusted_key_list); 7093123f114Skardel if (atrv != NULL) { 7103123f114Skardel fprintf(df, "trustedkey"); 7112950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 7122950cc38Schristos if (T_Integer == atrv->type) 7133123f114Skardel fprintf(df, " %d", atrv->value.i); 7142950cc38Schristos else if (T_Intrange == atrv->type) 7152950cc38Schristos fprintf(df, " (%d ... %d)", 7162950cc38Schristos atrv->value.r.first, 7172950cc38Schristos atrv->value.r.last); 7182950cc38Schristos #ifdef DEBUG 7193123f114Skardel else 7203123f114Skardel fprintf(df, "\n# dump error:\n" 7212950cc38Schristos "# unknown trustedkey attr type %d\n" 7222950cc38Schristos "trustedkey", atrv->type); 7232950cc38Schristos #endif 7242950cc38Schristos } 725abb0f93cSkardel fprintf(df, "\n"); 726abb0f93cSkardel } 727abb0f93cSkardel 728abb0f93cSkardel if (ptree->auth.control_key) 729abb0f93cSkardel fprintf(df, "controlkey %d\n", ptree->auth.control_key); 730abb0f93cSkardel 731abb0f93cSkardel if (ptree->auth.request_key) 732abb0f93cSkardel fprintf(df, "requestkey %d\n", ptree->auth.request_key); 733abb0f93cSkardel 734abb0f93cSkardel /* dump enable list, then disable list */ 735abb0f93cSkardel for (enable = 1; enable >= 0; enable--) { 7362950cc38Schristos atrv = (enable) 7372950cc38Schristos ? HEAD_PFIFO(ptree->enable_opts) 7382950cc38Schristos : HEAD_PFIFO(ptree->disable_opts); 7392950cc38Schristos if (atrv != NULL) { 740ea66d795Schristos fprintf(df, "%s", (enable) 741abb0f93cSkardel ? "enable" 742abb0f93cSkardel : "disable"); 7432950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) 744abb0f93cSkardel fprintf(df, " %s", 745abb0f93cSkardel keyword(atrv->value.i)); 746abb0f93cSkardel fprintf(df, "\n"); 747abb0f93cSkardel } 748abb0f93cSkardel } 749abb0f93cSkardel 7502950cc38Schristos atrv = HEAD_PFIFO(ptree->orphan_cmds); 7512950cc38Schristos if (atrv != NULL) { 752abb0f93cSkardel fprintf(df, "tos"); 7532950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 7542950cc38Schristos switch (atrv->type) { 7552950cc38Schristos #ifdef DEBUG 756abb0f93cSkardel default: 757abb0f93cSkardel fprintf(df, "\n# dump error:\n" 7582950cc38Schristos "# unknown tos attr type %d %s\n" 7592950cc38Schristos "tos", atrv->type, 7602950cc38Schristos token_name(atrv->type)); 761abb0f93cSkardel break; 7622950cc38Schristos #endif 7634eea345dSchristos case T_Integer: 7644eea345dSchristos if (atrv->attr == T_Basedate) { 7654eea345dSchristos struct calendar jd; 7664eea345dSchristos ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS); 7674eea345dSchristos fprintf(df, " %s \"%04hu-%02hu-%02hu\"", 7684eea345dSchristos keyword(atrv->attr), jd.year, 7694eea345dSchristos (u_short)jd.month, 7704eea345dSchristos (u_short)jd.monthday); 7714eea345dSchristos } else { 7724eea345dSchristos fprintf(df, " %s %d", 7734eea345dSchristos keyword(atrv->attr), 7744eea345dSchristos atrv->value.i); 7754eea345dSchristos } 7764eea345dSchristos break; 7774eea345dSchristos 7782950cc38Schristos case T_Double: 7792950cc38Schristos fprintf(df, " %s %s", 7802950cc38Schristos keyword(atrv->attr), 7812950cc38Schristos normal_dtoa(atrv->value.d)); 782abb0f93cSkardel break; 783abb0f93cSkardel } 784abb0f93cSkardel } 785abb0f93cSkardel fprintf(df, "\n"); 786abb0f93cSkardel } 787abb0f93cSkardel 7882950cc38Schristos atrv = HEAD_PFIFO(ptree->rlimit); 7892950cc38Schristos if (atrv != NULL) { 7902950cc38Schristos fprintf(df, "rlimit"); 7912950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 792ea66d795Schristos INSIST(T_Integer == atrv->type); 7932950cc38Schristos fprintf(df, " %s %d", keyword(atrv->attr), 7942950cc38Schristos atrv->value.i); 7952950cc38Schristos } 7962950cc38Schristos fprintf(df, "\n"); 7972950cc38Schristos } 7982950cc38Schristos 7992950cc38Schristos atrv = HEAD_PFIFO(ptree->tinker); 8002950cc38Schristos if (atrv != NULL) { 8012950cc38Schristos fprintf(df, "tinker"); 8022950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 803ea66d795Schristos INSIST(T_Double == atrv->type); 8042950cc38Schristos fprintf(df, " %s %s", keyword(atrv->attr), 8052950cc38Schristos normal_dtoa(atrv->value.d)); 8062950cc38Schristos } 807abb0f93cSkardel fprintf(df, "\n"); 808abb0f93cSkardel } 809abb0f93cSkardel 810abb0f93cSkardel if (ptree->broadcastclient) 811abb0f93cSkardel fprintf(df, "broadcastclient\n"); 812abb0f93cSkardel 8132950cc38Schristos peern = HEAD_PFIFO(ptree->peers); 8142950cc38Schristos for ( ; peern != NULL; peern = peern->link) { 8152950cc38Schristos addr = peern->addr; 8162950cc38Schristos fprintf(df, "%s", keyword(peern->host_mode)); 817abb0f93cSkardel switch (addr->type) { 8182950cc38Schristos #ifdef DEBUG 819abb0f93cSkardel default: 820abb0f93cSkardel fprintf(df, "# dump error:\n" 821abb0f93cSkardel "# unknown peer family %d for:\n" 8222950cc38Schristos "%s", addr->type, 8232950cc38Schristos keyword(peern->host_mode)); 824abb0f93cSkardel break; 8252950cc38Schristos #endif 826abb0f93cSkardel case AF_UNSPEC: 827abb0f93cSkardel break; 828abb0f93cSkardel 829abb0f93cSkardel case AF_INET: 830abb0f93cSkardel fprintf(df, " -4"); 831abb0f93cSkardel break; 832abb0f93cSkardel 833abb0f93cSkardel case AF_INET6: 834abb0f93cSkardel fprintf(df, " -6"); 835abb0f93cSkardel break; 836abb0f93cSkardel } 837abb0f93cSkardel fprintf(df, " %s", addr->address); 838abb0f93cSkardel 8392950cc38Schristos if (peern->minpoll != 0) 8402950cc38Schristos fprintf(df, " minpoll %u", peern->minpoll); 841abb0f93cSkardel 8422950cc38Schristos if (peern->maxpoll != 0) 8432950cc38Schristos fprintf(df, " maxpoll %u", peern->maxpoll); 844abb0f93cSkardel 8452950cc38Schristos if (peern->ttl != 0) { 846abb0f93cSkardel if (strlen(addr->address) > 8 847abb0f93cSkardel && !memcmp(addr->address, "127.127.", 8)) 8482950cc38Schristos fprintf(df, " mode %u", peern->ttl); 849abb0f93cSkardel else 8502950cc38Schristos fprintf(df, " ttl %u", peern->ttl); 851abb0f93cSkardel } 852abb0f93cSkardel 8532950cc38Schristos if (peern->peerversion != NTP_VERSION) 8542950cc38Schristos fprintf(df, " version %u", peern->peerversion); 855abb0f93cSkardel 8562950cc38Schristos if (peern->peerkey != 0) 8572950cc38Schristos fprintf(df, " key %u", peern->peerkey); 858abb0f93cSkardel 8592950cc38Schristos if (peern->group != NULL) 8602950cc38Schristos fprintf(df, " ident \"%s\"", peern->group); 861abb0f93cSkardel 8622950cc38Schristos atrv = HEAD_PFIFO(peern->peerflags); 8632950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 864ea66d795Schristos INSIST(T_Flag == atrv->attr); 865ea66d795Schristos INSIST(T_Integer == atrv->type); 866abb0f93cSkardel fprintf(df, " %s", keyword(atrv->value.i)); 867abb0f93cSkardel } 868abb0f93cSkardel 869abb0f93cSkardel fprintf(df, "\n"); 870abb0f93cSkardel 8712950cc38Schristos addr_opts = HEAD_PFIFO(ptree->fudge); 8722950cc38Schristos for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 8732950cc38Schristos peer_addr = peern->addr; 874abb0f93cSkardel fudge_addr = addr_opts->addr; 875abb0f93cSkardel 876abb0f93cSkardel s1 = peer_addr->address; 877abb0f93cSkardel s2 = fudge_addr->address; 878abb0f93cSkardel 8792950cc38Schristos if (strcmp(s1, s2)) 8802950cc38Schristos continue; 881abb0f93cSkardel 8822950cc38Schristos fprintf(df, "fudge %s", s1); 883abb0f93cSkardel 8842950cc38Schristos for (atrv = HEAD_PFIFO(addr_opts->options); 8852950cc38Schristos atrv != NULL; 8862950cc38Schristos atrv = atrv->link) { 887abb0f93cSkardel 8882950cc38Schristos switch (atrv->type) { 8892950cc38Schristos #ifdef DEBUG 890abb0f93cSkardel default: 891abb0f93cSkardel fprintf(df, "\n# dump error:\n" 8922950cc38Schristos "# unknown fudge atrv->type %d\n" 8932950cc38Schristos "fudge %s", atrv->type, 8942950cc38Schristos s1); 895abb0f93cSkardel break; 8962950cc38Schristos #endif 8972950cc38Schristos case T_Double: 8982950cc38Schristos fprintf(df, " %s %s", 899abb0f93cSkardel keyword(atrv->attr), 9002950cc38Schristos normal_dtoa(atrv->value.d)); 901abb0f93cSkardel break; 902abb0f93cSkardel 9032950cc38Schristos case T_Integer: 904abb0f93cSkardel fprintf(df, " %s %d", 905abb0f93cSkardel keyword(atrv->attr), 906abb0f93cSkardel atrv->value.i); 907abb0f93cSkardel break; 908abb0f93cSkardel 9092950cc38Schristos case T_String: 910abb0f93cSkardel fprintf(df, " %s %s", 911abb0f93cSkardel keyword(atrv->attr), 912abb0f93cSkardel atrv->value.s); 913abb0f93cSkardel break; 914abb0f93cSkardel } 915abb0f93cSkardel } 916abb0f93cSkardel fprintf(df, "\n"); 917abb0f93cSkardel } 918*eabc0478Schristos 919*eabc0478Schristos addr_opts = HEAD_PFIFO(ptree->device); 920*eabc0478Schristos for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 921*eabc0478Schristos peer_addr = peern->addr; 922*eabc0478Schristos fudge_addr = addr_opts->addr; 923*eabc0478Schristos 924*eabc0478Schristos s1 = peer_addr->address; 925*eabc0478Schristos s2 = fudge_addr->address; 926*eabc0478Schristos 927*eabc0478Schristos if (strcmp(s1, s2)) 928*eabc0478Schristos continue; 929*eabc0478Schristos 930*eabc0478Schristos fprintf(df, "device %s", s1); 931*eabc0478Schristos 932*eabc0478Schristos for (atrv = HEAD_PFIFO(addr_opts->options); 933*eabc0478Schristos atrv != NULL; 934*eabc0478Schristos atrv = atrv->link) { 935*eabc0478Schristos 936*eabc0478Schristos switch (atrv->type) { 937*eabc0478Schristos #ifdef DEBUG 938*eabc0478Schristos default: 939*eabc0478Schristos fprintf(df, "\n# dump error:\n" 940*eabc0478Schristos "# unknown device atrv->type %d\n" 941*eabc0478Schristos "device %s", atrv->type, 942*eabc0478Schristos s1); 943*eabc0478Schristos break; 944*eabc0478Schristos #endif 945*eabc0478Schristos case T_String: 946*eabc0478Schristos fprintf(df, " %s %s", 947*eabc0478Schristos keyword(atrv->attr), 948*eabc0478Schristos atrv->value.s); 949*eabc0478Schristos break; 950*eabc0478Schristos } 951*eabc0478Schristos } 952*eabc0478Schristos fprintf(df, "\n"); 953*eabc0478Schristos } 954abb0f93cSkardel } 955abb0f93cSkardel 9562950cc38Schristos addr = HEAD_PFIFO(ptree->manycastserver); 9572950cc38Schristos if (addr != NULL) { 9582950cc38Schristos fprintf(df, "manycastserver"); 9592950cc38Schristos for ( ; addr != NULL; addr = addr->link) 960abb0f93cSkardel fprintf(df, " %s", addr->address); 961abb0f93cSkardel fprintf(df, "\n"); 962abb0f93cSkardel } 963abb0f93cSkardel 9642950cc38Schristos addr = HEAD_PFIFO(ptree->multicastclient); 9652950cc38Schristos if (addr != NULL) { 9662950cc38Schristos fprintf(df, "multicastclient"); 9672950cc38Schristos for ( ; addr != NULL; addr = addr->link) 968abb0f93cSkardel fprintf(df, " %s", addr->address); 969abb0f93cSkardel fprintf(df, "\n"); 970abb0f93cSkardel } 971abb0f93cSkardel 972abb0f93cSkardel 9732950cc38Schristos for (unpeern = HEAD_PFIFO(ptree->unpeers); 9742950cc38Schristos unpeern != NULL; 9752950cc38Schristos unpeern = unpeern->link) 9762950cc38Schristos fprintf(df, "unpeer %s\n", unpeern->addr->address); 977abb0f93cSkardel 9782950cc38Schristos atrv = HEAD_PFIFO(ptree->mru_opts); 9792950cc38Schristos if (atrv != NULL) { 9802950cc38Schristos fprintf(df, "mru"); 9812950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) 982abb0f93cSkardel fprintf(df, " %s %d", keyword(atrv->attr), 983abb0f93cSkardel atrv->value.i); 984abb0f93cSkardel fprintf(df, "\n"); 985abb0f93cSkardel } 986abb0f93cSkardel 9872950cc38Schristos atrv = HEAD_PFIFO(ptree->discard_opts); 9882950cc38Schristos if (atrv != NULL) { 9892950cc38Schristos fprintf(df, "discard"); 9902950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) 9912950cc38Schristos fprintf(df, " %s %d", keyword(atrv->attr), 9922950cc38Schristos atrv->value.i); 9932950cc38Schristos fprintf(df, "\n"); 9942950cc38Schristos } 995abb0f93cSkardel 996cdfa2a7eSchristos atrv = HEAD_PFIFO(ptree->pollskewlist); 997cdfa2a7eSchristos if (atrv != NULL) { 998cdfa2a7eSchristos fprintf(df, "pollskewlist"); 999cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) { 1000cdfa2a7eSchristos if (-1 == atrv->attr) { 1001cdfa2a7eSchristos fprintf(df, " default"); 1002cdfa2a7eSchristos } else { 1003cdfa2a7eSchristos fprintf(df, " %d", atrv->attr); 1004cdfa2a7eSchristos } 1005cdfa2a7eSchristos fprintf(df, " %d|%d", 1006cdfa2a7eSchristos atrv->value.r.first, atrv->value.r.last); 1007cdfa2a7eSchristos } 1008cdfa2a7eSchristos fprintf(df, "\n"); 1009cdfa2a7eSchristos } 1010cdfa2a7eSchristos 10112950cc38Schristos for (rest_node = HEAD_PFIFO(ptree->restrict_opts); 10122950cc38Schristos rest_node != NULL; 10132950cc38Schristos rest_node = rest_node->link) { 1014*eabc0478Schristos int/*BOOL*/ is_default = FALSE; 1015*eabc0478Schristos int/*BOOL*/ omit_mask; 1016*eabc0478Schristos sockaddr_u mask; 1017*eabc0478Schristos sockaddr_u onesmask; 1018abb0f93cSkardel 1019*eabc0478Schristos s = NULL; 1020cdfa2a7eSchristos atrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 1021cdfa2a7eSchristos for (; atrv != NULL; atrv = atrv->link) { 1022cdfa2a7eSchristos if ( T_Integer == atrv->type 1023cdfa2a7eSchristos && T_Source == atrv->attr) { 1024*eabc0478Schristos s = keyword(T_Source); 10252950cc38Schristos break; 10262950cc38Schristos } 10274eea345dSchristos } 1028*eabc0478Schristos if (NULL == rest_node->addr) { 1029*eabc0478Schristos if (NULL == s) { 1030*eabc0478Schristos s = keyword(T_Default); 1031*eabc0478Schristos /* Don't need to set is_default here */ 1032*eabc0478Schristos } 10332950cc38Schristos } else { 10344eea345dSchristos const char *ap = rest_node->addr->address; 10354eea345dSchristos const char *mp = ""; 10364eea345dSchristos 10374eea345dSchristos if (rest_node->mask) 10384eea345dSchristos mp = rest_node->mask->address; 10394eea345dSchristos 10404eea345dSchristos if ( rest_node->addr->type == AF_INET 1041*eabc0478Schristos && !strcmp(mp, "0.0.0.0") 1042*eabc0478Schristos && !strcmp(ap, mp)) { 1043*eabc0478Schristos is_default = TRUE; 10444eea345dSchristos s = "-4 default"; 10454eea345dSchristos } else if ( rest_node->mask 10464eea345dSchristos && rest_node->mask->type == AF_INET6 1047*eabc0478Schristos && !strcmp(mp, "::") 1048*eabc0478Schristos && !strcmp(ap, mp)) { 1049*eabc0478Schristos is_default = TRUE; 10504eea345dSchristos s = "-6 default"; 10514eea345dSchristos } else { 1052*eabc0478Schristos if (NULL == s) { 10534eea345dSchristos s = ap; 1054*eabc0478Schristos } else { 1055*eabc0478Schristos LIB_GETBUF(s1); 1056*eabc0478Schristos snprintf(s1, LIB_BUFLENGTH, 1057*eabc0478Schristos "%s %s", 1058*eabc0478Schristos keyword(T_Source), ap); 1059*eabc0478Schristos s = s1; 10604eea345dSchristos } 10612950cc38Schristos } 1062*eabc0478Schristos } 1063*eabc0478Schristos fprintf(df, "%s %s", 1064*eabc0478Schristos keyword(rest_node->remove 1065*eabc0478Schristos ? T_Delrestrict 1066*eabc0478Schristos : T_Restrict), 1067*eabc0478Schristos s); 1068*eabc0478Schristos if (rest_node->mask != NULL && !is_default) { 1069*eabc0478Schristos ZERO(mask); 1070*eabc0478Schristos AF(&mask) = AF_UNSPEC; 1071*eabc0478Schristos omit_mask = (0 != getnetnum(rest_node->mask->address, 1072*eabc0478Schristos &mask, 0, t_UNK)); 1073*eabc0478Schristos if (omit_mask) { 1074*eabc0478Schristos SET_HOSTMASK(&onesmask, AF(&mask)); 1075*eabc0478Schristos omit_mask = SOCK_EQ(&mask, &onesmask); 1076*eabc0478Schristos } 1077*eabc0478Schristos if (!omit_mask) { 1078abb0f93cSkardel fprintf(df, " mask %s", 1079abb0f93cSkardel rest_node->mask->address); 1080*eabc0478Schristos } 1081*eabc0478Schristos } 1082*eabc0478Schristos if (-1 != rest_node->ippeerlimit) { 1083*eabc0478Schristos fprintf(df, " ippeerlimit %d", 1084*eabc0478Schristos rest_node->ippeerlimit); 1085*eabc0478Schristos } 1086cdfa2a7eSchristos atrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 1087cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) { 1088cdfa2a7eSchristos if ( T_Integer == atrv->type 1089cdfa2a7eSchristos && T_Source != atrv->attr) { 1090cdfa2a7eSchristos fprintf(df, " %s", keyword(atrv->attr)); 1091cdfa2a7eSchristos } 1092cdfa2a7eSchristos } 1093abb0f93cSkardel fprintf(df, "\n"); 1094cdfa2a7eSchristos /**/ 1095cdfa2a7eSchristos #if 0 1096cdfa2a7eSchristos msyslog(LOG_INFO, "Dumping flag_tok_fifo:"); 1097cdfa2a7eSchristos atrv = HEAD_PFIFO(rest_node->flag_tok_fifo); 1098cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) { 1099cdfa2a7eSchristos msyslog(LOG_INFO, "- flag_tok_fifo: flags: %08x", atrv->flag); 1100cdfa2a7eSchristos switch(atrv->type) { 1101cdfa2a7eSchristos case T_Integer: 1102cdfa2a7eSchristos msyslog(LOG_INFO, "- T_Integer: attr <%s>/%d, value %d", 1103cdfa2a7eSchristos keyword(atrv->attr), atrv->attr, atrv->value.i); 1104cdfa2a7eSchristos break; 1105cdfa2a7eSchristos default: 1106cdfa2a7eSchristos msyslog(LOG_INFO, "- Other: attr <%s>/%d, value ???", 1107cdfa2a7eSchristos keyword(atrv->attr), atrv->attr); 1108cdfa2a7eSchristos break; 1109cdfa2a7eSchristos 1110cdfa2a7eSchristos } 1111cdfa2a7eSchristos } 1112cdfa2a7eSchristos #endif 1113cdfa2a7eSchristos /**/ 1114abb0f93cSkardel } 1115abb0f93cSkardel 11162950cc38Schristos rule_node = HEAD_PFIFO(ptree->nic_rules); 11172950cc38Schristos for ( ; rule_node != NULL; rule_node = rule_node->link) { 1118abb0f93cSkardel fprintf(df, "interface %s %s\n", 1119abb0f93cSkardel keyword(rule_node->action), 1120abb0f93cSkardel (rule_node->match_class) 1121abb0f93cSkardel ? keyword(rule_node->match_class) 1122abb0f93cSkardel : rule_node->if_name); 1123abb0f93cSkardel } 1124abb0f93cSkardel 11252950cc38Schristos str_node = HEAD_PFIFO(ptree->phone); 11262950cc38Schristos if (str_node != NULL) { 1127abb0f93cSkardel fprintf(df, "phone"); 11282950cc38Schristos for ( ; str_node != NULL; str_node = str_node->link) 11292950cc38Schristos fprintf(df, " \"%s\"", str_node->s); 1130abb0f93cSkardel fprintf(df, "\n"); 1131abb0f93cSkardel } 1132abb0f93cSkardel 11332950cc38Schristos setv_node = HEAD_PFIFO(ptree->setvar); 11342950cc38Schristos for ( ; setv_node != NULL; setv_node = setv_node->link) { 11352950cc38Schristos s1 = quote_if_needed(setv_node->var); 1136abb0f93cSkardel s2 = quote_if_needed(setv_node->val); 11377476e6e4Schristos fprintf(df, "setvar %s = %s", s1, s2); 11382950cc38Schristos free(s1); 1139abb0f93cSkardel free(s2); 1140abb0f93cSkardel if (setv_node->isdefault) 1141abb0f93cSkardel fprintf(df, " default"); 1142abb0f93cSkardel fprintf(df, "\n"); 1143abb0f93cSkardel } 1144abb0f93cSkardel 11452950cc38Schristos i_n = HEAD_PFIFO(ptree->ttl); 11462950cc38Schristos if (i_n != NULL) { 1147abb0f93cSkardel fprintf(df, "ttl"); 11482950cc38Schristos for( ; i_n != NULL; i_n = i_n->link) 11492950cc38Schristos fprintf(df, " %d", i_n->i); 1150abb0f93cSkardel fprintf(df, "\n"); 1151abb0f93cSkardel } 1152abb0f93cSkardel 11532950cc38Schristos addr_opts = HEAD_PFIFO(ptree->trap); 11542950cc38Schristos for ( ; addr_opts != NULL; addr_opts = addr_opts->link) { 1155abb0f93cSkardel addr = addr_opts->addr; 1156abb0f93cSkardel fprintf(df, "trap %s", addr->address); 11572950cc38Schristos atrv = HEAD_PFIFO(addr_opts->options); 11582950cc38Schristos for ( ; atrv != NULL; atrv = atrv->link) { 1159abb0f93cSkardel switch (atrv->attr) { 11602950cc38Schristos #ifdef DEBUG 1161abb0f93cSkardel default: 1162abb0f93cSkardel fprintf(df, "\n# dump error:\n" 1163abb0f93cSkardel "# unknown trap token %d\n" 1164abb0f93cSkardel "trap %s", atrv->attr, 1165abb0f93cSkardel addr->address); 1166abb0f93cSkardel break; 11672950cc38Schristos #endif 1168abb0f93cSkardel case T_Port: 1169abb0f93cSkardel fprintf(df, " port %d", atrv->value.i); 1170abb0f93cSkardel break; 1171abb0f93cSkardel 1172abb0f93cSkardel case T_Interface: 11732950cc38Schristos fprintf(df, " interface %s", 11742950cc38Schristos atrv->value.s); 1175abb0f93cSkardel break; 1176abb0f93cSkardel } 1177abb0f93cSkardel } 11782950cc38Schristos fprintf(df, "\n"); 11792950cc38Schristos } 1180abb0f93cSkardel 11812950cc38Schristos counter_set = HEAD_PFIFO(ptree->reset_counters); 11822950cc38Schristos if (counter_set != NULL) { 11832950cc38Schristos fprintf(df, "reset"); 11842950cc38Schristos for ( ; counter_set != NULL; 11852950cc38Schristos counter_set = counter_set->link) 11862950cc38Schristos fprintf(df, " %s", keyword(counter_set->i)); 1187abb0f93cSkardel fprintf(df, "\n"); 1188abb0f93cSkardel } 1189abb0f93cSkardel 1190abb0f93cSkardel return 0; 1191abb0f93cSkardel } 1192abb0f93cSkardel #endif /* SAVECONFIG */ 1193abb0f93cSkardel 1194abb0f93cSkardel 11952950cc38Schristos /* generic fifo routines for structs linked by 1st member */ 11962950cc38Schristos void * 11972950cc38Schristos append_gen_fifo( 11982950cc38Schristos void *fifo, 11992950cc38Schristos void *entry 12002950cc38Schristos ) 12012950cc38Schristos { 12022950cc38Schristos gen_fifo *pf; 12032950cc38Schristos gen_node *pe; 12042950cc38Schristos 12052950cc38Schristos pf = fifo; 12062950cc38Schristos pe = entry; 12072950cc38Schristos if (NULL == pf) 12082950cc38Schristos pf = emalloc_zero(sizeof(*pf)); 12092950cc38Schristos else 12102950cc38Schristos CHECK_FIFO_CONSISTENCY(*pf); 12112950cc38Schristos if (pe != NULL) 12122950cc38Schristos LINK_FIFO(*pf, pe, link); 12132950cc38Schristos CHECK_FIFO_CONSISTENCY(*pf); 12142950cc38Schristos 12152950cc38Schristos return pf; 12162950cc38Schristos } 12172950cc38Schristos 12182950cc38Schristos 12192950cc38Schristos void * 12202950cc38Schristos concat_gen_fifos( 12212950cc38Schristos void *first, 12222950cc38Schristos void *second 12232950cc38Schristos ) 12242950cc38Schristos { 12252950cc38Schristos gen_fifo *pf1; 12262950cc38Schristos gen_fifo *pf2; 12272950cc38Schristos 12282950cc38Schristos pf1 = first; 12292950cc38Schristos pf2 = second; 12302950cc38Schristos if (NULL == pf1) 12312950cc38Schristos return pf2; 1232ea66d795Schristos if (NULL == pf2) 12332950cc38Schristos return pf1; 12342950cc38Schristos 12352950cc38Schristos CONCAT_FIFO(*pf1, *pf2, link); 12362950cc38Schristos free(pf2); 12372950cc38Schristos 12382950cc38Schristos return pf1; 12392950cc38Schristos } 12402950cc38Schristos 12414eea345dSchristos void* 12424eea345dSchristos destroy_gen_fifo( 12434eea345dSchristos void *fifo, 12444eea345dSchristos fifo_deleter func 12454eea345dSchristos ) 12464eea345dSchristos { 12474eea345dSchristos any_node * np = NULL; 12484eea345dSchristos any_node_fifo * pf1 = fifo; 12494eea345dSchristos 12504eea345dSchristos if (pf1 != NULL) { 12514eea345dSchristos if (!func) 12524eea345dSchristos func = free; 12534eea345dSchristos for (;;) { 12544eea345dSchristos UNLINK_FIFO(np, *pf1, link); 12554eea345dSchristos if (np == NULL) 12564eea345dSchristos break; 12574eea345dSchristos (*func)(np); 12584eea345dSchristos } 12594eea345dSchristos free(pf1); 12604eea345dSchristos } 12614eea345dSchristos return NULL; 12624eea345dSchristos } 12632950cc38Schristos 1264abb0f93cSkardel /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 1265abb0f93cSkardel * ----------------------------------------------- 1266abb0f93cSkardel */ 1267abb0f93cSkardel 12684eea345dSchristos void 12694eea345dSchristos destroy_attr_val( 12704eea345dSchristos attr_val * av 12714eea345dSchristos ) 12724eea345dSchristos { 12734eea345dSchristos if (av) { 12744eea345dSchristos if (T_String == av->type) 12754eea345dSchristos free(av->value.s); 12764eea345dSchristos free(av); 12774eea345dSchristos } 12784eea345dSchristos } 12794eea345dSchristos 12802950cc38Schristos attr_val * 1281abb0f93cSkardel create_attr_dval( 1282abb0f93cSkardel int attr, 1283abb0f93cSkardel double value 1284abb0f93cSkardel ) 1285abb0f93cSkardel { 12862950cc38Schristos attr_val *my_val; 1287abb0f93cSkardel 12882950cc38Schristos my_val = emalloc_zero(sizeof(*my_val)); 1289abb0f93cSkardel my_val->attr = attr; 1290abb0f93cSkardel my_val->value.d = value; 1291abb0f93cSkardel my_val->type = T_Double; 12922950cc38Schristos 1293abb0f93cSkardel return my_val; 1294abb0f93cSkardel } 1295abb0f93cSkardel 12962950cc38Schristos 12972950cc38Schristos attr_val * 1298abb0f93cSkardel create_attr_ival( 1299abb0f93cSkardel int attr, 1300abb0f93cSkardel int value 1301abb0f93cSkardel ) 1302abb0f93cSkardel { 13032950cc38Schristos attr_val *my_val; 1304abb0f93cSkardel 13052950cc38Schristos my_val = emalloc_zero(sizeof(*my_val)); 1306abb0f93cSkardel my_val->attr = attr; 1307abb0f93cSkardel my_val->value.i = value; 1308abb0f93cSkardel my_val->type = T_Integer; 13092950cc38Schristos 1310abb0f93cSkardel return my_val; 1311abb0f93cSkardel } 1312abb0f93cSkardel 13132950cc38Schristos 13142950cc38Schristos attr_val * 13152950cc38Schristos create_attr_uval( 13163123f114Skardel int attr, 13172950cc38Schristos u_int value 13183123f114Skardel ) 13193123f114Skardel { 13202950cc38Schristos attr_val *my_val; 13213123f114Skardel 13222950cc38Schristos my_val = emalloc_zero(sizeof(*my_val)); 13233123f114Skardel my_val->attr = attr; 13242950cc38Schristos my_val->value.u = value; 13252950cc38Schristos my_val->type = T_U_int; 13262950cc38Schristos 13273123f114Skardel return my_val; 13283123f114Skardel } 13293123f114Skardel 13302950cc38Schristos 13312950cc38Schristos attr_val * 1332cdfa2a7eSchristos create_attr_rval( 13332950cc38Schristos int attr, 13342950cc38Schristos int first, 13352950cc38Schristos int last 13362950cc38Schristos ) 13372950cc38Schristos { 13382950cc38Schristos attr_val *my_val; 13392950cc38Schristos 13402950cc38Schristos my_val = emalloc_zero(sizeof(*my_val)); 13412950cc38Schristos my_val->attr = attr; 13422950cc38Schristos my_val->value.r.first = first; 13432950cc38Schristos my_val->value.r.last = last; 13442950cc38Schristos my_val->type = T_Intrange; 13452950cc38Schristos 13462950cc38Schristos return my_val; 13472950cc38Schristos } 13482950cc38Schristos 13492950cc38Schristos 13502950cc38Schristos attr_val * 1351abb0f93cSkardel create_attr_sval( 1352abb0f93cSkardel int attr, 13532950cc38Schristos const char *s 1354abb0f93cSkardel ) 1355abb0f93cSkardel { 13562950cc38Schristos attr_val *my_val; 1357abb0f93cSkardel 13582950cc38Schristos my_val = emalloc_zero(sizeof(*my_val)); 1359abb0f93cSkardel my_val->attr = attr; 1360abb0f93cSkardel if (NULL == s) /* free() hates NULL */ 1361abb0f93cSkardel s = estrdup(""); 13627476e6e4Schristos my_val->value.s = _UC(s); 1363abb0f93cSkardel my_val->type = T_String; 13642950cc38Schristos 1365abb0f93cSkardel return my_val; 1366abb0f93cSkardel } 1367abb0f93cSkardel 1368abb0f93cSkardel 13692950cc38Schristos int_node * 13702950cc38Schristos create_int_node( 1371abb0f93cSkardel int val 1372abb0f93cSkardel ) 1373abb0f93cSkardel { 13742950cc38Schristos int_node *i_n; 1375abb0f93cSkardel 13762950cc38Schristos i_n = emalloc_zero(sizeof(*i_n)); 13772950cc38Schristos i_n->i = val; 13782950cc38Schristos 13792950cc38Schristos return i_n; 1380abb0f93cSkardel } 1381abb0f93cSkardel 13822950cc38Schristos 13832950cc38Schristos string_node * 13842950cc38Schristos create_string_node( 13852950cc38Schristos char *str 1386abb0f93cSkardel ) 1387abb0f93cSkardel { 13882950cc38Schristos string_node *sn; 1389abb0f93cSkardel 13902950cc38Schristos sn = emalloc_zero(sizeof(*sn)); 13912950cc38Schristos sn->s = str; 13922950cc38Schristos 13932950cc38Schristos return sn; 1394abb0f93cSkardel } 1395abb0f93cSkardel 1396abb0f93cSkardel 13972950cc38Schristos address_node * 1398abb0f93cSkardel create_address_node( 1399abb0f93cSkardel char * addr, 1400abb0f93cSkardel int type 1401abb0f93cSkardel ) 1402abb0f93cSkardel { 14032950cc38Schristos address_node *my_node; 1404abb0f93cSkardel 1405af12ab5eSchristos REQUIRE(NULL != addr); 1406af12ab5eSchristos REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type); 14072950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1408abb0f93cSkardel my_node->address = addr; 14092950cc38Schristos my_node->type = (u_short)type; 1410abb0f93cSkardel 1411abb0f93cSkardel return my_node; 1412abb0f93cSkardel } 1413abb0f93cSkardel 1414abb0f93cSkardel 1415abb0f93cSkardel void 1416abb0f93cSkardel destroy_address_node( 14172950cc38Schristos address_node *my_node 1418abb0f93cSkardel ) 1419abb0f93cSkardel { 14202950cc38Schristos if (NULL == my_node) 14212950cc38Schristos return; 1422af12ab5eSchristos REQUIRE(NULL != my_node->address); 1423abb0f93cSkardel 1424abb0f93cSkardel free(my_node->address); 14252950cc38Schristos free(my_node); 1426abb0f93cSkardel } 1427abb0f93cSkardel 1428abb0f93cSkardel 14292950cc38Schristos peer_node * 1430abb0f93cSkardel create_peer_node( 1431abb0f93cSkardel int hmode, 14322950cc38Schristos address_node * addr, 14332950cc38Schristos attr_val_fifo * options 1434abb0f93cSkardel ) 1435abb0f93cSkardel { 14362950cc38Schristos peer_node *my_node; 14372950cc38Schristos attr_val *option; 1438abb0f93cSkardel int freenode; 1439abb0f93cSkardel int errflag = 0; 1440abb0f93cSkardel 14412950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1442abb0f93cSkardel 1443abb0f93cSkardel /* Initialize node values to default */ 1444abb0f93cSkardel my_node->peerversion = NTP_VERSION; 1445abb0f93cSkardel 1446abb0f93cSkardel /* Now set the node to the read values */ 1447abb0f93cSkardel my_node->host_mode = hmode; 1448abb0f93cSkardel my_node->addr = addr; 1449abb0f93cSkardel 1450abb0f93cSkardel /* 14512950cc38Schristos * the options FIFO mixes items that will be saved in the 1452abb0f93cSkardel * peer_node as explicit members, such as minpoll, and 14532950cc38Schristos * those that are moved intact to the peer_node's peerflags 14542950cc38Schristos * FIFO. The options FIFO is consumed and reclaimed here. 1455abb0f93cSkardel */ 1456abb0f93cSkardel 14572950cc38Schristos if (options != NULL) 14582950cc38Schristos CHECK_FIFO_CONSISTENCY(*options); 14592950cc38Schristos while (options != NULL) { 14602950cc38Schristos UNLINK_FIFO(option, *options, link); 14612950cc38Schristos if (NULL == option) { 14622950cc38Schristos free(options); 14632950cc38Schristos break; 14642950cc38Schristos } 1465abb0f93cSkardel 1466abb0f93cSkardel freenode = 1; 1467abb0f93cSkardel /* Check the kind of option being set */ 1468abb0f93cSkardel switch (option->attr) { 1469abb0f93cSkardel 1470abb0f93cSkardel case T_Flag: 14712950cc38Schristos APPEND_G_FIFO(my_node->peerflags, option); 1472abb0f93cSkardel freenode = 0; 1473abb0f93cSkardel break; 1474abb0f93cSkardel 1475abb0f93cSkardel case T_Minpoll: 14762950cc38Schristos if (option->value.i < NTP_MINPOLL || 14772950cc38Schristos option->value.i > UCHAR_MAX) { 1478abb0f93cSkardel msyslog(LOG_INFO, 14792950cc38Schristos "minpoll: provided value (%d) is out of range [%d-%d])", 14802950cc38Schristos option->value.i, NTP_MINPOLL, 14812950cc38Schristos UCHAR_MAX); 1482abb0f93cSkardel my_node->minpoll = NTP_MINPOLL; 14832950cc38Schristos } else { 14842950cc38Schristos my_node->minpoll = 14852950cc38Schristos (u_char)option->value.u; 1486abb0f93cSkardel } 1487abb0f93cSkardel break; 1488abb0f93cSkardel 1489abb0f93cSkardel case T_Maxpoll: 14902950cc38Schristos if (option->value.i < 0 || 14912950cc38Schristos option->value.i > NTP_MAXPOLL) { 1492abb0f93cSkardel msyslog(LOG_INFO, 14932950cc38Schristos "maxpoll: provided value (%d) is out of range [0-%d])", 1494abb0f93cSkardel option->value.i, NTP_MAXPOLL); 1495abb0f93cSkardel my_node->maxpoll = NTP_MAXPOLL; 14962950cc38Schristos } else { 14972950cc38Schristos my_node->maxpoll = 14982950cc38Schristos (u_char)option->value.u; 1499abb0f93cSkardel } 1500abb0f93cSkardel break; 1501abb0f93cSkardel 1502abb0f93cSkardel case T_Ttl: 1503ccc794f0Schristos if (is_refclk_addr(addr)) { 1504ccc794f0Schristos msyslog(LOG_ERR, "'ttl' does not apply for refclocks"); 1505ccc794f0Schristos errflag = 1; 1506ccc794f0Schristos } else if (option->value.u >= MAX_TTL) { 1507abb0f93cSkardel msyslog(LOG_ERR, "ttl: invalid argument"); 1508abb0f93cSkardel errflag = 1; 15092950cc38Schristos } else { 15102950cc38Schristos my_node->ttl = (u_char)option->value.u; 1511abb0f93cSkardel } 1512abb0f93cSkardel break; 1513abb0f93cSkardel 1514abb0f93cSkardel case T_Mode: 1515ccc794f0Schristos if (is_refclk_addr(addr)) { 15162950cc38Schristos my_node->ttl = option->value.u; 1517ccc794f0Schristos } else { 1518ccc794f0Schristos msyslog(LOG_ERR, "'mode' does not apply for network peers"); 1519ccc794f0Schristos errflag = 1; 1520ccc794f0Schristos } 1521abb0f93cSkardel break; 1522abb0f93cSkardel 1523abb0f93cSkardel case T_Key: 15242950cc38Schristos if (option->value.u >= KEYID_T_MAX) { 15252950cc38Schristos msyslog(LOG_ERR, "key: invalid argument"); 15262950cc38Schristos errflag = 1; 15272950cc38Schristos } else { 15282950cc38Schristos my_node->peerkey = 15292950cc38Schristos (keyid_t)option->value.u; 15302950cc38Schristos } 1531abb0f93cSkardel break; 1532abb0f93cSkardel 1533abb0f93cSkardel case T_Version: 15342950cc38Schristos if (option->value.u >= UCHAR_MAX) { 15352950cc38Schristos msyslog(LOG_ERR, "version: invalid argument"); 15362950cc38Schristos errflag = 1; 15372950cc38Schristos } else { 15382950cc38Schristos my_node->peerversion = 15392950cc38Schristos (u_char)option->value.u; 15402950cc38Schristos } 1541abb0f93cSkardel break; 1542abb0f93cSkardel 15432950cc38Schristos case T_Ident: 15442950cc38Schristos my_node->group = option->value.s; 1545abb0f93cSkardel break; 1546abb0f93cSkardel 1547abb0f93cSkardel default: 1548abb0f93cSkardel msyslog(LOG_ERR, 1549abb0f93cSkardel "Unknown peer/server option token %s", 1550abb0f93cSkardel token_name(option->attr)); 1551abb0f93cSkardel errflag = 1; 1552abb0f93cSkardel } 1553abb0f93cSkardel if (freenode) 15542950cc38Schristos free(option); 1555abb0f93cSkardel } 1556abb0f93cSkardel 1557abb0f93cSkardel /* Check if errors were reported. If yes, ignore the node */ 1558abb0f93cSkardel if (errflag) { 15592950cc38Schristos free(my_node); 1560abb0f93cSkardel my_node = NULL; 1561abb0f93cSkardel } 15622950cc38Schristos 1563abb0f93cSkardel return my_node; 1564abb0f93cSkardel } 1565abb0f93cSkardel 1566abb0f93cSkardel 15672950cc38Schristos unpeer_node * 1568abb0f93cSkardel create_unpeer_node( 15692950cc38Schristos address_node *addr 1570abb0f93cSkardel ) 1571abb0f93cSkardel { 15722950cc38Schristos unpeer_node * my_node; 1573ccc794f0Schristos u_long u; 1574ccc794f0Schristos const u_char * pch; 1575abb0f93cSkardel 15762950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1577abb0f93cSkardel 1578abb0f93cSkardel /* 1579abb0f93cSkardel * From the parser's perspective an association ID fits into 1580abb0f93cSkardel * its generic T_String definition of a name/address "address". 1581abb0f93cSkardel * We treat all valid 16-bit numbers as association IDs. 1582abb0f93cSkardel */ 1583ccc794f0Schristos for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) { 1584ccc794f0Schristos /* accumulate with overflow retention */ 1585ccc794f0Schristos u = (10 * u + *pch - '0') | (u & 0xFF000000u); 1586ccc794f0Schristos } 1587abb0f93cSkardel 1588ccc794f0Schristos if (!*pch && u <= ASSOCID_MAX) { 15892950cc38Schristos my_node->assocID = (associd_t)u; 1590abb0f93cSkardel my_node->addr = NULL; 1591ccc794f0Schristos destroy_address_node(addr); 1592abb0f93cSkardel } else { 1593abb0f93cSkardel my_node->assocID = 0; 1594abb0f93cSkardel my_node->addr = addr; 1595abb0f93cSkardel } 1596abb0f93cSkardel 1597abb0f93cSkardel return my_node; 1598abb0f93cSkardel } 1599abb0f93cSkardel 16002950cc38Schristos filegen_node * 1601abb0f93cSkardel create_filegen_node( 1602abb0f93cSkardel int filegen_token, 16032950cc38Schristos attr_val_fifo * options 1604abb0f93cSkardel ) 1605abb0f93cSkardel { 16062950cc38Schristos filegen_node *my_node; 1607abb0f93cSkardel 16082950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1609abb0f93cSkardel my_node->filegen_token = filegen_token; 1610abb0f93cSkardel my_node->options = options; 1611abb0f93cSkardel 1612abb0f93cSkardel return my_node; 1613abb0f93cSkardel } 1614abb0f93cSkardel 1615abb0f93cSkardel 16162950cc38Schristos restrict_node * 1617abb0f93cSkardel create_restrict_node( 16182950cc38Schristos address_node * addr, 16192950cc38Schristos address_node * mask, 16204eea345dSchristos short ippeerlimit, 1621cdfa2a7eSchristos attr_val_fifo * flag_tok_fifo, 1622*eabc0478Schristos int/*BOOL*/ remove, 1623*eabc0478Schristos int nline, 1624*eabc0478Schristos int ncol 1625abb0f93cSkardel ) 1626abb0f93cSkardel { 16272950cc38Schristos restrict_node *my_node; 1628abb0f93cSkardel 16292950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1630abb0f93cSkardel my_node->addr = addr; 1631abb0f93cSkardel my_node->mask = mask; 16324eea345dSchristos my_node->ippeerlimit = ippeerlimit; 16334eea345dSchristos my_node->flag_tok_fifo = flag_tok_fifo; 1634*eabc0478Schristos my_node->remove = remove; 1635cdfa2a7eSchristos my_node->line_no = nline; 1636*eabc0478Schristos my_node->column = ncol; 1637abb0f93cSkardel 1638abb0f93cSkardel return my_node; 1639abb0f93cSkardel } 1640abb0f93cSkardel 16412950cc38Schristos 16422950cc38Schristos static void 1643abb0f93cSkardel destroy_restrict_node( 16442950cc38Schristos restrict_node *my_node 1645abb0f93cSkardel ) 1646abb0f93cSkardel { 1647abb0f93cSkardel /* With great care, free all the memory occupied by 1648abb0f93cSkardel * the restrict node 1649abb0f93cSkardel */ 1650abb0f93cSkardel destroy_address_node(my_node->addr); 1651abb0f93cSkardel destroy_address_node(my_node->mask); 1652cdfa2a7eSchristos destroy_attr_val_fifo(my_node->flag_tok_fifo); 16532950cc38Schristos free(my_node); 1654abb0f93cSkardel } 1655abb0f93cSkardel 1656abb0f93cSkardel 16572950cc38Schristos static void 16582950cc38Schristos destroy_int_fifo( 16592950cc38Schristos int_fifo * fifo 16602950cc38Schristos ) 16612950cc38Schristos { 16622950cc38Schristos int_node * i_n; 16632950cc38Schristos 16642950cc38Schristos if (fifo != NULL) { 1665ea66d795Schristos for (;;) { 16662950cc38Schristos UNLINK_FIFO(i_n, *fifo, link); 1667ea66d795Schristos if (i_n == NULL) 1668ea66d795Schristos break; 16692950cc38Schristos free(i_n); 1670ea66d795Schristos } 16712950cc38Schristos free(fifo); 16722950cc38Schristos } 16732950cc38Schristos } 16742950cc38Schristos 16752950cc38Schristos 16762950cc38Schristos static void 16772950cc38Schristos destroy_string_fifo( 16782950cc38Schristos string_fifo * fifo 16792950cc38Schristos ) 16802950cc38Schristos { 16812950cc38Schristos string_node * sn; 16822950cc38Schristos 16832950cc38Schristos if (fifo != NULL) { 1684ea66d795Schristos for (;;) { 16852950cc38Schristos UNLINK_FIFO(sn, *fifo, link); 1686ea66d795Schristos if (sn == NULL) 1687ea66d795Schristos break; 16882950cc38Schristos free(sn->s); 16892950cc38Schristos free(sn); 16902950cc38Schristos } 16912950cc38Schristos free(fifo); 16922950cc38Schristos } 16932950cc38Schristos } 16942950cc38Schristos 16952950cc38Schristos 16962950cc38Schristos static void 16972950cc38Schristos destroy_attr_val_fifo( 16982950cc38Schristos attr_val_fifo * av_fifo 16992950cc38Schristos ) 17002950cc38Schristos { 17012950cc38Schristos attr_val * av; 17022950cc38Schristos 17032950cc38Schristos if (av_fifo != NULL) { 1704ea66d795Schristos for (;;) { 17052950cc38Schristos UNLINK_FIFO(av, *av_fifo, link); 1706ea66d795Schristos if (av == NULL) 1707ea66d795Schristos break; 17084eea345dSchristos destroy_attr_val(av); 17092950cc38Schristos } 17102950cc38Schristos free(av_fifo); 17112950cc38Schristos } 17122950cc38Schristos } 17132950cc38Schristos 17142950cc38Schristos 17152950cc38Schristos static void 17162950cc38Schristos destroy_filegen_fifo( 17172950cc38Schristos filegen_fifo * fifo 17182950cc38Schristos ) 17192950cc38Schristos { 17202950cc38Schristos filegen_node * fg; 17212950cc38Schristos 17222950cc38Schristos if (fifo != NULL) { 1723ea66d795Schristos for (;;) { 17242950cc38Schristos UNLINK_FIFO(fg, *fifo, link); 1725ea66d795Schristos if (fg == NULL) 1726ea66d795Schristos break; 17272950cc38Schristos destroy_attr_val_fifo(fg->options); 17282950cc38Schristos free(fg); 17292950cc38Schristos } 17302950cc38Schristos free(fifo); 17312950cc38Schristos } 17322950cc38Schristos } 17332950cc38Schristos 17342950cc38Schristos 17352950cc38Schristos static void 17362950cc38Schristos destroy_restrict_fifo( 17372950cc38Schristos restrict_fifo * fifo 17382950cc38Schristos ) 17392950cc38Schristos { 17402950cc38Schristos restrict_node * rn; 17412950cc38Schristos 17422950cc38Schristos if (fifo != NULL) { 1743ea66d795Schristos for (;;) { 17442950cc38Schristos UNLINK_FIFO(rn, *fifo, link); 1745ea66d795Schristos if (rn == NULL) 1746ea66d795Schristos break; 17472950cc38Schristos destroy_restrict_node(rn); 1748ea66d795Schristos } 17492950cc38Schristos free(fifo); 17502950cc38Schristos } 17512950cc38Schristos } 17522950cc38Schristos 17532950cc38Schristos 17542950cc38Schristos static void 17552950cc38Schristos destroy_setvar_fifo( 17562950cc38Schristos setvar_fifo * fifo 17572950cc38Schristos ) 17582950cc38Schristos { 17592950cc38Schristos setvar_node * sv; 17602950cc38Schristos 17612950cc38Schristos if (fifo != NULL) { 1762ea66d795Schristos for (;;) { 17632950cc38Schristos UNLINK_FIFO(sv, *fifo, link); 1764ea66d795Schristos if (sv == NULL) 1765ea66d795Schristos break; 17662950cc38Schristos free(sv->var); 17672950cc38Schristos free(sv->val); 17682950cc38Schristos free(sv); 17692950cc38Schristos } 17702950cc38Schristos free(fifo); 17712950cc38Schristos } 17722950cc38Schristos } 17732950cc38Schristos 17742950cc38Schristos 17752950cc38Schristos static void 17762950cc38Schristos destroy_addr_opts_fifo( 17772950cc38Schristos addr_opts_fifo * fifo 17782950cc38Schristos ) 17792950cc38Schristos { 17802950cc38Schristos addr_opts_node * aon; 17812950cc38Schristos 17822950cc38Schristos if (fifo != NULL) { 1783ea66d795Schristos for (;;) { 17842950cc38Schristos UNLINK_FIFO(aon, *fifo, link); 1785ea66d795Schristos if (aon == NULL) 1786ea66d795Schristos break; 17872950cc38Schristos destroy_address_node(aon->addr); 17882950cc38Schristos destroy_attr_val_fifo(aon->options); 17892950cc38Schristos free(aon); 17902950cc38Schristos } 17912950cc38Schristos free(fifo); 17922950cc38Schristos } 17932950cc38Schristos } 17942950cc38Schristos 17952950cc38Schristos 17962950cc38Schristos setvar_node * 1797abb0f93cSkardel create_setvar_node( 1798abb0f93cSkardel char * var, 1799abb0f93cSkardel char * val, 1800abb0f93cSkardel int isdefault 1801abb0f93cSkardel ) 1802abb0f93cSkardel { 18032950cc38Schristos setvar_node * my_node; 1804abb0f93cSkardel char * pch; 1805abb0f93cSkardel 1806abb0f93cSkardel /* do not allow = in the variable name */ 18072950cc38Schristos pch = strchr(var, '='); 18082950cc38Schristos if (NULL != pch) 1809abb0f93cSkardel *pch = '\0'; 1810abb0f93cSkardel 1811abb0f93cSkardel /* Now store the string into a setvar_node */ 18122950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1813abb0f93cSkardel my_node->var = var; 1814abb0f93cSkardel my_node->val = val; 1815abb0f93cSkardel my_node->isdefault = isdefault; 1816abb0f93cSkardel 1817abb0f93cSkardel return my_node; 1818abb0f93cSkardel } 1819abb0f93cSkardel 1820abb0f93cSkardel 1821abb0f93cSkardel nic_rule_node * 1822abb0f93cSkardel create_nic_rule_node( 1823abb0f93cSkardel int match_class, 1824abb0f93cSkardel char *if_name, /* interface name or numeric address */ 1825abb0f93cSkardel int action 1826abb0f93cSkardel ) 1827abb0f93cSkardel { 1828abb0f93cSkardel nic_rule_node *my_node; 1829abb0f93cSkardel 1830af12ab5eSchristos REQUIRE(match_class != 0 || if_name != NULL); 1831abb0f93cSkardel 18322950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1833abb0f93cSkardel my_node->match_class = match_class; 1834abb0f93cSkardel my_node->if_name = if_name; 1835abb0f93cSkardel my_node->action = action; 1836abb0f93cSkardel 1837abb0f93cSkardel return my_node; 1838abb0f93cSkardel } 1839abb0f93cSkardel 1840abb0f93cSkardel 18412950cc38Schristos addr_opts_node * 1842abb0f93cSkardel create_addr_opts_node( 18432950cc38Schristos address_node * addr, 18442950cc38Schristos attr_val_fifo * options 1845abb0f93cSkardel ) 1846abb0f93cSkardel { 18472950cc38Schristos addr_opts_node *my_node; 1848abb0f93cSkardel 18492950cc38Schristos my_node = emalloc_zero(sizeof(*my_node)); 1850abb0f93cSkardel my_node->addr = addr; 1851abb0f93cSkardel my_node->options = options; 18522950cc38Schristos 1853abb0f93cSkardel return my_node; 1854abb0f93cSkardel } 1855abb0f93cSkardel 18562950cc38Schristos 1857ea66d795Schristos #ifdef SIM 1858abb0f93cSkardel script_info * 1859abb0f93cSkardel create_sim_script_info( 1860abb0f93cSkardel double duration, 18612950cc38Schristos attr_val_fifo * script_queue 1862abb0f93cSkardel ) 1863abb0f93cSkardel { 1864abb0f93cSkardel script_info *my_info; 18652950cc38Schristos attr_val *my_attr_val; 1866abb0f93cSkardel 18672950cc38Schristos my_info = emalloc_zero(sizeof(*my_info)); 1868abb0f93cSkardel 1869abb0f93cSkardel /* Initialize Script Info with default values*/ 1870abb0f93cSkardel my_info->duration = duration; 1871abb0f93cSkardel my_info->prop_delay = NET_DLY; 1872abb0f93cSkardel my_info->proc_delay = PROC_DLY; 1873abb0f93cSkardel 1874abb0f93cSkardel /* Traverse the script_queue and fill out non-default values */ 18752950cc38Schristos 18762950cc38Schristos for (my_attr_val = HEAD_PFIFO(script_queue); 18772950cc38Schristos my_attr_val != NULL; 18782950cc38Schristos my_attr_val = my_attr_val->link) { 18792950cc38Schristos 1880abb0f93cSkardel /* Set the desired value */ 1881abb0f93cSkardel switch (my_attr_val->attr) { 1882abb0f93cSkardel 1883abb0f93cSkardel case T_Freq_Offset: 1884abb0f93cSkardel my_info->freq_offset = my_attr_val->value.d; 1885abb0f93cSkardel break; 1886abb0f93cSkardel 1887abb0f93cSkardel case T_Wander: 1888abb0f93cSkardel my_info->wander = my_attr_val->value.d; 1889abb0f93cSkardel break; 1890abb0f93cSkardel 1891abb0f93cSkardel case T_Jitter: 1892abb0f93cSkardel my_info->jitter = my_attr_val->value.d; 1893abb0f93cSkardel break; 1894abb0f93cSkardel 1895abb0f93cSkardel case T_Prop_Delay: 1896abb0f93cSkardel my_info->prop_delay = my_attr_val->value.d; 1897abb0f93cSkardel break; 1898abb0f93cSkardel 1899abb0f93cSkardel case T_Proc_Delay: 1900abb0f93cSkardel my_info->proc_delay = my_attr_val->value.d; 1901abb0f93cSkardel break; 1902abb0f93cSkardel 1903abb0f93cSkardel default: 19042950cc38Schristos msyslog(LOG_ERR, "Unknown script token %d", 1905abb0f93cSkardel my_attr_val->attr); 1906abb0f93cSkardel } 1907abb0f93cSkardel } 1908abb0f93cSkardel 1909abb0f93cSkardel return my_info; 1910abb0f93cSkardel } 1911ea66d795Schristos #endif /* SIM */ 1912abb0f93cSkardel 19132950cc38Schristos 19142950cc38Schristos #ifdef SIM 19152950cc38Schristos static sockaddr_u * 19162950cc38Schristos get_next_address( 19172950cc38Schristos address_node *addr 1918abb0f93cSkardel ) 1919abb0f93cSkardel { 19202950cc38Schristos const char addr_prefix[] = "192.168.0."; 19212950cc38Schristos static int curr_addr_num = 1; 19222950cc38Schristos #define ADDR_LENGTH 16 + 1 /* room for 192.168.1.255 */ 19232950cc38Schristos char addr_string[ADDR_LENGTH]; 19242950cc38Schristos sockaddr_u *final_addr; 19252950cc38Schristos struct addrinfo *ptr; 19262950cc38Schristos int gai_err; 1927abb0f93cSkardel 19282950cc38Schristos final_addr = emalloc(sizeof(*final_addr)); 1929abb0f93cSkardel 19302950cc38Schristos if (addr->type == T_String) { 19312950cc38Schristos snprintf(addr_string, sizeof(addr_string), "%s%d", 19322950cc38Schristos addr_prefix, curr_addr_num++); 19332950cc38Schristos printf("Selecting ip address %s for hostname %s\n", 19342950cc38Schristos addr_string, addr->address); 19352950cc38Schristos gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr); 19362950cc38Schristos } else { 19372950cc38Schristos gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr); 19382950cc38Schristos } 19392950cc38Schristos 19402950cc38Schristos if (gai_err) { 19412950cc38Schristos fprintf(stderr, "ERROR!! Could not get a new address\n"); 19422950cc38Schristos exit(1); 19432950cc38Schristos } 19442950cc38Schristos memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen); 19452950cc38Schristos fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", 19462950cc38Schristos stoa(final_addr)); 19472950cc38Schristos freeaddrinfo(ptr); 19482950cc38Schristos 19492950cc38Schristos return final_addr; 19502950cc38Schristos } 19512950cc38Schristos #endif /* SIM */ 19522950cc38Schristos 19532950cc38Schristos 1954ea66d795Schristos #ifdef SIM 19552950cc38Schristos server_info * 19562950cc38Schristos create_sim_server( 19572950cc38Schristos address_node * addr, 19582950cc38Schristos double server_offset, 19592950cc38Schristos script_info_fifo * script 19602950cc38Schristos ) 19612950cc38Schristos { 19622950cc38Schristos server_info *my_info; 19632950cc38Schristos 19642950cc38Schristos my_info = emalloc_zero(sizeof(*my_info)); 19652950cc38Schristos my_info->server_time = server_offset; 19662950cc38Schristos my_info->addr = get_next_address(addr); 19672950cc38Schristos my_info->script = script; 19682950cc38Schristos UNLINK_FIFO(my_info->curr_script, *my_info->script, link); 19692950cc38Schristos 19702950cc38Schristos return my_info; 19712950cc38Schristos } 1972ea66d795Schristos #endif /* SIM */ 19732950cc38Schristos 19742950cc38Schristos sim_node * 19752950cc38Schristos create_sim_node( 19762950cc38Schristos attr_val_fifo * init_opts, 19772950cc38Schristos server_info_fifo * servers 19782950cc38Schristos ) 19792950cc38Schristos { 19802950cc38Schristos sim_node *my_node; 19812950cc38Schristos 19822950cc38Schristos my_node = emalloc(sizeof(*my_node)); 1983abb0f93cSkardel my_node->init_opts = init_opts; 1984abb0f93cSkardel my_node->servers = servers; 19852950cc38Schristos 1986abb0f93cSkardel return my_node; 1987abb0f93cSkardel } 1988abb0f93cSkardel 1989abb0f93cSkardel 1990abb0f93cSkardel 1991abb0f93cSkardel 1992abb0f93cSkardel /* FUNCTIONS FOR PERFORMING THE CONFIGURATION 1993abb0f93cSkardel * ------------------------------------------ 1994abb0f93cSkardel */ 1995abb0f93cSkardel 19962950cc38Schristos #ifndef SIM 1997abb0f93cSkardel static void 1998abb0f93cSkardel config_other_modes( 19992950cc38Schristos config_tree * ptree 2000abb0f93cSkardel ) 2001abb0f93cSkardel { 2002abb0f93cSkardel sockaddr_u addr_sock; 20032950cc38Schristos address_node * addr_node; 2004abb0f93cSkardel 2005abb0f93cSkardel if (ptree->broadcastclient) 20062950cc38Schristos proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 20072950cc38Schristos 0., NULL); 2008abb0f93cSkardel 20092950cc38Schristos addr_node = HEAD_PFIFO(ptree->manycastserver); 20102950cc38Schristos while (addr_node != NULL) { 20113123f114Skardel ZERO_SOCK(&addr_sock); 20122950cc38Schristos AF(&addr_sock) = addr_node->type; 20132950cc38Schristos if (1 == getnetnum(addr_node->address, &addr_sock, 1, 20142950cc38Schristos t_UNK)) { 20152950cc38Schristos proto_config(PROTO_MULTICAST_ADD, 20162950cc38Schristos 0, 0., &addr_sock); 2017abb0f93cSkardel sys_manycastserver = 1; 2018abb0f93cSkardel } 20192950cc38Schristos addr_node = addr_node->link; 20202950cc38Schristos } 2021abb0f93cSkardel 2022abb0f93cSkardel /* Configure the multicast clients */ 20232950cc38Schristos addr_node = HEAD_PFIFO(ptree->multicastclient); 2024abb0f93cSkardel if (addr_node != NULL) { 2025abb0f93cSkardel do { 20263123f114Skardel ZERO_SOCK(&addr_sock); 20272950cc38Schristos AF(&addr_sock) = addr_node->type; 20282950cc38Schristos if (1 == getnetnum(addr_node->address, 20292950cc38Schristos &addr_sock, 1, t_UNK)) { 20302950cc38Schristos proto_config(PROTO_MULTICAST_ADD, 0, 0., 20312950cc38Schristos &addr_sock); 20322950cc38Schristos } 20332950cc38Schristos addr_node = addr_node->link; 2034abb0f93cSkardel } while (addr_node != NULL); 2035abb0f93cSkardel proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL); 2036abb0f93cSkardel } 2037abb0f93cSkardel } 20382950cc38Schristos #endif /* !SIM */ 2039abb0f93cSkardel 2040abb0f93cSkardel 2041abb0f93cSkardel #ifdef FREE_CFG_T 2042abb0f93cSkardel static void 20432950cc38Schristos destroy_address_fifo( 20442950cc38Schristos address_fifo * pfifo 2045abb0f93cSkardel ) 2046abb0f93cSkardel { 20472950cc38Schristos address_node * addr_node; 2048abb0f93cSkardel 20492950cc38Schristos if (pfifo != NULL) { 2050ea66d795Schristos for (;;) { 20512950cc38Schristos UNLINK_FIFO(addr_node, *pfifo, link); 2052ea66d795Schristos if (addr_node == NULL) 2053ea66d795Schristos break; 2054abb0f93cSkardel destroy_address_node(addr_node); 2055ea66d795Schristos } 20562950cc38Schristos free(pfifo); 20572950cc38Schristos } 20582950cc38Schristos } 2059abb0f93cSkardel 20602950cc38Schristos 20612950cc38Schristos static void 20622950cc38Schristos free_config_other_modes( 20632950cc38Schristos config_tree *ptree 20642950cc38Schristos ) 20652950cc38Schristos { 20662950cc38Schristos FREE_ADDRESS_FIFO(ptree->manycastserver); 20672950cc38Schristos FREE_ADDRESS_FIFO(ptree->multicastclient); 2068abb0f93cSkardel } 2069abb0f93cSkardel #endif /* FREE_CFG_T */ 2070abb0f93cSkardel 2071abb0f93cSkardel 20722950cc38Schristos #ifndef SIM 2073abb0f93cSkardel static void 2074abb0f93cSkardel config_auth( 20752950cc38Schristos config_tree *ptree 2076abb0f93cSkardel ) 2077abb0f93cSkardel { 20782950cc38Schristos attr_val * my_val; 20792950cc38Schristos int first; 20802950cc38Schristos int last; 20812950cc38Schristos int i; 20822950cc38Schristos int count; 20832950cc38Schristos #ifdef AUTOKEY 2084abb0f93cSkardel int item; 2085abb0f93cSkardel #endif 2086abb0f93cSkardel 2087abb0f93cSkardel /* Crypto Command */ 20882950cc38Schristos #ifdef AUTOKEY 20892950cc38Schristos my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list); 20902950cc38Schristos for (; my_val != NULL; my_val = my_val->link) { 2091abb0f93cSkardel switch (my_val->attr) { 2092abb0f93cSkardel 2093abb0f93cSkardel default: 2094ccc794f0Schristos fatal_error("config_auth: attr-token=%d", my_val->attr); 2095abb0f93cSkardel 2096abb0f93cSkardel case T_Host: 2097abb0f93cSkardel item = CRYPTO_CONF_PRIV; 2098abb0f93cSkardel break; 2099abb0f93cSkardel 2100abb0f93cSkardel case T_Ident: 2101abb0f93cSkardel item = CRYPTO_CONF_IDENT; 2102abb0f93cSkardel break; 2103abb0f93cSkardel 2104abb0f93cSkardel case T_Pw: 2105abb0f93cSkardel item = CRYPTO_CONF_PW; 2106abb0f93cSkardel break; 2107abb0f93cSkardel 2108abb0f93cSkardel case T_Randfile: 2109abb0f93cSkardel item = CRYPTO_CONF_RAND; 2110abb0f93cSkardel break; 2111abb0f93cSkardel 2112abb0f93cSkardel case T_Digest: 2113abb0f93cSkardel item = CRYPTO_CONF_NID; 2114abb0f93cSkardel break; 2115abb0f93cSkardel } 2116abb0f93cSkardel crypto_config(item, my_val->value.s); 2117abb0f93cSkardel } 21182950cc38Schristos #endif /* AUTOKEY */ 2119abb0f93cSkardel 2120abb0f93cSkardel /* Keysdir Command */ 2121abb0f93cSkardel if (ptree->auth.keysdir) { 2122abb0f93cSkardel if (keysdir != default_keysdir) 2123abb0f93cSkardel free(keysdir); 2124abb0f93cSkardel keysdir = estrdup(ptree->auth.keysdir); 2125abb0f93cSkardel } 2126abb0f93cSkardel 2127abb0f93cSkardel 2128abb0f93cSkardel /* ntp_signd_socket Command */ 2129abb0f93cSkardel if (ptree->auth.ntp_signd_socket) { 2130abb0f93cSkardel if (ntp_signd_socket != default_ntp_signd_socket) 2131abb0f93cSkardel free(ntp_signd_socket); 2132abb0f93cSkardel ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket); 2133abb0f93cSkardel } 2134abb0f93cSkardel 21352950cc38Schristos #ifdef AUTOKEY 2136abb0f93cSkardel if (ptree->auth.cryptosw && !cryptosw) { 2137abb0f93cSkardel crypto_setup(); 2138abb0f93cSkardel cryptosw = 1; 2139abb0f93cSkardel } 21402950cc38Schristos #endif /* AUTOKEY */ 21412950cc38Schristos 21422950cc38Schristos /* 21432950cc38Schristos * Count the number of trusted keys to preallocate storage and 21442950cc38Schristos * size the hash table. 21452950cc38Schristos */ 21462950cc38Schristos count = 0; 21472950cc38Schristos my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 21482950cc38Schristos for (; my_val != NULL; my_val = my_val->link) { 21492950cc38Schristos if (T_Integer == my_val->type) { 21502950cc38Schristos first = my_val->value.i; 21512950cc38Schristos if (first > 1 && first <= NTP_MAXKEY) 21522950cc38Schristos count++; 21532950cc38Schristos } else { 21542950cc38Schristos REQUIRE(T_Intrange == my_val->type); 21552950cc38Schristos first = my_val->value.r.first; 21562950cc38Schristos last = my_val->value.r.last; 21572950cc38Schristos if (!(first > last || first < 1 || 21582950cc38Schristos last > NTP_MAXKEY)) { 21592950cc38Schristos count += 1 + last - first; 21602950cc38Schristos } 21612950cc38Schristos } 21622950cc38Schristos } 21632950cc38Schristos auth_prealloc_symkeys(count); 2164abb0f93cSkardel 2165abb0f93cSkardel /* Keys Command */ 2166abb0f93cSkardel if (ptree->auth.keys) 2167abb0f93cSkardel getauthkeys(ptree->auth.keys); 2168abb0f93cSkardel 2169abb0f93cSkardel /* Control Key Command */ 2170abb0f93cSkardel if (ptree->auth.control_key) 2171abb0f93cSkardel ctl_auth_keyid = (keyid_t)ptree->auth.control_key; 2172abb0f93cSkardel 2173abb0f93cSkardel /* Requested Key Command */ 2174abb0f93cSkardel if (ptree->auth.request_key) { 2175abb0f93cSkardel DPRINTF(4, ("set info_auth_keyid to %08lx\n", 2176abb0f93cSkardel (u_long) ptree->auth.request_key)); 2177abb0f93cSkardel info_auth_keyid = (keyid_t)ptree->auth.request_key; 2178abb0f93cSkardel } 2179abb0f93cSkardel 2180abb0f93cSkardel /* Trusted Key Command */ 21812950cc38Schristos my_val = HEAD_PFIFO(ptree->auth.trusted_key_list); 21822950cc38Schristos for (; my_val != NULL; my_val = my_val->link) { 21832950cc38Schristos if (T_Integer == my_val->type) { 21842950cc38Schristos first = my_val->value.i; 21852950cc38Schristos if (first >= 1 && first <= NTP_MAXKEY) { 21862950cc38Schristos authtrust(first, TRUE); 21872950cc38Schristos } else { 21882950cc38Schristos msyslog(LOG_NOTICE, 21892950cc38Schristos "Ignoring invalid trustedkey %d, min 1 max %d.", 21902950cc38Schristos first, NTP_MAXKEY); 21912950cc38Schristos } 21922950cc38Schristos } else { 21932950cc38Schristos first = my_val->value.r.first; 21942950cc38Schristos last = my_val->value.r.last; 21952950cc38Schristos if (first > last || first < 1 || 21962950cc38Schristos last > NTP_MAXKEY) { 21972950cc38Schristos msyslog(LOG_NOTICE, 21982950cc38Schristos "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.", 21992950cc38Schristos first, last, NTP_MAXKEY); 22002950cc38Schristos } else { 22012950cc38Schristos for (i = first; i <= last; i++) { 22022950cc38Schristos authtrust(i, TRUE); 22032950cc38Schristos } 22042950cc38Schristos } 22053123f114Skardel } 2206abb0f93cSkardel } 2207abb0f93cSkardel 22082950cc38Schristos #ifdef AUTOKEY 2209abb0f93cSkardel /* crypto revoke command */ 2210cdfa2a7eSchristos if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32) 2211cdfa2a7eSchristos sys_revoke = (u_char)ptree->auth.revoke; 2212cdfa2a7eSchristos else if (ptree->auth.revoke) 2213cdfa2a7eSchristos msyslog(LOG_ERR, 2214cdfa2a7eSchristos "'revoke' value %d ignored", 2215cdfa2a7eSchristos ptree->auth.revoke); 22162950cc38Schristos #endif /* AUTOKEY */ 2217abb0f93cSkardel } 22182950cc38Schristos #endif /* !SIM */ 2219abb0f93cSkardel 2220abb0f93cSkardel 2221abb0f93cSkardel #ifdef FREE_CFG_T 2222abb0f93cSkardel static void 2223abb0f93cSkardel free_config_auth( 22242950cc38Schristos config_tree *ptree 2225abb0f93cSkardel ) 2226abb0f93cSkardel { 22272950cc38Schristos destroy_attr_val_fifo(ptree->auth.crypto_cmd_list); 22282950cc38Schristos ptree->auth.crypto_cmd_list = NULL; 22292950cc38Schristos destroy_attr_val_fifo(ptree->auth.trusted_key_list); 22302950cc38Schristos ptree->auth.trusted_key_list = NULL; 2231abb0f93cSkardel } 2232abb0f93cSkardel #endif /* FREE_CFG_T */ 2233abb0f93cSkardel 2234abb0f93cSkardel 2235*eabc0478Schristos #ifndef SIM 22364eea345dSchristos /* Configure low-level clock-related parameters. Return TRUE if the 22374eea345dSchristos * clock might need adjustment like era-checking after the call, FALSE 22384eea345dSchristos * otherwise. 22394eea345dSchristos */ 22404eea345dSchristos static int/*BOOL*/ 22414eea345dSchristos config_tos_clock( 22424eea345dSchristos config_tree* ptree 22434eea345dSchristos ) 22444eea345dSchristos { 22454eea345dSchristos int ret; 22464eea345dSchristos attr_val* tos; 22474eea345dSchristos 22484eea345dSchristos ret = FALSE; 22494eea345dSchristos tos = HEAD_PFIFO(ptree->orphan_cmds); 22504eea345dSchristos for (; tos != NULL; tos = tos->link) { 22514eea345dSchristos switch (tos->attr) { 22524eea345dSchristos 22534eea345dSchristos default: 22544eea345dSchristos break; 22554eea345dSchristos 22564eea345dSchristos case T_Basedate: 22574eea345dSchristos basedate_set_day(tos->value.i); 22584eea345dSchristos ret = TRUE; 22594eea345dSchristos break; 22604eea345dSchristos } 22614eea345dSchristos } 2262cdfa2a7eSchristos 2263*eabc0478Schristos if (basedate_get_day() <= NTP_TO_UNIX_DAYS) { 2264cdfa2a7eSchristos basedate_set_day(basedate_eval_buildstamp() - 11); 2265*eabc0478Schristos } 22664eea345dSchristos return ret; 22674eea345dSchristos } 2268*eabc0478Schristos #endif /* !SIM */ 2269*eabc0478Schristos 22704eea345dSchristos 2271abb0f93cSkardel static void 2272abb0f93cSkardel config_tos( 22732950cc38Schristos config_tree *ptree 2274abb0f93cSkardel ) 2275abb0f93cSkardel { 2276*eabc0478Schristos char const improper_operation_msg[] = 2277*eabc0478Schristos " - daemon will not operate properly!"; 22782950cc38Schristos attr_val * tos; 2279abb0f93cSkardel int item; 22802950cc38Schristos double val; 2281abb0f93cSkardel 2282ccc794f0Schristos /* [Bug 2896] For the daemon to work properly it is essential 2283ccc794f0Schristos * that minsane < minclock <= maxclock. 2284ccc794f0Schristos * 2285ccc794f0Schristos * If either constraint is violated, the daemon will be or might 2286ccc794f0Schristos * become dysfunctional. Fixing the values is too fragile here, 2287ccc794f0Schristos * since three variables with interdependecies are involved. We 2288ccc794f0Schristos * just log an error but do not stop: This might be caused by 2289ccc794f0Schristos * remote config, and it might be fixed by remote config, too. 2290ccc794f0Schristos */ 2291ccc794f0Schristos int l_maxclock = sys_maxclock; 2292ccc794f0Schristos int l_minclock = sys_minclock; 2293ccc794f0Schristos int l_minsane = sys_minsane; 2294*eabc0478Schristos int l_floor = sys_floor; 2295*eabc0478Schristos int l_ceiling = sys_ceiling; 2296ccc794f0Schristos 2297ccc794f0Schristos /* -*- phase one: inspect / sanitize the values */ 2298ccc794f0Schristos tos = HEAD_PFIFO(ptree->orphan_cmds); 2299ccc794f0Schristos for (; tos != NULL; tos = tos->link) { 23004eea345dSchristos /* not all attributes are doubles (any more), so loading 23014eea345dSchristos * 'val' in all cases is not a good idea: It should be 23024eea345dSchristos * done as needed in every case processed here. 23034eea345dSchristos */ 2304ccc794f0Schristos switch(tos->attr) { 2305ccc794f0Schristos default: 2306ccc794f0Schristos break; 2307ccc794f0Schristos 2308ccc794f0Schristos case T_Bcpollbstep: 23094eea345dSchristos val = tos->value.d; 2310ccc794f0Schristos if (val > 4) { 2311ccc794f0Schristos msyslog(LOG_WARNING, 2312*eabc0478Schristos "Using maximum tos bcpollbstep %d, %d requested", 2313ccc794f0Schristos 4, (int)val); 2314ccc794f0Schristos tos->value.d = 4; 2315ccc794f0Schristos } else if (val < 0) { 2316ccc794f0Schristos msyslog(LOG_WARNING, 2317*eabc0478Schristos "Using minimum tos bcpollbstep %d, %d requested", 2318ccc794f0Schristos 0, (int)val); 2319ccc794f0Schristos tos->value.d = 0; 2320ccc794f0Schristos } 2321ccc794f0Schristos break; 2322ccc794f0Schristos 2323*eabc0478Schristos case T_Floor: 2324*eabc0478Schristos l_floor = (int)tos->value.d; 2325*eabc0478Schristos if (l_floor > STRATUM_UNSPEC - 1) { 2326ccc794f0Schristos msyslog(LOG_WARNING, 2327*eabc0478Schristos "Using maximum tos floor %d, %d requested", 2328*eabc0478Schristos STRATUM_UNSPEC - 1, l_floor); 2329ccc794f0Schristos tos->value.d = STRATUM_UNSPEC - 1; 2330*eabc0478Schristos } 2331*eabc0478Schristos else if (l_floor < 0) { 2332ccc794f0Schristos msyslog(LOG_WARNING, 2333ccc794f0Schristos "Using minimum tos floor %d, %d requested", 2334*eabc0478Schristos 0, l_floor); 2335*eabc0478Schristos tos->value.d = 0; 2336ccc794f0Schristos } 2337*eabc0478Schristos l_floor = (int)tos->value.d; 2338*eabc0478Schristos break; 2339*eabc0478Schristos 2340*eabc0478Schristos case T_Ceiling: 2341*eabc0478Schristos l_ceiling = (int)tos->value.d; 2342*eabc0478Schristos if (l_ceiling > STRATUM_UNSPEC - 1) { 2343*eabc0478Schristos msyslog(LOG_WARNING, 2344*eabc0478Schristos "Using maximum tos ceiling %d, %d requested", 2345*eabc0478Schristos STRATUM_UNSPEC - 1, l_ceiling); 2346*eabc0478Schristos tos->value.d = STRATUM_UNSPEC - 1; 2347*eabc0478Schristos } 2348*eabc0478Schristos else if (l_ceiling < 0) { 2349*eabc0478Schristos msyslog(LOG_WARNING, 2350*eabc0478Schristos "Using minimum tos ceiling %d, %d requested", 2351*eabc0478Schristos 0, l_ceiling); 2352*eabc0478Schristos tos->value.d = 0; 2353*eabc0478Schristos } 2354*eabc0478Schristos l_ceiling = (int)tos->value.d; 2355ccc794f0Schristos break; 2356ccc794f0Schristos 2357ccc794f0Schristos case T_Minclock: 23584eea345dSchristos val = tos->value.d; 2359ccc794f0Schristos if ((int)tos->value.d < 1) 2360ccc794f0Schristos tos->value.d = 1; 2361ccc794f0Schristos l_minclock = (int)tos->value.d; 2362ccc794f0Schristos break; 2363ccc794f0Schristos 2364ccc794f0Schristos case T_Maxclock: 23654eea345dSchristos val = tos->value.d; 2366ccc794f0Schristos if ((int)tos->value.d < 1) 2367ccc794f0Schristos tos->value.d = 1; 2368ccc794f0Schristos l_maxclock = (int)tos->value.d; 2369ccc794f0Schristos break; 2370ccc794f0Schristos 2371ccc794f0Schristos case T_Minsane: 23724eea345dSchristos val = tos->value.d; 2373cdfa2a7eSchristos if ((int)tos->value.d < 0) 2374cdfa2a7eSchristos tos->value.d = 0; 2375ccc794f0Schristos l_minsane = (int)tos->value.d; 2376ccc794f0Schristos break; 2377ccc794f0Schristos } 2378ccc794f0Schristos } 2379ccc794f0Schristos 2380ccc794f0Schristos if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) { 2381*eabc0478Schristos msyslog(LOG_ERR, "Must have tos " 2382*eabc0478Schristos "minsane (%d) < minclock (%d) <= maxclock (%d)%s", 2383*eabc0478Schristos l_minsane, l_minclock, l_maxclock, 2384*eabc0478Schristos improper_operation_msg); 2385*eabc0478Schristos } 2386*eabc0478Schristos 2387*eabc0478Schristos if (l_floor > l_ceiling) { 2388*eabc0478Schristos msyslog(LOG_ERR, "Must have tos " 2389*eabc0478Schristos "floor (%d) <= ceiling (%d)%s", 2390*eabc0478Schristos l_floor, l_ceiling, improper_operation_msg); 2391ccc794f0Schristos } 2392ccc794f0Schristos 2393ccc794f0Schristos /* -*- phase two: forward the values to the protocol machinery */ 23942950cc38Schristos tos = HEAD_PFIFO(ptree->orphan_cmds); 23952950cc38Schristos for (; tos != NULL; tos = tos->link) { 2396abb0f93cSkardel switch(tos->attr) { 2397abb0f93cSkardel 2398abb0f93cSkardel default: 2399ccc794f0Schristos fatal_error("config-tos: attr-token=%d", tos->attr); 2400abb0f93cSkardel 240103cfe0ffSchristos case T_Bcpollbstep: 240203cfe0ffSchristos item = PROTO_BCPOLLBSTEP; 240303cfe0ffSchristos break; 240403cfe0ffSchristos 2405abb0f93cSkardel case T_Ceiling: 2406abb0f93cSkardel item = PROTO_CEILING; 2407abb0f93cSkardel break; 2408abb0f93cSkardel 2409abb0f93cSkardel case T_Floor: 2410abb0f93cSkardel item = PROTO_FLOOR; 2411abb0f93cSkardel break; 2412abb0f93cSkardel 2413abb0f93cSkardel case T_Cohort: 2414abb0f93cSkardel item = PROTO_COHORT; 2415abb0f93cSkardel break; 2416abb0f93cSkardel 2417abb0f93cSkardel case T_Orphan: 2418abb0f93cSkardel item = PROTO_ORPHAN; 2419abb0f93cSkardel break; 2420abb0f93cSkardel 24212950cc38Schristos case T_Orphanwait: 24222950cc38Schristos item = PROTO_ORPHWAIT; 24232950cc38Schristos break; 24242950cc38Schristos 2425abb0f93cSkardel case T_Mindist: 2426abb0f93cSkardel item = PROTO_MINDISP; 2427abb0f93cSkardel break; 2428abb0f93cSkardel 2429abb0f93cSkardel case T_Maxdist: 2430abb0f93cSkardel item = PROTO_MAXDIST; 2431abb0f93cSkardel break; 2432abb0f93cSkardel 2433abb0f93cSkardel case T_Minclock: 2434abb0f93cSkardel item = PROTO_MINCLOCK; 2435abb0f93cSkardel break; 2436abb0f93cSkardel 2437abb0f93cSkardel case T_Maxclock: 2438abb0f93cSkardel item = PROTO_MAXCLOCK; 2439abb0f93cSkardel break; 2440abb0f93cSkardel 2441abb0f93cSkardel case T_Minsane: 2442abb0f93cSkardel item = PROTO_MINSANE; 2443abb0f93cSkardel break; 2444abb0f93cSkardel 2445abb0f93cSkardel case T_Beacon: 2446abb0f93cSkardel item = PROTO_BEACON; 2447abb0f93cSkardel break; 24484eea345dSchristos 24494eea345dSchristos case T_Basedate: 24504eea345dSchristos continue; /* SKIP proto-config for this! */ 2451abb0f93cSkardel } 24524eea345dSchristos proto_config(item, 0, tos->value.d, NULL); 2453abb0f93cSkardel } 2454abb0f93cSkardel } 2455abb0f93cSkardel 2456abb0f93cSkardel 2457abb0f93cSkardel #ifdef FREE_CFG_T 2458abb0f93cSkardel static void 2459abb0f93cSkardel free_config_tos( 24602950cc38Schristos config_tree *ptree 2461abb0f93cSkardel ) 2462abb0f93cSkardel { 24632950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->orphan_cmds); 2464abb0f93cSkardel } 2465abb0f93cSkardel #endif /* FREE_CFG_T */ 2466abb0f93cSkardel 2467abb0f93cSkardel 2468abb0f93cSkardel static void 2469abb0f93cSkardel config_monitor( 24702950cc38Schristos config_tree* ptree 2471abb0f93cSkardel ) 2472abb0f93cSkardel { 24732950cc38Schristos int_node * pfilegen_token; 2474abb0f93cSkardel const char * filegen_string; 2475abb0f93cSkardel const char * filegen_file; 2476abb0f93cSkardel FILEGEN * filegen; 24772950cc38Schristos filegen_node * my_node; 24782950cc38Schristos attr_val* my_opts; 2479abb0f93cSkardel int filegen_type; 2480abb0f93cSkardel int filegen_flag; 2481abb0f93cSkardel 2482abb0f93cSkardel /* Set the statistics directory */ 2483*eabc0478Schristos if (ptree->stats_dir) { 2484*eabc0478Schristos stats_config(STATS_STATSDIR, ptree->stats_dir, TRUE); 2485*eabc0478Schristos } 2486abb0f93cSkardel 2487abb0f93cSkardel /* NOTE: 2488abb0f93cSkardel * Calling filegen_get is brain dead. Doing a string 2489abb0f93cSkardel * comparison to find the relavant filegen structure is 2490abb0f93cSkardel * expensive. 2491abb0f93cSkardel * 2492abb0f93cSkardel * Through the parser, we already know which filegen is 2493abb0f93cSkardel * being specified. Hence, we should either store a 2494abb0f93cSkardel * pointer to the specified structure in the syntax tree 2495abb0f93cSkardel * or an index into a filegen array. 2496abb0f93cSkardel * 2497abb0f93cSkardel * Need to change the filegen code to reflect the above. 2498abb0f93cSkardel */ 2499abb0f93cSkardel 2500abb0f93cSkardel /* Turn on the specified statistics */ 25012950cc38Schristos pfilegen_token = HEAD_PFIFO(ptree->stats_list); 25022950cc38Schristos for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) { 25032950cc38Schristos filegen_string = keyword(pfilegen_token->i); 2504abb0f93cSkardel filegen = filegen_get(filegen_string); 25052950cc38Schristos if (NULL == filegen) { 25062950cc38Schristos msyslog(LOG_ERR, 25072950cc38Schristos "stats %s unrecognized", 25082950cc38Schristos filegen_string); 25092950cc38Schristos continue; 25102950cc38Schristos } 2511abb0f93cSkardel DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n", 25122950cc38Schristos filegen_string, filegen->dir, 25132950cc38Schristos filegen->fname)); 25142950cc38Schristos filegen_flag = filegen->flag; 25152950cc38Schristos filegen_flag |= FGEN_FLAG_ENABLED; 25162950cc38Schristos filegen_config(filegen, statsdir, filegen_string, 25172950cc38Schristos filegen->type, filegen_flag); 2518abb0f93cSkardel } 2519abb0f93cSkardel 2520abb0f93cSkardel /* Configure the statistics with the options */ 25212950cc38Schristos my_node = HEAD_PFIFO(ptree->filegen_opts); 25222950cc38Schristos for (; my_node != NULL; my_node = my_node->link) { 25232950cc38Schristos filegen_string = keyword(my_node->filegen_token); 25242950cc38Schristos filegen = filegen_get(filegen_string); 25252950cc38Schristos if (NULL == filegen) { 25262950cc38Schristos msyslog(LOG_ERR, 25272950cc38Schristos "filegen category '%s' unrecognized", 25282950cc38Schristos filegen_string); 25292950cc38Schristos continue; 25302950cc38Schristos } 25312950cc38Schristos filegen_file = filegen_string; 2532abb0f93cSkardel 25332950cc38Schristos /* Initialize the filegen variables to their pre-configuration states */ 2534abb0f93cSkardel filegen_flag = filegen->flag; 2535abb0f93cSkardel filegen_type = filegen->type; 2536abb0f93cSkardel 25373123f114Skardel /* "filegen ... enabled" is the default (when filegen is used) */ 25383123f114Skardel filegen_flag |= FGEN_FLAG_ENABLED; 25393123f114Skardel 25402950cc38Schristos my_opts = HEAD_PFIFO(my_node->options); 25412950cc38Schristos for (; my_opts != NULL; my_opts = my_opts->link) { 2542abb0f93cSkardel switch (my_opts->attr) { 2543abb0f93cSkardel 2544abb0f93cSkardel case T_File: 25452950cc38Schristos filegen_file = my_opts->value.s; 2546abb0f93cSkardel break; 2547abb0f93cSkardel 2548abb0f93cSkardel case T_Type: 2549abb0f93cSkardel switch (my_opts->value.i) { 2550abb0f93cSkardel 2551abb0f93cSkardel default: 2552ccc794f0Schristos fatal_error("config-monitor: type-token=%d", my_opts->value.i); 2553abb0f93cSkardel 2554abb0f93cSkardel case T_None: 2555abb0f93cSkardel filegen_type = FILEGEN_NONE; 2556abb0f93cSkardel break; 2557abb0f93cSkardel 2558abb0f93cSkardel case T_Pid: 2559abb0f93cSkardel filegen_type = FILEGEN_PID; 2560abb0f93cSkardel break; 2561abb0f93cSkardel 2562abb0f93cSkardel case T_Day: 2563abb0f93cSkardel filegen_type = FILEGEN_DAY; 2564abb0f93cSkardel break; 2565abb0f93cSkardel 2566abb0f93cSkardel case T_Week: 2567abb0f93cSkardel filegen_type = FILEGEN_WEEK; 2568abb0f93cSkardel break; 2569abb0f93cSkardel 2570abb0f93cSkardel case T_Month: 2571abb0f93cSkardel filegen_type = FILEGEN_MONTH; 2572abb0f93cSkardel break; 2573abb0f93cSkardel 2574abb0f93cSkardel case T_Year: 2575abb0f93cSkardel filegen_type = FILEGEN_YEAR; 2576abb0f93cSkardel break; 2577abb0f93cSkardel 2578abb0f93cSkardel case T_Age: 2579abb0f93cSkardel filegen_type = FILEGEN_AGE; 2580abb0f93cSkardel break; 2581abb0f93cSkardel } 2582abb0f93cSkardel break; 2583abb0f93cSkardel 2584abb0f93cSkardel case T_Flag: 2585abb0f93cSkardel switch (my_opts->value.i) { 2586abb0f93cSkardel 2587abb0f93cSkardel case T_Link: 2588abb0f93cSkardel filegen_flag |= FGEN_FLAG_LINK; 2589abb0f93cSkardel break; 2590abb0f93cSkardel 2591abb0f93cSkardel case T_Nolink: 2592abb0f93cSkardel filegen_flag &= ~FGEN_FLAG_LINK; 2593abb0f93cSkardel break; 2594abb0f93cSkardel 2595abb0f93cSkardel case T_Enable: 2596abb0f93cSkardel filegen_flag |= FGEN_FLAG_ENABLED; 2597abb0f93cSkardel break; 2598abb0f93cSkardel 2599abb0f93cSkardel case T_Disable: 2600abb0f93cSkardel filegen_flag &= ~FGEN_FLAG_ENABLED; 2601abb0f93cSkardel break; 2602abb0f93cSkardel 2603abb0f93cSkardel default: 2604abb0f93cSkardel msyslog(LOG_ERR, 2605abb0f93cSkardel "Unknown filegen flag token %d", 2606abb0f93cSkardel my_opts->value.i); 2607abb0f93cSkardel exit(1); 2608abb0f93cSkardel } 2609abb0f93cSkardel break; 26102950cc38Schristos 2611abb0f93cSkardel default: 2612abb0f93cSkardel msyslog(LOG_ERR, 2613abb0f93cSkardel "Unknown filegen option token %d", 2614abb0f93cSkardel my_opts->attr); 2615abb0f93cSkardel exit(1); 2616abb0f93cSkardel } 2617abb0f93cSkardel } 26182950cc38Schristos filegen_config(filegen, statsdir, filegen_file, 26192950cc38Schristos filegen_type, filegen_flag); 2620abb0f93cSkardel } 2621abb0f93cSkardel } 2622abb0f93cSkardel 2623abb0f93cSkardel 2624abb0f93cSkardel #ifdef FREE_CFG_T 2625abb0f93cSkardel static void 2626abb0f93cSkardel free_config_monitor( 26272950cc38Schristos config_tree *ptree 2628abb0f93cSkardel ) 2629abb0f93cSkardel { 2630abb0f93cSkardel if (ptree->stats_dir) { 2631abb0f93cSkardel free(ptree->stats_dir); 2632abb0f93cSkardel ptree->stats_dir = NULL; 2633abb0f93cSkardel } 2634abb0f93cSkardel 26352950cc38Schristos FREE_INT_FIFO(ptree->stats_list); 26362950cc38Schristos FREE_FILEGEN_FIFO(ptree->filegen_opts); 2637abb0f93cSkardel } 2638abb0f93cSkardel #endif /* FREE_CFG_T */ 2639abb0f93cSkardel 2640abb0f93cSkardel 26412950cc38Schristos #ifndef SIM 2642abb0f93cSkardel static void 2643abb0f93cSkardel config_access( 26442950cc38Schristos config_tree *ptree 2645abb0f93cSkardel ) 2646abb0f93cSkardel { 2647abb0f93cSkardel static int warned_signd; 26482950cc38Schristos attr_val * my_opt; 26492950cc38Schristos restrict_node * my_node; 26502950cc38Schristos sockaddr_u addr; 26512950cc38Schristos sockaddr_u mask; 26522950cc38Schristos struct addrinfo hints; 26532950cc38Schristos struct addrinfo * ai_list; 26542950cc38Schristos struct addrinfo * pai; 26552950cc38Schristos int rc; 2656*eabc0478Schristos int/*BOOL*/ success; 2657*eabc0478Schristos int/*BOOL*/ restrict_default; 26584eea345dSchristos u_short rflags; 26593123f114Skardel u_short mflags; 26604eea345dSchristos short ippeerlimit; 26612950cc38Schristos int range_err; 2662cdfa2a7eSchristos attr_val * atrv; 2663cdfa2a7eSchristos attr_val * dflt_psl_atr; 2664abb0f93cSkardel const char * signd_warning = 2665abb0f93cSkardel #ifdef HAVE_NTP_SIGND 2666*eabc0478Schristos "MS-SNTP signd operations currently block ntpd degrading service to all clients.\n"; 2667abb0f93cSkardel #else 2668*eabc0478Schristos "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.\n"; 2669abb0f93cSkardel #endif 2670abb0f93cSkardel 26712950cc38Schristos /* Configure the mru options */ 26722950cc38Schristos my_opt = HEAD_PFIFO(ptree->mru_opts); 26732950cc38Schristos for (; my_opt != NULL; my_opt = my_opt->link) { 26742950cc38Schristos 26752950cc38Schristos range_err = FALSE; 26762950cc38Schristos 26772950cc38Schristos switch (my_opt->attr) { 26782950cc38Schristos 26792950cc38Schristos case T_Incalloc: 26802950cc38Schristos if (0 <= my_opt->value.i) 26812950cc38Schristos mru_incalloc = my_opt->value.u; 26822950cc38Schristos else 26832950cc38Schristos range_err = TRUE; 26842950cc38Schristos break; 26852950cc38Schristos 26862950cc38Schristos case T_Incmem: 26872950cc38Schristos if (0 <= my_opt->value.i) 2688ea66d795Schristos mru_incalloc = (my_opt->value.u * 1024U) 26892950cc38Schristos / sizeof(mon_entry); 26902950cc38Schristos else 26912950cc38Schristos range_err = TRUE; 26922950cc38Schristos break; 26932950cc38Schristos 26942950cc38Schristos case T_Initalloc: 26952950cc38Schristos if (0 <= my_opt->value.i) 26962950cc38Schristos mru_initalloc = my_opt->value.u; 26972950cc38Schristos else 26982950cc38Schristos range_err = TRUE; 26992950cc38Schristos break; 27002950cc38Schristos 27012950cc38Schristos case T_Initmem: 27022950cc38Schristos if (0 <= my_opt->value.i) 2703ea66d795Schristos mru_initalloc = (my_opt->value.u * 1024U) 27042950cc38Schristos / sizeof(mon_entry); 27052950cc38Schristos else 27062950cc38Schristos range_err = TRUE; 27072950cc38Schristos break; 27082950cc38Schristos 27092950cc38Schristos case T_Mindepth: 27102950cc38Schristos if (0 <= my_opt->value.i) 27112950cc38Schristos mru_mindepth = my_opt->value.u; 27122950cc38Schristos else 27132950cc38Schristos range_err = TRUE; 27142950cc38Schristos break; 27152950cc38Schristos 27162950cc38Schristos case T_Maxage: 27172950cc38Schristos mru_maxage = my_opt->value.i; 27182950cc38Schristos break; 27192950cc38Schristos 27202950cc38Schristos case T_Maxdepth: 27212950cc38Schristos if (0 <= my_opt->value.i) 27222950cc38Schristos mru_maxdepth = my_opt->value.u; 27232950cc38Schristos else 27242950cc38Schristos mru_maxdepth = UINT_MAX; 27252950cc38Schristos break; 27262950cc38Schristos 27272950cc38Schristos case T_Maxmem: 27282950cc38Schristos if (0 <= my_opt->value.i) 2729ea66d795Schristos mru_maxdepth = (my_opt->value.u * 1024U) / 27302950cc38Schristos sizeof(mon_entry); 27312950cc38Schristos else 27322950cc38Schristos mru_maxdepth = UINT_MAX; 27332950cc38Schristos break; 27342950cc38Schristos 27352950cc38Schristos default: 27362950cc38Schristos msyslog(LOG_ERR, 27372950cc38Schristos "Unknown mru option %s (%d)", 27382950cc38Schristos keyword(my_opt->attr), my_opt->attr); 27392950cc38Schristos exit(1); 27402950cc38Schristos } 27412950cc38Schristos if (range_err) 27422950cc38Schristos msyslog(LOG_ERR, 27432950cc38Schristos "mru %s %d out of range, ignored.", 27442950cc38Schristos keyword(my_opt->attr), my_opt->value.i); 27452950cc38Schristos } 27462950cc38Schristos 2747abb0f93cSkardel /* Configure the discard options */ 27482950cc38Schristos my_opt = HEAD_PFIFO(ptree->discard_opts); 27492950cc38Schristos for (; my_opt != NULL; my_opt = my_opt->link) { 2750abb0f93cSkardel 2751abb0f93cSkardel switch (my_opt->attr) { 2752abb0f93cSkardel 2753abb0f93cSkardel case T_Average: 27542950cc38Schristos if (0 <= my_opt->value.i && 27552950cc38Schristos my_opt->value.i <= UCHAR_MAX) 27562950cc38Schristos ntp_minpoll = (u_char)my_opt->value.u; 27572950cc38Schristos else 27582950cc38Schristos msyslog(LOG_ERR, 27592950cc38Schristos "discard average %d out of range, ignored.", 27602950cc38Schristos my_opt->value.i); 2761abb0f93cSkardel break; 2762abb0f93cSkardel 2763abb0f93cSkardel case T_Minimum: 2764abb0f93cSkardel ntp_minpkt = my_opt->value.i; 2765abb0f93cSkardel break; 2766abb0f93cSkardel 2767abb0f93cSkardel case T_Monitor: 2768abb0f93cSkardel mon_age = my_opt->value.i; 2769abb0f93cSkardel break; 2770abb0f93cSkardel 2771abb0f93cSkardel default: 2772abb0f93cSkardel msyslog(LOG_ERR, 27732950cc38Schristos "Unknown discard option %s (%d)", 27742950cc38Schristos keyword(my_opt->attr), my_opt->attr); 2775abb0f93cSkardel exit(1); 2776abb0f93cSkardel } 2777abb0f93cSkardel } 2778abb0f93cSkardel 2779cdfa2a7eSchristos /* Configure each line of restrict options */ 27802950cc38Schristos my_node = HEAD_PFIFO(ptree->restrict_opts); 27814eea345dSchristos 27822950cc38Schristos for (; my_node != NULL; my_node = my_node->link) { 2783cdfa2a7eSchristos 27844eea345dSchristos /* Grab the ippeerlmit */ 27854eea345dSchristos ippeerlimit = my_node->ippeerlimit; 27864eea345dSchristos 2787abb0f93cSkardel /* Parse the flags */ 27884eea345dSchristos rflags = 0; 2789abb0f93cSkardel mflags = 0; 2790abb0f93cSkardel 2791cdfa2a7eSchristos my_opt = HEAD_PFIFO(my_node->flag_tok_fifo); 2792cdfa2a7eSchristos for (; my_opt != NULL; my_opt = my_opt->link) { 2793cdfa2a7eSchristos switch (my_opt->attr) { 2794abb0f93cSkardel 2795abb0f93cSkardel default: 2796cdfa2a7eSchristos fatal_error("config_access: Unknown flag-type-token=%s/%d", keyword(my_opt->attr), my_opt->attr); 2797abb0f93cSkardel 2798abb0f93cSkardel case T_Ntpport: 2799abb0f93cSkardel mflags |= RESM_NTPONLY; 2800abb0f93cSkardel break; 2801abb0f93cSkardel 28022950cc38Schristos case T_Source: 28032950cc38Schristos mflags |= RESM_SOURCE; 28042950cc38Schristos break; 28052950cc38Schristos 2806abb0f93cSkardel case T_Flake: 28074eea345dSchristos rflags |= RES_FLAKE; 2808abb0f93cSkardel break; 2809abb0f93cSkardel 2810abb0f93cSkardel case T_Ignore: 28114eea345dSchristos rflags |= RES_IGNORE; 2812abb0f93cSkardel break; 2813abb0f93cSkardel 2814abb0f93cSkardel case T_Kod: 28154eea345dSchristos rflags |= RES_KOD; 2816abb0f93cSkardel break; 2817abb0f93cSkardel 2818abb0f93cSkardel case T_Limited: 28194eea345dSchristos rflags |= RES_LIMITED; 2820abb0f93cSkardel break; 2821abb0f93cSkardel 2822abb0f93cSkardel case T_Lowpriotrap: 28234eea345dSchristos rflags |= RES_LPTRAP; 2824abb0f93cSkardel break; 2825abb0f93cSkardel 2826cdfa2a7eSchristos case T_Mssntp: 2827cdfa2a7eSchristos rflags |= RES_MSSNTP; 2828cdfa2a7eSchristos break; 2829cdfa2a7eSchristos 2830abb0f93cSkardel case T_Nomodify: 28314eea345dSchristos rflags |= RES_NOMODIFY; 2832abb0f93cSkardel break; 2833abb0f93cSkardel 28342950cc38Schristos case T_Nomrulist: 28354eea345dSchristos rflags |= RES_NOMRULIST; 28364eea345dSchristos break; 28374eea345dSchristos 28384eea345dSchristos case T_Noepeer: 28394eea345dSchristos rflags |= RES_NOEPEER; 28402950cc38Schristos break; 28412950cc38Schristos 2842abb0f93cSkardel case T_Nopeer: 28434eea345dSchristos rflags |= RES_NOPEER; 2844abb0f93cSkardel break; 2845abb0f93cSkardel 2846abb0f93cSkardel case T_Noquery: 28474eea345dSchristos rflags |= RES_NOQUERY; 2848abb0f93cSkardel break; 2849abb0f93cSkardel 2850abb0f93cSkardel case T_Noserve: 28514eea345dSchristos rflags |= RES_DONTSERVE; 2852abb0f93cSkardel break; 2853abb0f93cSkardel 2854abb0f93cSkardel case T_Notrap: 28554eea345dSchristos rflags |= RES_NOTRAP; 2856abb0f93cSkardel break; 2857abb0f93cSkardel 2858abb0f93cSkardel case T_Notrust: 28594eea345dSchristos rflags |= RES_DONTTRUST; 2860abb0f93cSkardel break; 2861abb0f93cSkardel 2862cdfa2a7eSchristos case T_ServerresponseFuzz: 2863cdfa2a7eSchristos rflags |= RES_SRVRSPFUZ; 2864cdfa2a7eSchristos break; 2865cdfa2a7eSchristos 2866abb0f93cSkardel case T_Version: 28674eea345dSchristos rflags |= RES_VERSION; 2868abb0f93cSkardel break; 2869abb0f93cSkardel } 2870abb0f93cSkardel } 2871abb0f93cSkardel 28724eea345dSchristos if ((RES_MSSNTP & rflags) && !warned_signd) { 2873*eabc0478Schristos warned_signd = TRUE; 2874*eabc0478Schristos fprintf(stderr, "%s", signd_warning); 28757fdb569fSchristos msyslog(LOG_WARNING, "%s", signd_warning); 2876abb0f93cSkardel } 28772950cc38Schristos 28784eea345dSchristos if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) { 2879ea66d795Schristos const char *kod_where = (my_node->addr) 2880ea66d795Schristos ? my_node->addr->address 2881ea66d795Schristos : (mflags & RESM_SOURCE) 2882ea66d795Schristos ? "source" 2883ea66d795Schristos : "default"; 2884*eabc0478Schristos const char *kod_warn = "'kod' does nothing without 'limited'.\n"; 2885ea66d795Schristos 2886*eabc0478Schristos fprintf(stderr, "line %d col %d restrict %s: %s", 2887*eabc0478Schristos my_node->line_no, my_node->column, 2888*eabc0478Schristos kod_where, kod_warn); 2889*eabc0478Schristos msyslog(LOG_WARNING, "line %d col %d restrict %s: %s", 2890*eabc0478Schristos my_node->line_no, my_node->column, 2891*eabc0478Schristos kod_where, kod_warn); 2892ea66d795Schristos } 2893ea66d795Schristos 28942950cc38Schristos ZERO_SOCK(&addr); 28952950cc38Schristos ai_list = NULL; 28962950cc38Schristos pai = NULL; 2897*eabc0478Schristos restrict_default = FALSE; 28982950cc38Schristos 28992950cc38Schristos if (NULL == my_node->addr) { 29002950cc38Schristos ZERO_SOCK(&mask); 29012950cc38Schristos if (!(RESM_SOURCE & mflags)) { 29022950cc38Schristos /* 29032950cc38Schristos * The user specified a default rule 29042950cc38Schristos * without a -4 / -6 qualifier, add to 29052950cc38Schristos * both lists 29062950cc38Schristos */ 2907*eabc0478Schristos restrict_default = TRUE; 29082950cc38Schristos } else { 29092950cc38Schristos /* apply "restrict source ..." */ 2910*eabc0478Schristos success = hack_restrict(RESTRICT_FLAGS, 2911*eabc0478Schristos NULL, NULL, 2912*eabc0478Schristos ippeerlimit, 2913*eabc0478Schristos mflags, rflags, 2914*eabc0478Schristos 0); 2915*eabc0478Schristos if (!success) { 2916*eabc0478Schristos msyslog(LOG_ERR, 2917*eabc0478Schristos "unable to save restrict source"); 2918*eabc0478Schristos } 29192950cc38Schristos continue; 29202950cc38Schristos } 29212950cc38Schristos } else { 29222950cc38Schristos /* Resolve the specified address */ 29232950cc38Schristos AF(&addr) = (u_short)my_node->addr->type; 29242950cc38Schristos 29252950cc38Schristos if (getnetnum(my_node->addr->address, 29262950cc38Schristos &addr, 1, t_UNK) != 1) { 29272950cc38Schristos /* 29282950cc38Schristos * Attempt a blocking lookup. This 29292950cc38Schristos * is in violation of the nonblocking 29302950cc38Schristos * design of ntpd's mainline code. The 29312950cc38Schristos * alternative of running without the 29322950cc38Schristos * restriction until the name resolved 29332950cc38Schristos * seems worse. 29342950cc38Schristos * Ideally some scheme could be used for 29352950cc38Schristos * restrict directives in the startup 29362950cc38Schristos * ntp.conf to delay starting up the 29372950cc38Schristos * protocol machinery until after all 29382950cc38Schristos * restrict hosts have been resolved. 29392950cc38Schristos */ 29402950cc38Schristos ai_list = NULL; 29412950cc38Schristos ZERO(hints); 29422950cc38Schristos hints.ai_protocol = IPPROTO_UDP; 29432950cc38Schristos hints.ai_socktype = SOCK_DGRAM; 29442950cc38Schristos hints.ai_family = my_node->addr->type; 29452950cc38Schristos rc = getaddrinfo(my_node->addr->address, 29462950cc38Schristos "ntp", &hints, 29472950cc38Schristos &ai_list); 29482950cc38Schristos if (rc) { 29492950cc38Schristos msyslog(LOG_ERR, 2950*eabc0478Schristos "restrict: line %d col %d" 2951*eabc0478Schristos " address/host '%s' unusable.", 29522950cc38Schristos my_node->line_no, 2953*eabc0478Schristos my_node->column, 29542950cc38Schristos my_node->addr->address); 29552950cc38Schristos continue; 29562950cc38Schristos } 2957ea66d795Schristos INSIST(ai_list != NULL); 29582950cc38Schristos pai = ai_list; 2959ea66d795Schristos INSIST(pai->ai_addr != NULL); 2960*eabc0478Schristos INSIST(sizeof(addr) >= pai->ai_addrlen); 29612950cc38Schristos memcpy(&addr, pai->ai_addr, 29622950cc38Schristos pai->ai_addrlen); 2963ea66d795Schristos INSIST(AF_INET == AF(&addr) || 29642950cc38Schristos AF_INET6 == AF(&addr)); 29652950cc38Schristos } 29662950cc38Schristos 2967*eabc0478Schristos /* default to all-ones mask for single address */ 29682950cc38Schristos SET_HOSTMASK(&mask, AF(&addr)); 29692950cc38Schristos 2970*eabc0478Schristos /* Ignore mask if addr from hostname [Bug 3872] */ 2971*eabc0478Schristos if (NULL == ai_list && my_node->mask) { 29722950cc38Schristos ZERO_SOCK(&mask); 29732950cc38Schristos AF(&mask) = my_node->mask->type; 29742950cc38Schristos if (getnetnum(my_node->mask->address, 29752950cc38Schristos &mask, 1, t_MSK) != 1) { 29762950cc38Schristos msyslog(LOG_ERR, 2977*eabc0478Schristos "restrict: line %d col %d" 2978*eabc0478Schristos " mask '%s' unusable.", 29792950cc38Schristos my_node->line_no, 2980*eabc0478Schristos my_node->column, 29812950cc38Schristos my_node->mask->address); 29822950cc38Schristos continue; 2983abb0f93cSkardel } 2984abb0f93cSkardel } 29852950cc38Schristos } 29862950cc38Schristos 29872950cc38Schristos /* Set the flags */ 29882950cc38Schristos if (restrict_default) { 29892950cc38Schristos AF(&addr) = AF_INET; 29902950cc38Schristos AF(&mask) = AF_INET; 2991*eabc0478Schristos success = hack_restrict( 2992*eabc0478Schristos RESTRICT_FLAGS, 2993*eabc0478Schristos &addr, 2994*eabc0478Schristos &mask, 2995*eabc0478Schristos ippeerlimit, 2996*eabc0478Schristos mflags, 2997*eabc0478Schristos rflags, 2998*eabc0478Schristos 0 2999*eabc0478Schristos ); 3000*eabc0478Schristos if (!success) { 3001*eabc0478Schristos msyslog(LOG_ERR, 3002*eabc0478Schristos "unable to save %s %s restriction", 3003*eabc0478Schristos stoa(&addr), stoa(&mask)); 3004*eabc0478Schristos } 30052950cc38Schristos AF(&addr) = AF_INET6; 30062950cc38Schristos AF(&mask) = AF_INET6; 30072950cc38Schristos } 30082950cc38Schristos 30092950cc38Schristos do { 3010*eabc0478Schristos success = hack_restrict( 3011*eabc0478Schristos my_node->remove 3012*eabc0478Schristos ? RESTRICT_REMOVE 3013*eabc0478Schristos : RESTRICT_FLAGS, 3014*eabc0478Schristos &addr, 3015*eabc0478Schristos &mask, 3016*eabc0478Schristos ippeerlimit, 3017*eabc0478Schristos mflags, 3018*eabc0478Schristos rflags, 3019*eabc0478Schristos 0); 3020*eabc0478Schristos if (!success) { 3021*eabc0478Schristos msyslog(LOG_ERR, 3022*eabc0478Schristos "unable to %s %s %s restriction", 3023*eabc0478Schristos my_node->remove 3024*eabc0478Schristos ? "delete" 3025*eabc0478Schristos : "save", 3026*eabc0478Schristos stoa(&addr), stoa(&mask)); 3027*eabc0478Schristos } 30282950cc38Schristos if (pai != NULL && 30292950cc38Schristos NULL != (pai = pai->ai_next)) { 3030ea66d795Schristos INSIST(pai->ai_addr != NULL); 3031ea66d795Schristos INSIST(sizeof(addr) >= 30322950cc38Schristos pai->ai_addrlen); 30332950cc38Schristos ZERO_SOCK(&addr); 30342950cc38Schristos memcpy(&addr, pai->ai_addr, 30352950cc38Schristos pai->ai_addrlen); 3036ea66d795Schristos INSIST(AF_INET == AF(&addr) || 30372950cc38Schristos AF_INET6 == AF(&addr)); 30382950cc38Schristos SET_HOSTMASK(&mask, AF(&addr)); 30392950cc38Schristos } 30402950cc38Schristos } while (pai != NULL); 30412950cc38Schristos 3042*eabc0478Schristos if (ai_list != NULL) { 30432950cc38Schristos freeaddrinfo(ai_list); 30442950cc38Schristos } 3045*eabc0478Schristos } 3046cdfa2a7eSchristos 3047cdfa2a7eSchristos /* 3048*eabc0478Schristos * pollskewlist 3049*eabc0478Schristos */ 3050*eabc0478Schristos atrv = HEAD_PFIFO(ptree->pollskewlist); 3051*eabc0478Schristos if (NULL == atrv) { 3052*eabc0478Schristos /* don't touch the poll skew list */ 3053*eabc0478Schristos return; 3054*eabc0478Schristos } 3055*eabc0478Schristos ZERO(psl); 3056*eabc0478Schristos /* 3057cdfa2a7eSchristos * First, find the last default pollskewlist item. 3058cdfa2a7eSchristos */ 3059cdfa2a7eSchristos dflt_psl_atr = NULL; 3060cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) { 3061*eabc0478Schristos if (-1 == atrv->attr) { /* default */ 3062cdfa2a7eSchristos dflt_psl_atr = atrv; 3063*eabc0478Schristos } else if ( atrv->attr < NTP_MINPOLL 3064*eabc0478Schristos || atrv->attr > NTP_MAXPOLL) { 3065cdfa2a7eSchristos msyslog(LOG_ERR, 3066*eabc0478Schristos "Poll %d out of bounds [%d-%d] for pollskewlist", 3067*eabc0478Schristos atrv->attr, NTP_MINPOLL, NTP_MAXPOLL); 3068cdfa2a7eSchristos } 3069cdfa2a7eSchristos } 3070cdfa2a7eSchristos 3071*eabc0478Schristos /* If we have a nonzero default, put it in all entries */ 3072cdfa2a7eSchristos if ( dflt_psl_atr 3073cdfa2a7eSchristos && ( 0 != dflt_psl_atr->value.r.first 3074cdfa2a7eSchristos || 0 != dflt_psl_atr->value.r.last)) { 3075cdfa2a7eSchristos int i; 3076cdfa2a7eSchristos 3077*eabc0478Schristos for (i = NTP_MINPOLL; i <= NTP_MAXPOLL; ++i) { 3078cdfa2a7eSchristos attrtopsl(i, dflt_psl_atr); 3079cdfa2a7eSchristos } 3080cdfa2a7eSchristos } 3081cdfa2a7eSchristos 3082cdfa2a7eSchristos /* Finally, update the PSL with any explicit entries */ 3083cdfa2a7eSchristos atrv = HEAD_PFIFO(ptree->pollskewlist); 3084cdfa2a7eSchristos for ( ; atrv != NULL; atrv = atrv->link) { 3085*eabc0478Schristos if (atrv->attr >= NTP_MINPOLL && atrv->attr <= NTP_MAXPOLL) { 3086cdfa2a7eSchristos attrtopsl(atrv->attr, atrv); 3087cdfa2a7eSchristos } 3088cdfa2a7eSchristos } 3089cdfa2a7eSchristos 3090cdfa2a7eSchristos #if 0 3091cdfa2a7eSchristos int p; 3092cdfa2a7eSchristos msyslog(LOG_INFO, "Dumping PSL:"); 3093*eabc0478Schristos for (p = NTP_MINPOLL; p <= NTP_MAXPOLL; ++p) { 3094cdfa2a7eSchristos psl_item psi; 3095cdfa2a7eSchristos 3096cdfa2a7eSchristos if (0 == get_pollskew(p, &psi)) { 3097cdfa2a7eSchristos msyslog(LOG_INFO, "poll %d: sub %d, qty %d, msk %d", 3098cdfa2a7eSchristos p, psi.sub, psi.qty, psi.msk); 3099cdfa2a7eSchristos } else { 3100cdfa2a7eSchristos msyslog(LOG_ERR, "Dumping PSL: get_pollskew(%d) failed!", p); 3101cdfa2a7eSchristos } 3102cdfa2a7eSchristos } 3103cdfa2a7eSchristos #endif 3104cdfa2a7eSchristos } 3105cdfa2a7eSchristos 3106cdfa2a7eSchristos 3107*eabc0478Schristos static void 3108*eabc0478Schristos attrtopsl( 3109*eabc0478Schristos u_char log2_poll, 3110*eabc0478Schristos attr_val * avp 3111*eabc0478Schristos ) 3112cdfa2a7eSchristos { 3113*eabc0478Schristos int pao = log2_poll - NTP_MINPOLL; /* poll array offset */ 3114*eabc0478Schristos u_int32 lower = (u_short)avp->value.r.first; /* ntp_parser.y ensures */ 3115*eabc0478Schristos u_int32 upper = (u_short)avp->value.r.last; /* non-neg. first/last */ 3116*eabc0478Schristos u_int psmax = 1 << (log2_poll - 1); 3117*eabc0478Schristos u_int32 qmsk; 3118cdfa2a7eSchristos 3119*eabc0478Schristos DEBUG_INSIST((size_t)pao < COUNTOF(psl)); 3120cdfa2a7eSchristos 3121cdfa2a7eSchristos if (lower > psmax) { 3122*eabc0478Schristos msyslog(LOG_WARNING, "pollskewlist %d lower bound reduced from %d to %d", 3123*eabc0478Schristos log2_poll, lower, psmax); 3124cdfa2a7eSchristos lower = psmax; 3125cdfa2a7eSchristos } 3126cdfa2a7eSchristos if (upper > psmax) { 3127*eabc0478Schristos msyslog(LOG_WARNING, "pollskewlist %d upper bound reduced from %d to %d", 3128*eabc0478Schristos log2_poll, upper, psmax); 3129cdfa2a7eSchristos upper = psmax; 3130cdfa2a7eSchristos } 3131cdfa2a7eSchristos psl[pao].sub = lower; 3132cdfa2a7eSchristos psl[pao].qty = lower + upper; 3133cdfa2a7eSchristos 3134cdfa2a7eSchristos qmsk = 1; 3135cdfa2a7eSchristos while (qmsk < (lower + upper)) { 3136cdfa2a7eSchristos qmsk <<= 1; 3137cdfa2a7eSchristos qmsk |= 1; 3138cdfa2a7eSchristos } 3139*eabc0478Schristos psl[pao].msk = qmsk; 31402950cc38Schristos } 31412950cc38Schristos #endif /* !SIM */ 3142abb0f93cSkardel 3143abb0f93cSkardel 3144cdfa2a7eSchristos int 3145cdfa2a7eSchristos get_pollskew( 3146cdfa2a7eSchristos int p, 3147cdfa2a7eSchristos psl_item *rv 3148cdfa2a7eSchristos ) 3149cdfa2a7eSchristos { 3150*eabc0478Schristos #ifdef DISABLE_BUG3767_FIX 3151*eabc0478Schristos DEBUG_INSIST(NTP_MINPOLL <= p && NTP_MAXPOLL >= p); 3152*eabc0478Schristos #endif 3153*eabc0478Schristos if (NTP_MINPOLL <= p && p <= NTP_MAXPOLL) { 3154*eabc0478Schristos *rv = psl[p - NTP_MINPOLL]; 3155cdfa2a7eSchristos return 0; 3156cdfa2a7eSchristos } else { 3157*eabc0478Schristos msyslog(LOG_DEBUG, "get_pollskew(%d): out of range", p); 3158cdfa2a7eSchristos return -1; 3159cdfa2a7eSchristos } 3160cdfa2a7eSchristos 3161cdfa2a7eSchristos /* NOTREACHED */ 3162cdfa2a7eSchristos } 3163cdfa2a7eSchristos 3164cdfa2a7eSchristos 3165abb0f93cSkardel #ifdef FREE_CFG_T 3166abb0f93cSkardel static void 3167abb0f93cSkardel free_config_access( 31682950cc38Schristos config_tree *ptree 3169abb0f93cSkardel ) 3170abb0f93cSkardel { 31712950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->mru_opts); 31722950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->discard_opts); 31732950cc38Schristos FREE_RESTRICT_FIFO(ptree->restrict_opts); 3174abb0f93cSkardel } 3175abb0f93cSkardel #endif /* FREE_CFG_T */ 3176abb0f93cSkardel 3177abb0f93cSkardel 3178abb0f93cSkardel static void 31792950cc38Schristos config_rlimit( 31802950cc38Schristos config_tree *ptree 3181abb0f93cSkardel ) 3182abb0f93cSkardel { 31832950cc38Schristos attr_val * rlimit_av; 3184abb0f93cSkardel 31852950cc38Schristos rlimit_av = HEAD_PFIFO(ptree->rlimit); 31862950cc38Schristos for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) { 31872950cc38Schristos switch (rlimit_av->attr) { 31882950cc38Schristos 31892950cc38Schristos default: 3190ccc794f0Schristos fatal_error("config-rlimit: value-token=%d", rlimit_av->attr); 31912950cc38Schristos 31922950cc38Schristos case T_Memlock: 3193af12ab5eSchristos /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */ 31944eea345dSchristos if (HAVE_OPT( SAVECONFIGQUIT )) { 31954eea345dSchristos break; 31964eea345dSchristos } 3197af12ab5eSchristos if (rlimit_av->value.i == -1) { 3198af12ab5eSchristos # if defined(HAVE_MLOCKALL) 3199af12ab5eSchristos if (cur_memlock != 0) { 3200af12ab5eSchristos if (-1 == munlockall()) { 3201af12ab5eSchristos msyslog(LOG_ERR, "munlockall() failed: %m"); 3202af12ab5eSchristos } 3203af12ab5eSchristos } 3204af12ab5eSchristos cur_memlock = 0; 3205af12ab5eSchristos # endif /* HAVE_MLOCKALL */ 3206af12ab5eSchristos } else if (rlimit_av->value.i >= 0) { 32072950cc38Schristos #if defined(RLIMIT_MEMLOCK) 3208af12ab5eSchristos # if defined(HAVE_MLOCKALL) 3209af12ab5eSchristos if (cur_memlock != 1) { 3210af12ab5eSchristos if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) { 3211af12ab5eSchristos msyslog(LOG_ERR, "mlockall() failed: %m"); 3212af12ab5eSchristos } 3213af12ab5eSchristos } 3214af12ab5eSchristos # endif /* HAVE_MLOCKALL */ 32152950cc38Schristos ntp_rlimit(RLIMIT_MEMLOCK, 32162950cc38Schristos (rlim_t)(rlimit_av->value.i * 1024 * 1024), 32172950cc38Schristos 1024 * 1024, 32182950cc38Schristos "MB"); 3219af12ab5eSchristos cur_memlock = 1; 32202950cc38Schristos #else 32212950cc38Schristos /* STDERR as well would be fine... */ 32222950cc38Schristos msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system."); 32232950cc38Schristos #endif /* RLIMIT_MEMLOCK */ 32242950cc38Schristos } else { 3225af12ab5eSchristos msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i); 32262950cc38Schristos } 32272950cc38Schristos break; 32282950cc38Schristos 32292950cc38Schristos case T_Stacksize: 32302950cc38Schristos #if defined(RLIMIT_STACK) 32312950cc38Schristos ntp_rlimit(RLIMIT_STACK, 32322950cc38Schristos (rlim_t)(rlimit_av->value.i * 4096), 32332950cc38Schristos 4096, 32342950cc38Schristos "4k"); 32352950cc38Schristos #else 32362950cc38Schristos /* STDERR as well would be fine... */ 32372950cc38Schristos msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system."); 32382950cc38Schristos #endif /* RLIMIT_STACK */ 32392950cc38Schristos break; 32402950cc38Schristos 32412950cc38Schristos case T_Filenum: 32422950cc38Schristos #if defined(RLIMIT_NOFILE) 32432950cc38Schristos ntp_rlimit(RLIMIT_NOFILE, 32442950cc38Schristos (rlim_t)(rlimit_av->value.i), 32452950cc38Schristos 1, 32462950cc38Schristos ""); 32472950cc38Schristos #else 32482950cc38Schristos /* STDERR as well would be fine... */ 32492950cc38Schristos msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system."); 32502950cc38Schristos #endif /* RLIMIT_NOFILE */ 32512950cc38Schristos break; 32522950cc38Schristos 32532950cc38Schristos } 32542950cc38Schristos } 32552950cc38Schristos } 32562950cc38Schristos 32572950cc38Schristos 32582950cc38Schristos static void 32592950cc38Schristos config_tinker( 32602950cc38Schristos config_tree *ptree 32612950cc38Schristos ) 32622950cc38Schristos { 32632950cc38Schristos attr_val * tinker; 32642950cc38Schristos int item; 32652950cc38Schristos 32662950cc38Schristos tinker = HEAD_PFIFO(ptree->tinker); 32672950cc38Schristos for (; tinker != NULL; tinker = tinker->link) { 3268abb0f93cSkardel switch (tinker->attr) { 3269abb0f93cSkardel 3270abb0f93cSkardel default: 3271ccc794f0Schristos fatal_error("config_tinker: attr-token=%d", tinker->attr); 3272abb0f93cSkardel 3273abb0f93cSkardel case T_Allan: 3274abb0f93cSkardel item = LOOP_ALLAN; 3275abb0f93cSkardel break; 3276abb0f93cSkardel 3277abb0f93cSkardel case T_Dispersion: 3278abb0f93cSkardel item = LOOP_PHI; 3279abb0f93cSkardel break; 3280abb0f93cSkardel 3281abb0f93cSkardel case T_Freq: 3282abb0f93cSkardel item = LOOP_FREQ; 3283abb0f93cSkardel break; 3284abb0f93cSkardel 3285abb0f93cSkardel case T_Huffpuff: 3286abb0f93cSkardel item = LOOP_HUFFPUFF; 3287abb0f93cSkardel break; 3288abb0f93cSkardel 3289abb0f93cSkardel case T_Panic: 3290abb0f93cSkardel item = LOOP_PANIC; 3291abb0f93cSkardel break; 3292abb0f93cSkardel 3293abb0f93cSkardel case T_Step: 3294abb0f93cSkardel item = LOOP_MAX; 3295abb0f93cSkardel break; 3296abb0f93cSkardel 32977476e6e4Schristos case T_Stepback: 32987476e6e4Schristos item = LOOP_MAX_BACK; 32997476e6e4Schristos break; 33007476e6e4Schristos 33017476e6e4Schristos case T_Stepfwd: 33027476e6e4Schristos item = LOOP_MAX_FWD; 33037476e6e4Schristos break; 33047476e6e4Schristos 3305abb0f93cSkardel case T_Stepout: 3306abb0f93cSkardel item = LOOP_MINSTEP; 3307abb0f93cSkardel break; 33082950cc38Schristos 33092950cc38Schristos case T_Tick: 33102950cc38Schristos item = LOOP_TICK; 33112950cc38Schristos break; 3312abb0f93cSkardel } 3313abb0f93cSkardel loop_config(item, tinker->value.d); 3314abb0f93cSkardel } 3315abb0f93cSkardel } 3316abb0f93cSkardel 3317abb0f93cSkardel 3318abb0f93cSkardel #ifdef FREE_CFG_T 3319abb0f93cSkardel static void 33202950cc38Schristos free_config_rlimit( 33212950cc38Schristos config_tree *ptree 3322abb0f93cSkardel ) 3323abb0f93cSkardel { 33242950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->rlimit); 33252950cc38Schristos } 3326abb0f93cSkardel 33272950cc38Schristos static void 33282950cc38Schristos free_config_tinker( 33292950cc38Schristos config_tree *ptree 33302950cc38Schristos ) 33312950cc38Schristos { 33322950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->tinker); 3333abb0f93cSkardel } 3334abb0f93cSkardel #endif /* FREE_CFG_T */ 3335abb0f93cSkardel 3336abb0f93cSkardel 3337abb0f93cSkardel /* 3338abb0f93cSkardel * config_nic_rules - apply interface listen/ignore/drop items 3339abb0f93cSkardel */ 33402950cc38Schristos #ifndef SIM 3341ea66d795Schristos static void 3342abb0f93cSkardel config_nic_rules( 33435d681e99Schristos config_tree *ptree, 33445d681e99Schristos int/*BOOL*/ input_from_file 3345abb0f93cSkardel ) 3346abb0f93cSkardel { 3347abb0f93cSkardel nic_rule_node * curr_node; 33483123f114Skardel sockaddr_u addr; 3349abb0f93cSkardel nic_rule_match match_type; 3350abb0f93cSkardel nic_rule_action action; 3351abb0f93cSkardel char * if_name; 3352abb0f93cSkardel char * pchSlash; 3353abb0f93cSkardel int prefixlen; 33543123f114Skardel int addrbits; 3355abb0f93cSkardel 33562950cc38Schristos curr_node = HEAD_PFIFO(ptree->nic_rules); 3357abb0f93cSkardel 3358abb0f93cSkardel if (curr_node != NULL 3359abb0f93cSkardel && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) { 3360abb0f93cSkardel msyslog(LOG_ERR, 3361abb0f93cSkardel "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s", 3362abb0f93cSkardel (input_from_file) ? ", exiting" : ""); 3363abb0f93cSkardel if (input_from_file) 3364abb0f93cSkardel exit(1); 3365abb0f93cSkardel else 3366abb0f93cSkardel return; 3367abb0f93cSkardel } 3368abb0f93cSkardel 33692950cc38Schristos for (; curr_node != NULL; curr_node = curr_node->link) { 3370abb0f93cSkardel prefixlen = -1; 3371abb0f93cSkardel if_name = curr_node->if_name; 3372abb0f93cSkardel if (if_name != NULL) 3373abb0f93cSkardel if_name = estrdup(if_name); 3374abb0f93cSkardel 3375abb0f93cSkardel switch (curr_node->match_class) { 3376abb0f93cSkardel default: 3377*eabc0478Schristos #ifdef DEBUG 3378ccc794f0Schristos fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class); 3379*eabc0478Schristos #endif 3380*eabc0478Schristos case T_All: 3381*eabc0478Schristos match_type = MATCH_ALL; 3382*eabc0478Schristos break; 3383abb0f93cSkardel 3384abb0f93cSkardel case 0: 3385abb0f93cSkardel /* 3386abb0f93cSkardel * 0 is out of range for valid token T_... 3387abb0f93cSkardel * and in a nic_rules_node indicates the 3388abb0f93cSkardel * interface descriptor is either a name or 3389abb0f93cSkardel * address, stored in if_name in either case. 3390abb0f93cSkardel */ 33912950cc38Schristos INSIST(if_name != NULL); 3392abb0f93cSkardel pchSlash = strchr(if_name, '/'); 3393abb0f93cSkardel if (pchSlash != NULL) 3394abb0f93cSkardel *pchSlash = '\0'; 33952950cc38Schristos if (is_ip_address(if_name, AF_UNSPEC, &addr)) { 3396abb0f93cSkardel match_type = MATCH_IFADDR; 33972950cc38Schristos if (pchSlash != NULL 33982950cc38Schristos && 1 == sscanf(pchSlash + 1, "%d", 33992950cc38Schristos &prefixlen)) { 34003123f114Skardel addrbits = 8 * 34013123f114Skardel SIZEOF_INADDR(AF(&addr)); 3402abb0f93cSkardel prefixlen = max(-1, prefixlen); 3403abb0f93cSkardel prefixlen = min(prefixlen, 34043123f114Skardel addrbits); 3405abb0f93cSkardel } 3406abb0f93cSkardel } else { 3407abb0f93cSkardel match_type = MATCH_IFNAME; 3408abb0f93cSkardel if (pchSlash != NULL) 3409abb0f93cSkardel *pchSlash = '/'; 3410abb0f93cSkardel } 3411abb0f93cSkardel break; 3412abb0f93cSkardel 3413abb0f93cSkardel case T_Ipv4: 3414abb0f93cSkardel match_type = MATCH_IPV4; 3415abb0f93cSkardel break; 3416abb0f93cSkardel 3417abb0f93cSkardel case T_Ipv6: 3418abb0f93cSkardel match_type = MATCH_IPV6; 3419abb0f93cSkardel break; 3420abb0f93cSkardel 3421abb0f93cSkardel case T_Wildcard: 3422abb0f93cSkardel match_type = MATCH_WILDCARD; 3423abb0f93cSkardel break; 3424abb0f93cSkardel } 3425abb0f93cSkardel 3426abb0f93cSkardel switch (curr_node->action) { 3427abb0f93cSkardel default: 3428*eabc0478Schristos #ifdef DEBUG 3429ccc794f0Schristos fatal_error("config_nic_rules: action-token=%d", curr_node->action); 3430*eabc0478Schristos #endif 3431abb0f93cSkardel case T_Listen: 3432abb0f93cSkardel action = ACTION_LISTEN; 3433abb0f93cSkardel break; 3434abb0f93cSkardel 3435abb0f93cSkardel case T_Ignore: 3436abb0f93cSkardel action = ACTION_IGNORE; 3437abb0f93cSkardel break; 3438abb0f93cSkardel 3439abb0f93cSkardel case T_Drop: 3440abb0f93cSkardel action = ACTION_DROP; 3441abb0f93cSkardel break; 3442abb0f93cSkardel } 3443abb0f93cSkardel 3444abb0f93cSkardel add_nic_rule(match_type, if_name, prefixlen, 3445abb0f93cSkardel action); 3446*eabc0478Schristos if (!initializing && !scan_addrs_once) { 3447*eabc0478Schristos endpt_scan_timer = 1 + current_time; 3448*eabc0478Schristos } 3449abb0f93cSkardel if (if_name != NULL) 3450abb0f93cSkardel free(if_name); 3451abb0f93cSkardel } 3452abb0f93cSkardel } 34532950cc38Schristos #endif /* !SIM */ 3454abb0f93cSkardel 3455abb0f93cSkardel 3456abb0f93cSkardel #ifdef FREE_CFG_T 3457abb0f93cSkardel static void 3458abb0f93cSkardel free_config_nic_rules( 34592950cc38Schristos config_tree *ptree 3460abb0f93cSkardel ) 3461abb0f93cSkardel { 3462abb0f93cSkardel nic_rule_node *curr_node; 3463abb0f93cSkardel 34642950cc38Schristos if (ptree->nic_rules != NULL) { 3465ea66d795Schristos for (;;) { 34662950cc38Schristos UNLINK_FIFO(curr_node, *ptree->nic_rules, link); 34672950cc38Schristos if (NULL == curr_node) 34682950cc38Schristos break; 3469abb0f93cSkardel free(curr_node->if_name); 34702950cc38Schristos free(curr_node); 3471abb0f93cSkardel } 34722950cc38Schristos free(ptree->nic_rules); 34732950cc38Schristos ptree->nic_rules = NULL; 34742950cc38Schristos } 3475abb0f93cSkardel } 3476abb0f93cSkardel #endif /* FREE_CFG_T */ 3477abb0f93cSkardel 3478abb0f93cSkardel 3479abb0f93cSkardel static void 3480abb0f93cSkardel apply_enable_disable( 34812950cc38Schristos attr_val_fifo * fifo, 3482abb0f93cSkardel int enable 3483abb0f93cSkardel ) 3484abb0f93cSkardel { 34854eea345dSchristos attr_val *curr_tok_fifo; 3486abb0f93cSkardel int option; 3487abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3488abb0f93cSkardel bc_entry *pentry; 3489abb0f93cSkardel #endif 3490abb0f93cSkardel 34914eea345dSchristos for (curr_tok_fifo = HEAD_PFIFO(fifo); 34924eea345dSchristos curr_tok_fifo != NULL; 34934eea345dSchristos curr_tok_fifo = curr_tok_fifo->link) { 3494abb0f93cSkardel 34954eea345dSchristos option = curr_tok_fifo->value.i; 3496abb0f93cSkardel switch (option) { 3497abb0f93cSkardel 3498abb0f93cSkardel default: 3499abb0f93cSkardel msyslog(LOG_ERR, 3500abb0f93cSkardel "can not apply enable/disable token %d, unknown", 3501abb0f93cSkardel option); 3502abb0f93cSkardel break; 3503abb0f93cSkardel 3504abb0f93cSkardel case T_Auth: 3505abb0f93cSkardel proto_config(PROTO_AUTHENTICATE, enable, 0., NULL); 3506abb0f93cSkardel break; 3507abb0f93cSkardel 3508abb0f93cSkardel case T_Bclient: 3509abb0f93cSkardel proto_config(PROTO_BROADCLIENT, enable, 0., NULL); 3510abb0f93cSkardel break; 3511abb0f93cSkardel 3512abb0f93cSkardel case T_Calibrate: 3513abb0f93cSkardel proto_config(PROTO_CAL, enable, 0., NULL); 3514abb0f93cSkardel break; 3515abb0f93cSkardel 3516abb0f93cSkardel case T_Kernel: 3517abb0f93cSkardel proto_config(PROTO_KERNEL, enable, 0., NULL); 3518abb0f93cSkardel break; 3519abb0f93cSkardel 3520abb0f93cSkardel case T_Monitor: 3521abb0f93cSkardel proto_config(PROTO_MONITOR, enable, 0., NULL); 3522abb0f93cSkardel break; 3523abb0f93cSkardel 3524717847f5Schristos case T_Mode7: 3525717847f5Schristos proto_config(PROTO_MODE7, enable, 0., NULL); 3526717847f5Schristos break; 3527717847f5Schristos 3528abb0f93cSkardel case T_Ntp: 3529abb0f93cSkardel proto_config(PROTO_NTP, enable, 0., NULL); 3530abb0f93cSkardel break; 3531abb0f93cSkardel 3532717847f5Schristos case T_PCEdigest: 3533717847f5Schristos proto_config(PROTO_PCEDIGEST, enable, 0., NULL); 35342950cc38Schristos break; 35352950cc38Schristos 3536abb0f93cSkardel case T_Stats: 3537abb0f93cSkardel proto_config(PROTO_FILEGEN, enable, 0., NULL); 3538abb0f93cSkardel break; 3539abb0f93cSkardel 354068dbbb44Schristos case T_UEcrypto: 354168dbbb44Schristos proto_config(PROTO_UECRYPTO, enable, 0., NULL); 354268dbbb44Schristos break; 354368dbbb44Schristos 354468dbbb44Schristos case T_UEcryptonak: 354568dbbb44Schristos proto_config(PROTO_UECRYPTONAK, enable, 0., NULL); 354668dbbb44Schristos break; 354768dbbb44Schristos 354868dbbb44Schristos case T_UEdigest: 354968dbbb44Schristos proto_config(PROTO_UEDIGEST, enable, 0., NULL); 355068dbbb44Schristos break; 355168dbbb44Schristos 3552abb0f93cSkardel #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED 3553abb0f93cSkardel case T_Bc_bugXXXX: 3554abb0f93cSkardel pentry = bc_list; 3555abb0f93cSkardel while (pentry->token) { 3556abb0f93cSkardel if (pentry->token == option) 3557abb0f93cSkardel break; 3558abb0f93cSkardel pentry++; 3559abb0f93cSkardel } 3560abb0f93cSkardel if (!pentry->token) { 3561abb0f93cSkardel msyslog(LOG_ERR, 3562abb0f93cSkardel "compat token %d not in bc_list[]", 3563abb0f93cSkardel option); 3564abb0f93cSkardel continue; 3565abb0f93cSkardel } 3566abb0f93cSkardel pentry->enabled = enable; 3567abb0f93cSkardel break; 3568abb0f93cSkardel #endif 3569abb0f93cSkardel } 3570abb0f93cSkardel } 3571abb0f93cSkardel } 3572abb0f93cSkardel 3573abb0f93cSkardel 3574abb0f93cSkardel static void 3575abb0f93cSkardel config_system_opts( 35762950cc38Schristos config_tree *ptree 3577abb0f93cSkardel ) 3578abb0f93cSkardel { 3579abb0f93cSkardel apply_enable_disable(ptree->enable_opts, 1); 3580abb0f93cSkardel apply_enable_disable(ptree->disable_opts, 0); 3581abb0f93cSkardel } 3582abb0f93cSkardel 3583abb0f93cSkardel 3584abb0f93cSkardel #ifdef FREE_CFG_T 3585abb0f93cSkardel static void 3586abb0f93cSkardel free_config_system_opts( 35872950cc38Schristos config_tree *ptree 3588abb0f93cSkardel ) 3589abb0f93cSkardel { 35902950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->enable_opts); 35912950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->disable_opts); 3592abb0f93cSkardel } 3593abb0f93cSkardel #endif /* FREE_CFG_T */ 3594abb0f93cSkardel 3595abb0f93cSkardel 3596abb0f93cSkardel static void 3597abb0f93cSkardel config_logconfig( 35982950cc38Schristos config_tree *ptree 3599abb0f93cSkardel ) 3600abb0f93cSkardel { 36012950cc38Schristos attr_val * my_lc; 3602abb0f93cSkardel 36032950cc38Schristos my_lc = HEAD_PFIFO(ptree->logconfig); 36042950cc38Schristos for (; my_lc != NULL; my_lc = my_lc->link) { 36052950cc38Schristos switch (my_lc->attr) { 3606abb0f93cSkardel 3607abb0f93cSkardel case '+': 36082950cc38Schristos ntp_syslogmask |= get_logmask(my_lc->value.s); 3609abb0f93cSkardel break; 36102950cc38Schristos 3611abb0f93cSkardel case '-': 36122950cc38Schristos ntp_syslogmask &= ~get_logmask(my_lc->value.s); 3613abb0f93cSkardel break; 36142950cc38Schristos 3615abb0f93cSkardel case '=': 36162950cc38Schristos ntp_syslogmask = get_logmask(my_lc->value.s); 3617abb0f93cSkardel break; 3618ea66d795Schristos default: 3619ccc794f0Schristos fatal_error("config-logconfig: modifier='%c'", my_lc->attr); 3620abb0f93cSkardel } 3621abb0f93cSkardel } 3622abb0f93cSkardel } 3623abb0f93cSkardel 3624abb0f93cSkardel 3625abb0f93cSkardel #ifdef FREE_CFG_T 3626abb0f93cSkardel static void 3627abb0f93cSkardel free_config_logconfig( 36282950cc38Schristos config_tree *ptree 3629abb0f93cSkardel ) 3630abb0f93cSkardel { 36312950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->logconfig); 3632abb0f93cSkardel } 3633abb0f93cSkardel #endif /* FREE_CFG_T */ 3634abb0f93cSkardel 3635abb0f93cSkardel 36362950cc38Schristos #ifndef SIM 3637abb0f93cSkardel static void 3638abb0f93cSkardel config_phone( 36392950cc38Schristos config_tree *ptree 3640abb0f93cSkardel ) 3641abb0f93cSkardel { 36422950cc38Schristos size_t i; 36432950cc38Schristos string_node * sn; 3644abb0f93cSkardel 36452950cc38Schristos i = 0; 36462950cc38Schristos sn = HEAD_PFIFO(ptree->phone); 36472950cc38Schristos for (; sn != NULL; sn = sn->link) { 36482950cc38Schristos /* need to leave array entry for NULL terminator */ 36493123f114Skardel if (i < COUNTOF(sys_phone) - 1) { 36502950cc38Schristos sys_phone[i++] = estrdup(sn->s); 36513123f114Skardel sys_phone[i] = NULL; 36523123f114Skardel } else { 3653abb0f93cSkardel msyslog(LOG_INFO, 36542950cc38Schristos "phone: Number of phone entries exceeds %zu. Ignoring phone %s...", 36552950cc38Schristos (COUNTOF(sys_phone) - 1), sn->s); 3656abb0f93cSkardel } 3657abb0f93cSkardel } 36582950cc38Schristos } 3659abb0f93cSkardel 3660a04a202dSchristos static void 3661a04a202dSchristos config_mdnstries( 3662a04a202dSchristos config_tree *ptree 3663a04a202dSchristos ) 3664a04a202dSchristos { 3665a04a202dSchristos #ifdef HAVE_DNSREGISTRATION 3666a04a202dSchristos extern int mdnstries; 3667a04a202dSchristos mdnstries = ptree->mdnstries; 3668a04a202dSchristos #endif /* HAVE_DNSREGISTRATION */ 3669a04a202dSchristos } 3670*eabc0478Schristos #endif /* !SIM */ 3671abb0f93cSkardel 3672abb0f93cSkardel #ifdef FREE_CFG_T 3673abb0f93cSkardel static void 3674abb0f93cSkardel free_config_phone( 36752950cc38Schristos config_tree *ptree 3676abb0f93cSkardel ) 3677abb0f93cSkardel { 36782950cc38Schristos FREE_STRING_FIFO(ptree->phone); 3679abb0f93cSkardel } 3680abb0f93cSkardel #endif /* FREE_CFG_T */ 3681abb0f93cSkardel 3682abb0f93cSkardel 36832950cc38Schristos #ifndef SIM 3684abb0f93cSkardel static void 3685abb0f93cSkardel config_setvar( 36862950cc38Schristos config_tree *ptree 3687abb0f93cSkardel ) 3688abb0f93cSkardel { 36892950cc38Schristos setvar_node *my_node; 3690abb0f93cSkardel size_t varlen, vallen, octets; 3691abb0f93cSkardel char * str; 3692abb0f93cSkardel 3693abb0f93cSkardel str = NULL; 36942950cc38Schristos my_node = HEAD_PFIFO(ptree->setvar); 36952950cc38Schristos for (; my_node != NULL; my_node = my_node->link) { 3696abb0f93cSkardel varlen = strlen(my_node->var); 3697abb0f93cSkardel vallen = strlen(my_node->val); 3698abb0f93cSkardel octets = varlen + vallen + 1 + 1; 3699abb0f93cSkardel str = erealloc(str, octets); 3700abb0f93cSkardel snprintf(str, octets, "%s=%s", my_node->var, 3701abb0f93cSkardel my_node->val); 3702abb0f93cSkardel set_sys_var(str, octets, (my_node->isdefault) 3703abb0f93cSkardel ? DEF 3704abb0f93cSkardel : 0); 3705abb0f93cSkardel } 3706abb0f93cSkardel if (str != NULL) 3707abb0f93cSkardel free(str); 3708abb0f93cSkardel } 37092950cc38Schristos #endif /* !SIM */ 3710abb0f93cSkardel 3711abb0f93cSkardel 3712abb0f93cSkardel #ifdef FREE_CFG_T 3713abb0f93cSkardel static void 3714abb0f93cSkardel free_config_setvar( 37152950cc38Schristos config_tree *ptree 3716abb0f93cSkardel ) 3717abb0f93cSkardel { 37182950cc38Schristos FREE_SETVAR_FIFO(ptree->setvar); 3719abb0f93cSkardel } 3720abb0f93cSkardel #endif /* FREE_CFG_T */ 3721abb0f93cSkardel 3722abb0f93cSkardel 37232950cc38Schristos #ifndef SIM 3724abb0f93cSkardel static void 3725abb0f93cSkardel config_ttl( 37262950cc38Schristos config_tree *ptree 3727abb0f93cSkardel ) 3728abb0f93cSkardel { 3729e19314b7Schristos size_t i = 0; 37302950cc38Schristos int_node *curr_ttl; 3731abb0f93cSkardel 373279045f13Schristos /* [Bug 3465] There is a built-in default for the TTLs. We must 373379045f13Schristos * overwrite 'sys_ttlmax' if we change that preset, and leave it 373479045f13Schristos * alone otherwise! 373579045f13Schristos */ 37362950cc38Schristos curr_ttl = HEAD_PFIFO(ptree->ttl); 37372950cc38Schristos for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) { 3738abb0f93cSkardel if (i < COUNTOF(sys_ttl)) 37392950cc38Schristos sys_ttl[i++] = (u_char)curr_ttl->i; 3740abb0f93cSkardel else 3741abb0f93cSkardel msyslog(LOG_INFO, 37422950cc38Schristos "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...", 37432950cc38Schristos COUNTOF(sys_ttl), curr_ttl->i); 3744abb0f93cSkardel } 374579045f13Schristos if (0 != i) /* anything written back at all? */ 374679045f13Schristos sys_ttlmax = i - 1; 3747abb0f93cSkardel } 37482950cc38Schristos #endif /* !SIM */ 3749abb0f93cSkardel 3750abb0f93cSkardel 3751abb0f93cSkardel #ifdef FREE_CFG_T 3752abb0f93cSkardel static void 3753abb0f93cSkardel free_config_ttl( 37542950cc38Schristos config_tree *ptree 3755abb0f93cSkardel ) 3756abb0f93cSkardel { 37572950cc38Schristos FREE_INT_FIFO(ptree->ttl); 3758abb0f93cSkardel } 3759abb0f93cSkardel #endif /* FREE_CFG_T */ 3760abb0f93cSkardel 3761abb0f93cSkardel 37622950cc38Schristos #ifndef SIM 3763abb0f93cSkardel static void 3764abb0f93cSkardel config_trap( 37652950cc38Schristos config_tree *ptree 3766abb0f93cSkardel ) 3767abb0f93cSkardel { 37682950cc38Schristos addr_opts_node *curr_trap; 37692950cc38Schristos attr_val *curr_opt; 3770abb0f93cSkardel sockaddr_u addr_sock; 3771abb0f93cSkardel sockaddr_u peeraddr; 3772*eabc0478Schristos endpt *localaddr; 37732950cc38Schristos struct addrinfo hints; 37742950cc38Schristos char port_text[8]; 37752950cc38Schristos settrap_parms *pstp; 37762950cc38Schristos u_short port; 3777abb0f93cSkardel int err_flag; 37782950cc38Schristos int rc; 3779abb0f93cSkardel 3780abb0f93cSkardel /* silence warning about addr_sock potentially uninitialized */ 3781abb0f93cSkardel AF(&addr_sock) = AF_UNSPEC; 3782abb0f93cSkardel 37832950cc38Schristos curr_trap = HEAD_PFIFO(ptree->trap); 37842950cc38Schristos for (; curr_trap != NULL; curr_trap = curr_trap->link) { 3785abb0f93cSkardel err_flag = 0; 37862950cc38Schristos port = 0; 3787abb0f93cSkardel localaddr = NULL; 3788abb0f93cSkardel 37892950cc38Schristos curr_opt = HEAD_PFIFO(curr_trap->options); 37902950cc38Schristos for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3791abb0f93cSkardel if (T_Port == curr_opt->attr) { 3792abb0f93cSkardel if (curr_opt->value.i < 1 3793abb0f93cSkardel || curr_opt->value.i > USHRT_MAX) { 3794abb0f93cSkardel msyslog(LOG_ERR, 3795abb0f93cSkardel "invalid port number " 3796abb0f93cSkardel "%d, trap ignored", 3797abb0f93cSkardel curr_opt->value.i); 3798abb0f93cSkardel err_flag = 1; 3799abb0f93cSkardel } 38002950cc38Schristos port = (u_short)curr_opt->value.i; 3801abb0f93cSkardel } 3802abb0f93cSkardel else if (T_Interface == curr_opt->attr) { 3803abb0f93cSkardel /* Resolve the interface address */ 3804abb0f93cSkardel ZERO_SOCK(&addr_sock); 38052950cc38Schristos if (getnetnum(curr_opt->value.s, 3806abb0f93cSkardel &addr_sock, 1, t_UNK) != 1) { 3807abb0f93cSkardel err_flag = 1; 3808abb0f93cSkardel break; 3809abb0f93cSkardel } 3810abb0f93cSkardel 3811abb0f93cSkardel localaddr = findinterface(&addr_sock); 3812abb0f93cSkardel 3813abb0f93cSkardel if (NULL == localaddr) { 3814abb0f93cSkardel msyslog(LOG_ERR, 3815abb0f93cSkardel "can't find interface with address %s", 3816abb0f93cSkardel stoa(&addr_sock)); 3817abb0f93cSkardel err_flag = 1; 3818abb0f93cSkardel } 3819abb0f93cSkardel } 3820abb0f93cSkardel } 3821abb0f93cSkardel 3822abb0f93cSkardel /* Now process the trap for the specified interface 3823abb0f93cSkardel * and port number 3824abb0f93cSkardel */ 3825abb0f93cSkardel if (!err_flag) { 38262950cc38Schristos if (!port) 38272950cc38Schristos port = TRAPPORT; 3828abb0f93cSkardel ZERO_SOCK(&peeraddr); 38292950cc38Schristos rc = getnetnum(curr_trap->addr->address, 38302950cc38Schristos &peeraddr, 1, t_UNK); 38312950cc38Schristos if (1 != rc) { 38322950cc38Schristos #ifndef WORKER 38332950cc38Schristos msyslog(LOG_ERR, 38342950cc38Schristos "trap: unable to use IP address %s.", 38352950cc38Schristos curr_trap->addr->address); 38362950cc38Schristos #else /* WORKER follows */ 38372950cc38Schristos /* 38382950cc38Schristos * save context and hand it off 38392950cc38Schristos * for name resolution. 38402950cc38Schristos */ 38412950cc38Schristos ZERO(hints); 38422950cc38Schristos hints.ai_protocol = IPPROTO_UDP; 38432950cc38Schristos hints.ai_socktype = SOCK_DGRAM; 38442950cc38Schristos snprintf(port_text, sizeof(port_text), 38452950cc38Schristos "%u", port); 38462950cc38Schristos hints.ai_flags = Z_AI_NUMERICSERV; 38472950cc38Schristos pstp = emalloc_zero(sizeof(*pstp)); 38482950cc38Schristos if (localaddr != NULL) { 38492950cc38Schristos hints.ai_family = localaddr->family; 38502950cc38Schristos pstp->ifaddr_nonnull = 1; 38512950cc38Schristos memcpy(&pstp->ifaddr, 38522950cc38Schristos &localaddr->sin, 38532950cc38Schristos sizeof(pstp->ifaddr)); 38542950cc38Schristos } 38552950cc38Schristos rc = getaddrinfo_sometime( 38562950cc38Schristos curr_trap->addr->address, 38572950cc38Schristos port_text, &hints, 38582950cc38Schristos INITIAL_DNS_RETRY, 38592950cc38Schristos &trap_name_resolved, 38602950cc38Schristos pstp); 38612950cc38Schristos if (!rc) 38622950cc38Schristos msyslog(LOG_ERR, 38632950cc38Schristos "config_trap: getaddrinfo_sometime(%s,%s): %m", 38642950cc38Schristos curr_trap->addr->address, 38652950cc38Schristos port_text); 38662950cc38Schristos #endif /* WORKER */ 3867abb0f93cSkardel continue; 38682950cc38Schristos } 3869abb0f93cSkardel /* port is at same location for v4 and v6 */ 38702950cc38Schristos SET_PORT(&peeraddr, port); 3871abb0f93cSkardel 38723123f114Skardel if (NULL == localaddr) 3873abb0f93cSkardel localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 38743123f114Skardel else 3875abb0f93cSkardel AF(&peeraddr) = AF(&addr_sock); 3876abb0f93cSkardel 3877abb0f93cSkardel if (!ctlsettrap(&peeraddr, localaddr, 0, 3878abb0f93cSkardel NTP_VERSION)) 3879abb0f93cSkardel msyslog(LOG_ERR, 38802950cc38Schristos "set trap %s -> %s failed.", 38812950cc38Schristos latoa(localaddr), 3882abb0f93cSkardel stoa(&peeraddr)); 3883abb0f93cSkardel } 3884abb0f93cSkardel } 3885abb0f93cSkardel } 3886abb0f93cSkardel 3887abb0f93cSkardel 38882950cc38Schristos /* 38892950cc38Schristos * trap_name_resolved() 38902950cc38Schristos * 38912950cc38Schristos * Callback invoked when config_trap()'s DNS lookup completes. 38922950cc38Schristos */ 38932950cc38Schristos # ifdef WORKER 3894ea66d795Schristos static void 38952950cc38Schristos trap_name_resolved( 38962950cc38Schristos int rescode, 38972950cc38Schristos int gai_errno, 38982950cc38Schristos void * context, 38992950cc38Schristos const char * name, 39002950cc38Schristos const char * service, 39012950cc38Schristos const struct addrinfo * hints, 39022950cc38Schristos const struct addrinfo * res 39032950cc38Schristos ) 39042950cc38Schristos { 39052950cc38Schristos settrap_parms *pstp; 3906*eabc0478Schristos endpt *localaddr; 39072950cc38Schristos sockaddr_u peeraddr; 39082950cc38Schristos 3909ea66d795Schristos (void)gai_errno; 3910ea66d795Schristos (void)service; 3911ea66d795Schristos (void)hints; 39122950cc38Schristos pstp = context; 39132950cc38Schristos if (rescode) { 39142950cc38Schristos msyslog(LOG_ERR, 39152950cc38Schristos "giving up resolving trap host %s: %s (%d)", 39162950cc38Schristos name, gai_strerror(rescode), rescode); 39172950cc38Schristos free(pstp); 39182950cc38Schristos return; 39192950cc38Schristos } 3920ea66d795Schristos INSIST(sizeof(peeraddr) >= res->ai_addrlen); 39212950cc38Schristos ZERO(peeraddr); 39222950cc38Schristos memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 39232950cc38Schristos localaddr = NULL; 39242950cc38Schristos if (pstp->ifaddr_nonnull) 39252950cc38Schristos localaddr = findinterface(&pstp->ifaddr); 39262950cc38Schristos if (NULL == localaddr) 39272950cc38Schristos localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); 39282950cc38Schristos if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) 39292950cc38Schristos msyslog(LOG_ERR, "set trap %s -> %s failed.", 39302950cc38Schristos latoa(localaddr), stoa(&peeraddr)); 39312950cc38Schristos free(pstp); 39322950cc38Schristos } 39332950cc38Schristos # endif /* WORKER */ 39342950cc38Schristos #endif /* !SIM */ 39352950cc38Schristos 39362950cc38Schristos 3937abb0f93cSkardel #ifdef FREE_CFG_T 3938abb0f93cSkardel static void 3939abb0f93cSkardel free_config_trap( 39402950cc38Schristos config_tree *ptree 3941abb0f93cSkardel ) 3942abb0f93cSkardel { 39432950cc38Schristos FREE_ADDR_OPTS_FIFO(ptree->trap); 3944abb0f93cSkardel } 3945abb0f93cSkardel #endif /* FREE_CFG_T */ 3946abb0f93cSkardel 3947abb0f93cSkardel 39482950cc38Schristos #ifndef SIM 3949abb0f93cSkardel static void 3950abb0f93cSkardel config_fudge( 39512950cc38Schristos config_tree *ptree 3952abb0f93cSkardel ) 3953abb0f93cSkardel { 39542950cc38Schristos addr_opts_node *curr_fudge; 39552950cc38Schristos attr_val *curr_opt; 3956abb0f93cSkardel sockaddr_u addr_sock; 39572950cc38Schristos address_node *addr_node; 3958abb0f93cSkardel struct refclockstat clock_stat; 3959*eabc0478Schristos char refidstr[5]; 3960abb0f93cSkardel int err_flag; 3961abb0f93cSkardel 39622950cc38Schristos curr_fudge = HEAD_PFIFO(ptree->fudge); 39632950cc38Schristos for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) { 3964abb0f93cSkardel err_flag = 0; 3965abb0f93cSkardel 3966abb0f93cSkardel /* Get the reference clock address and 3967abb0f93cSkardel * ensure that it is sane 3968abb0f93cSkardel */ 3969abb0f93cSkardel addr_node = curr_fudge->addr; 3970abb0f93cSkardel ZERO_SOCK(&addr_sock); 3971abb0f93cSkardel if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 39722950cc38Schristos != 1) { 3973abb0f93cSkardel err_flag = 1; 39742950cc38Schristos msyslog(LOG_ERR, 39752950cc38Schristos "unrecognized fudge reference clock address %s, line ignored", 397679045f13Schristos addr_node->address); 397779045f13Schristos } else if (!ISREFCLOCKADR(&addr_sock)) { 39782950cc38Schristos err_flag = 1; 3979abb0f93cSkardel msyslog(LOG_ERR, 3980abb0f93cSkardel "inappropriate address %s for the fudge command, line ignored", 3981abb0f93cSkardel stoa(&addr_sock)); 3982abb0f93cSkardel } 3983abb0f93cSkardel 3984abb0f93cSkardel /* Parse all the options to the fudge command */ 39852950cc38Schristos ZERO(clock_stat); 3986cdfa2a7eSchristos /* some things are not necessarily cleared by ZERO...*/ 3987cdfa2a7eSchristos clock_stat.fudgeminjitter = 0.0; 3988cdfa2a7eSchristos clock_stat.fudgetime1 = 0.0; 3989cdfa2a7eSchristos clock_stat.fudgetime2 = 0.0; 39902950cc38Schristos curr_opt = HEAD_PFIFO(curr_fudge->options); 39912950cc38Schristos for (; curr_opt != NULL; curr_opt = curr_opt->link) { 3992abb0f93cSkardel switch (curr_opt->attr) { 39932950cc38Schristos 3994abb0f93cSkardel case T_Time1: 3995abb0f93cSkardel clock_stat.haveflags |= CLK_HAVETIME1; 3996abb0f93cSkardel clock_stat.fudgetime1 = curr_opt->value.d; 3997abb0f93cSkardel break; 39982950cc38Schristos 3999abb0f93cSkardel case T_Time2: 4000abb0f93cSkardel clock_stat.haveflags |= CLK_HAVETIME2; 4001abb0f93cSkardel clock_stat.fudgetime2 = curr_opt->value.d; 4002abb0f93cSkardel break; 40032950cc38Schristos 4004abb0f93cSkardel case T_Stratum: 4005abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEVAL1; 4006abb0f93cSkardel clock_stat.fudgeval1 = curr_opt->value.i; 4007abb0f93cSkardel break; 40082950cc38Schristos 4009abb0f93cSkardel case T_Refid: 4010abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEVAL2; 4011*eabc0478Schristos /* 4012*eabc0478Schristos * strncpy() does exactly what we want 4013*eabc0478Schristos * here, do not be tempted to replace 4014*eabc0478Schristos * it with strlcpy(), we want it to 4015*eabc0478Schristos * zero-fill refid's less than 4 chars 4016*eabc0478Schristos * because we're going to stuff it 4017*eabc0478Schristos * into a u_int32. 4018*eabc0478Schristos */ 4019*eabc0478Schristos strncpy(refidstr, curr_opt->value.s, 4020*eabc0478Schristos sizeof refidstr - 1); 4021*eabc0478Schristos memcpy(&clock_stat.fudgeval2, refidstr, 4022*eabc0478Schristos sizeof clock_stat.fudgeval2); 4023abb0f93cSkardel break; 40242950cc38Schristos 4025abb0f93cSkardel case T_Flag1: 4026abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEFLAG1; 4027abb0f93cSkardel if (curr_opt->value.i) 4028abb0f93cSkardel clock_stat.flags |= CLK_FLAG1; 4029abb0f93cSkardel else 4030abb0f93cSkardel clock_stat.flags &= ~CLK_FLAG1; 4031abb0f93cSkardel break; 40322950cc38Schristos 4033abb0f93cSkardel case T_Flag2: 4034abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEFLAG2; 4035abb0f93cSkardel if (curr_opt->value.i) 4036abb0f93cSkardel clock_stat.flags |= CLK_FLAG2; 4037abb0f93cSkardel else 4038abb0f93cSkardel clock_stat.flags &= ~CLK_FLAG2; 4039abb0f93cSkardel break; 40402950cc38Schristos 4041abb0f93cSkardel case T_Flag3: 4042abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEFLAG3; 4043abb0f93cSkardel if (curr_opt->value.i) 4044abb0f93cSkardel clock_stat.flags |= CLK_FLAG3; 4045abb0f93cSkardel else 4046abb0f93cSkardel clock_stat.flags &= ~CLK_FLAG3; 4047abb0f93cSkardel break; 40482950cc38Schristos 4049abb0f93cSkardel case T_Flag4: 4050abb0f93cSkardel clock_stat.haveflags |= CLK_HAVEFLAG4; 4051abb0f93cSkardel if (curr_opt->value.i) 4052abb0f93cSkardel clock_stat.flags |= CLK_FLAG4; 4053abb0f93cSkardel else 4054abb0f93cSkardel clock_stat.flags &= ~CLK_FLAG4; 4055abb0f93cSkardel break; 40562950cc38Schristos 4057cdfa2a7eSchristos case T_Minjitter: 4058cdfa2a7eSchristos clock_stat.haveflags |= CLK_HAVEMINJIT; 4059cdfa2a7eSchristos clock_stat.fudgeminjitter = curr_opt->value.d; 4060cdfa2a7eSchristos break; 4061cdfa2a7eSchristos 4062abb0f93cSkardel default: 4063abb0f93cSkardel msyslog(LOG_ERR, 40642950cc38Schristos "Unexpected fudge flag %s (%d) for %s", 40652950cc38Schristos token_name(curr_opt->attr), 406679045f13Schristos curr_opt->attr, addr_node->address); 4067abb0f93cSkardel exit(curr_opt->attr ? curr_opt->attr : 1); 4068abb0f93cSkardel } 4069abb0f93cSkardel } 4070abb0f93cSkardel # ifdef REFCLOCK 4071abb0f93cSkardel if (!err_flag) 40722950cc38Schristos refclock_control(&addr_sock, &clock_stat, NULL); 4073abb0f93cSkardel # endif 4074abb0f93cSkardel } 4075abb0f93cSkardel } 40762950cc38Schristos #endif /* !SIM */ 4077abb0f93cSkardel 4078*eabc0478Schristos #ifndef SIM 4079*eabc0478Schristos static void 4080*eabc0478Schristos config_device( 4081*eabc0478Schristos config_tree *ptree 4082*eabc0478Schristos ) 4083*eabc0478Schristos { 4084*eabc0478Schristos addr_opts_node *curr_device; 4085*eabc0478Schristos attr_val *curr_opt; 4086*eabc0478Schristos sockaddr_u addr_sock; 4087*eabc0478Schristos address_node *addr_node; 4088*eabc0478Schristos char *ttyName, *ppsName; 4089*eabc0478Schristos 4090*eabc0478Schristos curr_device = HEAD_PFIFO(ptree->device); 4091*eabc0478Schristos for (; curr_device != NULL; curr_device = curr_device->link) { 4092*eabc0478Schristos /* Get the reference clock address and 4093*eabc0478Schristos * ensure that it is sane 4094*eabc0478Schristos */ 4095*eabc0478Schristos addr_node = curr_device->addr; 4096*eabc0478Schristos ZERO_SOCK(&addr_sock); 4097*eabc0478Schristos if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) 4098*eabc0478Schristos != 1) { 4099*eabc0478Schristos msyslog(LOG_ERR, 4100*eabc0478Schristos "unrecognized device reference clock address %s, line ignored", 4101*eabc0478Schristos addr_node->address); 4102*eabc0478Schristos continue; 4103*eabc0478Schristos } 4104*eabc0478Schristos if (!ISREFCLOCKADR(&addr_sock)) { 4105*eabc0478Schristos msyslog(LOG_ERR, 4106*eabc0478Schristos "inappropriate address %s for the device command, line ignored", 4107*eabc0478Schristos stoa(&addr_sock)); 4108*eabc0478Schristos continue; 4109*eabc0478Schristos } 4110*eabc0478Schristos 4111*eabc0478Schristos ppsName = ttyName = NULL; 4112*eabc0478Schristos curr_opt = HEAD_PFIFO(curr_device->options); 4113*eabc0478Schristos for (; curr_opt != NULL; curr_opt = curr_opt->link) { 4114*eabc0478Schristos switch (curr_opt->attr) { 4115*eabc0478Schristos 4116*eabc0478Schristos case T_TimeData: 4117*eabc0478Schristos ttyName = curr_opt->value.s; 4118*eabc0478Schristos break; 4119*eabc0478Schristos 4120*eabc0478Schristos case T_PpsData: 4121*eabc0478Schristos ppsName = curr_opt->value.s; 4122*eabc0478Schristos break; 4123*eabc0478Schristos 4124*eabc0478Schristos default: 4125*eabc0478Schristos msyslog(LOG_ERR, 4126*eabc0478Schristos "Unexpected device spec %s (%d) for %s", 4127*eabc0478Schristos token_name(curr_opt->attr), 4128*eabc0478Schristos curr_opt->attr, addr_node->address); 4129*eabc0478Schristos exit(curr_opt->attr ? curr_opt->attr : 1); 4130*eabc0478Schristos } 4131*eabc0478Schristos } 4132*eabc0478Schristos # ifdef REFCLOCK 4133*eabc0478Schristos clockdev_update(&addr_sock, ttyName, ppsName); 4134*eabc0478Schristos # endif 4135*eabc0478Schristos } 4136*eabc0478Schristos } 4137*eabc0478Schristos #endif /* !SIM */ 4138*eabc0478Schristos 4139abb0f93cSkardel 4140abb0f93cSkardel #ifdef FREE_CFG_T 4141abb0f93cSkardel static void 4142abb0f93cSkardel free_config_fudge( 41432950cc38Schristos config_tree *ptree 4144abb0f93cSkardel ) 4145abb0f93cSkardel { 41462950cc38Schristos FREE_ADDR_OPTS_FIFO(ptree->fudge); 4147abb0f93cSkardel } 4148*eabc0478Schristos 4149*eabc0478Schristos static void 4150*eabc0478Schristos free_config_device( 4151*eabc0478Schristos config_tree *ptree 4152*eabc0478Schristos ) 4153*eabc0478Schristos { 4154*eabc0478Schristos FREE_ADDR_OPTS_FIFO(ptree->device); 4155*eabc0478Schristos } 4156abb0f93cSkardel #endif /* FREE_CFG_T */ 4157abb0f93cSkardel 4158abb0f93cSkardel 4159abb0f93cSkardel static void 4160abb0f93cSkardel config_vars( 41612950cc38Schristos config_tree *ptree 4162abb0f93cSkardel ) 4163abb0f93cSkardel { 41642950cc38Schristos attr_val *curr_var; 4165abb0f93cSkardel int len; 4166abb0f93cSkardel 41672950cc38Schristos curr_var = HEAD_PFIFO(ptree->vars); 41682950cc38Schristos for (; curr_var != NULL; curr_var = curr_var->link) { 4169abb0f93cSkardel /* Determine which variable to set and set it */ 4170abb0f93cSkardel switch (curr_var->attr) { 41712950cc38Schristos 4172abb0f93cSkardel case T_Broadcastdelay: 4173abb0f93cSkardel proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL); 4174abb0f93cSkardel break; 41752950cc38Schristos 4176abb0f93cSkardel case T_Tick: 41772950cc38Schristos loop_config(LOOP_TICK, curr_var->value.d); 4178abb0f93cSkardel break; 41792950cc38Schristos 4180abb0f93cSkardel case T_Driftfile: 4181*eabc0478Schristos if ('\0' == curr_var->value.s[0]) 41822950cc38Schristos msyslog(LOG_INFO, "config: driftfile disabled"); 4183*eabc0478Schristos stats_config(STATS_FREQ_FILE, curr_var->value.s, TRUE); 4184abb0f93cSkardel break; 41852950cc38Schristos 41865d681e99Schristos case T_Dscp: 41875d681e99Schristos /* DSCP is in the upper 6 bits of the IP TOS/DS field */ 41885d681e99Schristos qos = curr_var->value.i << 2; 41895d681e99Schristos break; 41905d681e99Schristos 41912950cc38Schristos case T_Ident: 41922950cc38Schristos sys_ident = curr_var->value.s; 41932950cc38Schristos break; 41942950cc38Schristos 41952950cc38Schristos case T_WanderThreshold: /* FALLTHROUGH */ 41962950cc38Schristos case T_Nonvolatile: 4197abb0f93cSkardel wander_threshold = curr_var->value.d; 4198abb0f93cSkardel break; 41992950cc38Schristos 4200abb0f93cSkardel case T_Leapfile: 4201cdfa2a7eSchristos stats_config(STATS_LEAP_FILE, curr_var->value.s, curr_var->flag); 4202abb0f93cSkardel break; 42032950cc38Schristos 42045d681e99Schristos #ifdef LEAP_SMEAR 42055d681e99Schristos case T_Leapsmearinterval: 42065d681e99Schristos leap_smear_intv = curr_var->value.i; 42075d681e99Schristos msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv); 42085d681e99Schristos break; 42095d681e99Schristos #endif 42105d681e99Schristos 4211abb0f93cSkardel case T_Pidfile: 4212cdfa2a7eSchristos stats_config(STATS_PID_FILE, curr_var->value.s, 0); 4213abb0f93cSkardel break; 4214abb0f93cSkardel 42152950cc38Schristos case T_Logfile: 42162950cc38Schristos if (-1 == change_logfile(curr_var->value.s, TRUE)) 4217abb0f93cSkardel msyslog(LOG_ERR, 42182950cc38Schristos "Cannot open logfile %s: %m", 4219abb0f93cSkardel curr_var->value.s); 4220abb0f93cSkardel break; 4221abb0f93cSkardel 4222abb0f93cSkardel case T_Saveconfigdir: 4223abb0f93cSkardel if (saveconfigdir != NULL) 4224abb0f93cSkardel free(saveconfigdir); 4225abb0f93cSkardel len = strlen(curr_var->value.s); 42262950cc38Schristos if (0 == len) { 4227abb0f93cSkardel saveconfigdir = NULL; 42282950cc38Schristos } else if (DIR_SEP != curr_var->value.s[len - 1] 4229abb0f93cSkardel #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */ 4230abb0f93cSkardel && '/' != curr_var->value.s[len - 1] 4231abb0f93cSkardel #endif 4232abb0f93cSkardel ) { 4233abb0f93cSkardel len++; 4234abb0f93cSkardel saveconfigdir = emalloc(len + 1); 4235abb0f93cSkardel snprintf(saveconfigdir, len + 1, 4236abb0f93cSkardel "%s%c", 4237abb0f93cSkardel curr_var->value.s, 4238abb0f93cSkardel DIR_SEP); 42392950cc38Schristos } else { 4240abb0f93cSkardel saveconfigdir = estrdup( 4241abb0f93cSkardel curr_var->value.s); 42422950cc38Schristos } 4243abb0f93cSkardel break; 4244abb0f93cSkardel 4245abb0f93cSkardel case T_Automax: 42462950cc38Schristos #ifdef AUTOKEY 4247cdfa2a7eSchristos if (curr_var->value.i > 2 && curr_var->value.i < 32) 4248cdfa2a7eSchristos sys_automax = (u_char)curr_var->value.i; 4249cdfa2a7eSchristos else 4250cdfa2a7eSchristos msyslog(LOG_ERR, 4251cdfa2a7eSchristos "'automax' value %d ignored", 4252cdfa2a7eSchristos curr_var->value.i); 4253abb0f93cSkardel #endif 4254abb0f93cSkardel break; 4255abb0f93cSkardel 4256abb0f93cSkardel default: 4257abb0f93cSkardel msyslog(LOG_ERR, 4258abb0f93cSkardel "config_vars(): unexpected token %d", 4259abb0f93cSkardel curr_var->attr); 4260abb0f93cSkardel } 4261abb0f93cSkardel } 4262abb0f93cSkardel } 4263abb0f93cSkardel 4264abb0f93cSkardel 4265abb0f93cSkardel #ifdef FREE_CFG_T 4266abb0f93cSkardel static void 4267abb0f93cSkardel free_config_vars( 42682950cc38Schristos config_tree *ptree 4269abb0f93cSkardel ) 4270abb0f93cSkardel { 42712950cc38Schristos FREE_ATTR_VAL_FIFO(ptree->vars); 4272abb0f93cSkardel } 4273abb0f93cSkardel #endif /* FREE_CFG_T */ 4274abb0f93cSkardel 4275abb0f93cSkardel 4276*eabc0478Schristos #ifndef SIM 4277abb0f93cSkardel /* Define a function to check if a resolved address is sane. 4278abb0f93cSkardel * If yes, return 1, else return 0; 4279abb0f93cSkardel */ 4280abb0f93cSkardel static int 4281abb0f93cSkardel is_sane_resolved_address( 4282abb0f93cSkardel sockaddr_u * peeraddr, 4283abb0f93cSkardel int hmode 4284abb0f93cSkardel ) 4285abb0f93cSkardel { 4286abb0f93cSkardel if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) { 4287abb0f93cSkardel msyslog(LOG_ERR, 4288abb0f93cSkardel "attempt to configure invalid address %s", 4289abb0f93cSkardel stoa(peeraddr)); 4290abb0f93cSkardel return 0; 4291abb0f93cSkardel } 4292abb0f93cSkardel /* 4293cdfa2a7eSchristos * Shouldn't be able to specify: 4294cdfa2a7eSchristos * - multicast address for server/peer! 4295cdfa2a7eSchristos * - unicast address for manycastclient! 4296abb0f93cSkardel */ 4297abb0f93cSkardel if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode) 4298abb0f93cSkardel && IS_MCAST(peeraddr)) { 4299abb0f93cSkardel msyslog(LOG_ERR, 4300abb0f93cSkardel "attempt to configure invalid address %s", 4301abb0f93cSkardel stoa(peeraddr)); 4302abb0f93cSkardel return 0; 4303abb0f93cSkardel } 4304abb0f93cSkardel if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) { 4305abb0f93cSkardel msyslog(LOG_ERR, 4306abb0f93cSkardel "attempt to configure invalid address %s", 4307abb0f93cSkardel stoa(peeraddr)); 4308abb0f93cSkardel return 0; 4309abb0f93cSkardel } 4310abb0f93cSkardel 4311abb0f93cSkardel if (IS_IPV6(peeraddr) && !ipv6_works) 4312abb0f93cSkardel return 0; 4313abb0f93cSkardel 4314abb0f93cSkardel /* Ok, all tests succeeded, now we can return 1 */ 4315abb0f93cSkardel return 1; 4316abb0f93cSkardel } 4317abb0f93cSkardel 43182950cc38Schristos 43192950cc38Schristos static u_char 4320abb0f93cSkardel get_correct_host_mode( 43212950cc38Schristos int token 4322abb0f93cSkardel ) 4323abb0f93cSkardel { 43242950cc38Schristos switch (token) { 43252950cc38Schristos 4326abb0f93cSkardel case T_Server: 4327abb0f93cSkardel case T_Pool: 4328abb0f93cSkardel case T_Manycastclient: 4329abb0f93cSkardel return MODE_CLIENT; 43302950cc38Schristos 4331abb0f93cSkardel case T_Peer: 4332abb0f93cSkardel return MODE_ACTIVE; 43332950cc38Schristos 4334abb0f93cSkardel case T_Broadcast: 4335abb0f93cSkardel return MODE_BROADCAST; 43362950cc38Schristos 4337abb0f93cSkardel default: 43382950cc38Schristos return 0; 4339abb0f93cSkardel } 4340abb0f93cSkardel } 4341abb0f93cSkardel 43422950cc38Schristos 43432950cc38Schristos /* 43442950cc38Schristos * peerflag_bits() get config_peers() peerflags value from a 43452950cc38Schristos * peer_node's queue of flag attr_val entries. 43462950cc38Schristos */ 43472950cc38Schristos static int 43482950cc38Schristos peerflag_bits( 43492950cc38Schristos peer_node *pn 4350abb0f93cSkardel ) 4351abb0f93cSkardel { 4352abb0f93cSkardel int peerflags; 43532950cc38Schristos attr_val *option; 4354cdfa2a7eSchristos int hmode; 4355abb0f93cSkardel 4356cdfa2a7eSchristos DEBUG_INSIST(pn); 4357abb0f93cSkardel /* translate peerflags options to bits */ 4358abb0f93cSkardel peerflags = 0; 4359cdfa2a7eSchristos hmode = pn->host_mode; 43602950cc38Schristos option = HEAD_PFIFO(pn->peerflags); 43612950cc38Schristos for (; option != NULL; option = option->link) { 4362abb0f93cSkardel switch (option->value.i) { 4363abb0f93cSkardel 4364abb0f93cSkardel default: 4365ccc794f0Schristos fatal_error("peerflag_bits: option-token=%d", option->value.i); 4366abb0f93cSkardel 4367abb0f93cSkardel case T_Autokey: 4368abb0f93cSkardel peerflags |= FLAG_SKEY; 4369abb0f93cSkardel break; 4370abb0f93cSkardel 4371abb0f93cSkardel case T_Burst: 4372abb0f93cSkardel peerflags |= FLAG_BURST; 4373abb0f93cSkardel break; 4374abb0f93cSkardel 4375abb0f93cSkardel case T_Iburst: 4376abb0f93cSkardel peerflags |= FLAG_IBURST; 4377abb0f93cSkardel break; 4378abb0f93cSkardel 4379abb0f93cSkardel case T_Noselect: 4380abb0f93cSkardel peerflags |= FLAG_NOSELECT; 4381abb0f93cSkardel break; 4382abb0f93cSkardel 4383abb0f93cSkardel case T_Preempt: 4384abb0f93cSkardel peerflags |= FLAG_PREEMPT; 4385abb0f93cSkardel break; 4386abb0f93cSkardel 4387abb0f93cSkardel case T_Prefer: 4388abb0f93cSkardel peerflags |= FLAG_PREFER; 4389abb0f93cSkardel break; 4390abb0f93cSkardel 4391abb0f93cSkardel case T_True: 4392abb0f93cSkardel peerflags |= FLAG_TRUE; 4393abb0f93cSkardel break; 4394abb0f93cSkardel 4395abb0f93cSkardel case T_Xleave: 4396abb0f93cSkardel peerflags |= FLAG_XLEAVE; 4397abb0f93cSkardel break; 4398cdfa2a7eSchristos 4399cdfa2a7eSchristos case T_Xmtnonce: 4400cdfa2a7eSchristos if ( MODE_CLIENT == hmode ) { 4401cdfa2a7eSchristos peerflags |= FLAG_LOOPNONCE; 4402cdfa2a7eSchristos } 4403cdfa2a7eSchristos break; 4404abb0f93cSkardel } 44052950cc38Schristos } 4406abb0f93cSkardel 44072950cc38Schristos return peerflags; 44082950cc38Schristos } 44092950cc38Schristos 44102950cc38Schristos 44112950cc38Schristos static void 44122950cc38Schristos config_peers( 44132950cc38Schristos config_tree *ptree 44142950cc38Schristos ) 44152950cc38Schristos { 44162950cc38Schristos sockaddr_u peeraddr; 44172950cc38Schristos struct addrinfo hints; 44182950cc38Schristos peer_node * curr_peer; 44192950cc38Schristos peer_resolved_ctx * ctx; 44202950cc38Schristos u_char hmode; 44212950cc38Schristos 44222950cc38Schristos /* add servers named on the command line with iburst implied */ 44232950cc38Schristos for (; 44242950cc38Schristos cmdline_server_count > 0; 44252950cc38Schristos cmdline_server_count--, cmdline_servers++) { 44262950cc38Schristos 4427abb0f93cSkardel ZERO_SOCK(&peeraddr); 4428abb0f93cSkardel /* 44292950cc38Schristos * If we have a numeric address, we can safely 44302950cc38Schristos * proceed in the mainline with it. Otherwise, hand 44312950cc38Schristos * the hostname off to the blocking child. 44324eea345dSchristos * 44334eea345dSchristos * Note that if we're told to add the peer here, we 44344eea345dSchristos * do that regardless of ippeerlimit. 4435abb0f93cSkardel */ 44362950cc38Schristos if (is_ip_address(*cmdline_servers, AF_UNSPEC, 44372950cc38Schristos &peeraddr)) { 4438abb0f93cSkardel 44392950cc38Schristos SET_PORT(&peeraddr, NTP_PORT); 44402950cc38Schristos if (is_sane_resolved_address(&peeraddr, 44412950cc38Schristos T_Server)) 44422950cc38Schristos peer_config( 44432950cc38Schristos &peeraddr, 44442950cc38Schristos NULL, 44452950cc38Schristos NULL, 44464eea345dSchristos -1, 44472950cc38Schristos MODE_CLIENT, 44482950cc38Schristos NTP_VERSION, 44492950cc38Schristos 0, 44502950cc38Schristos 0, 44512950cc38Schristos FLAG_IBURST, 44522950cc38Schristos 0, 44532950cc38Schristos 0, 44542950cc38Schristos NULL); 44552950cc38Schristos } else { 44562950cc38Schristos /* we have a hostname to resolve */ 44572950cc38Schristos # ifdef WORKER 44582950cc38Schristos ctx = emalloc_zero(sizeof(*ctx)); 44592950cc38Schristos ctx->family = AF_UNSPEC; 44602950cc38Schristos ctx->host_mode = T_Server; 44612950cc38Schristos ctx->hmode = MODE_CLIENT; 44622950cc38Schristos ctx->version = NTP_VERSION; 44632950cc38Schristos ctx->flags = FLAG_IBURST; 4464*eabc0478Schristos ctx->was_initializing = initializing; 44652950cc38Schristos 44662950cc38Schristos ZERO(hints); 44672950cc38Schristos hints.ai_family = (u_short)ctx->family; 44682950cc38Schristos hints.ai_socktype = SOCK_DGRAM; 44692950cc38Schristos hints.ai_protocol = IPPROTO_UDP; 44702950cc38Schristos 447103cfe0ffSchristos getaddrinfo_sometime_ex(*cmdline_servers, 44722950cc38Schristos "ntp", &hints, 44732950cc38Schristos INITIAL_DNS_RETRY, 44742950cc38Schristos &peer_name_resolved, 447503cfe0ffSchristos (void *)ctx, DNSFLAGS); 44762950cc38Schristos # else /* !WORKER follows */ 44772950cc38Schristos msyslog(LOG_ERR, 44782950cc38Schristos "hostname %s can not be used, please use IP address instead.", 44792950cc38Schristos curr_peer->addr->address); 44802950cc38Schristos # endif 44812950cc38Schristos } 44822950cc38Schristos } 44832950cc38Schristos 44842950cc38Schristos /* add associations from the configuration file */ 44852950cc38Schristos curr_peer = HEAD_PFIFO(ptree->peers); 44862950cc38Schristos for (; curr_peer != NULL; curr_peer = curr_peer->link) { 44872950cc38Schristos ZERO_SOCK(&peeraddr); 44882950cc38Schristos /* Find the correct host-mode */ 44892950cc38Schristos hmode = get_correct_host_mode(curr_peer->host_mode); 4490ea66d795Schristos INSIST(hmode != 0); 44912950cc38Schristos 44922950cc38Schristos if (T_Pool == curr_peer->host_mode) { 44932950cc38Schristos AF(&peeraddr) = curr_peer->addr->type; 44942950cc38Schristos peer_config( 44952950cc38Schristos &peeraddr, 44962950cc38Schristos curr_peer->addr->address, 4497abb0f93cSkardel NULL, 44984eea345dSchristos -1, 4499abb0f93cSkardel hmode, 4500abb0f93cSkardel curr_peer->peerversion, 4501abb0f93cSkardel curr_peer->minpoll, 4502abb0f93cSkardel curr_peer->maxpoll, 45032950cc38Schristos peerflag_bits(curr_peer), 4504abb0f93cSkardel curr_peer->ttl, 4505abb0f93cSkardel curr_peer->peerkey, 45062950cc38Schristos curr_peer->group); 45072950cc38Schristos /* 45082950cc38Schristos * If we have a numeric address, we can safely 45092950cc38Schristos * proceed in the mainline with it. Otherwise, hand 45102950cc38Schristos * the hostname off to the blocking child. 45112950cc38Schristos */ 45122950cc38Schristos } else if (is_ip_address(curr_peer->addr->address, 45132950cc38Schristos curr_peer->addr->type, &peeraddr)) { 45142950cc38Schristos 45152950cc38Schristos SET_PORT(&peeraddr, NTP_PORT); 45162950cc38Schristos if (is_sane_resolved_address(&peeraddr, 45172950cc38Schristos curr_peer->host_mode)) 45182950cc38Schristos peer_config( 45192950cc38Schristos &peeraddr, 45202950cc38Schristos NULL, 45212950cc38Schristos NULL, 45224eea345dSchristos -1, 45232950cc38Schristos hmode, 45242950cc38Schristos curr_peer->peerversion, 45252950cc38Schristos curr_peer->minpoll, 45262950cc38Schristos curr_peer->maxpoll, 45272950cc38Schristos peerflag_bits(curr_peer), 45282950cc38Schristos curr_peer->ttl, 45292950cc38Schristos curr_peer->peerkey, 45302950cc38Schristos curr_peer->group); 45312950cc38Schristos } else { 45322950cc38Schristos /* we have a hostname to resolve */ 45332950cc38Schristos # ifdef WORKER 45342950cc38Schristos ctx = emalloc_zero(sizeof(*ctx)); 45352950cc38Schristos ctx->family = curr_peer->addr->type; 45362950cc38Schristos ctx->host_mode = curr_peer->host_mode; 45372950cc38Schristos ctx->hmode = hmode; 45382950cc38Schristos ctx->version = curr_peer->peerversion; 45392950cc38Schristos ctx->minpoll = curr_peer->minpoll; 45402950cc38Schristos ctx->maxpoll = curr_peer->maxpoll; 45412950cc38Schristos ctx->flags = peerflag_bits(curr_peer); 45422950cc38Schristos ctx->ttl = curr_peer->ttl; 45432950cc38Schristos ctx->keyid = curr_peer->peerkey; 45442950cc38Schristos ctx->group = curr_peer->group; 4545*eabc0478Schristos ctx->was_initializing = initializing; 45462950cc38Schristos 45472950cc38Schristos ZERO(hints); 45482950cc38Schristos hints.ai_family = ctx->family; 45492950cc38Schristos hints.ai_socktype = SOCK_DGRAM; 45502950cc38Schristos hints.ai_protocol = IPPROTO_UDP; 45512950cc38Schristos 455203cfe0ffSchristos getaddrinfo_sometime_ex(curr_peer->addr->address, 45532950cc38Schristos "ntp", &hints, 45542950cc38Schristos INITIAL_DNS_RETRY, 455503cfe0ffSchristos &peer_name_resolved, ctx, 455603cfe0ffSchristos DNSFLAGS); 45572950cc38Schristos # else /* !WORKER follows */ 45582950cc38Schristos msyslog(LOG_ERR, 45592950cc38Schristos "hostname %s can not be used, please use IP address instead.", 45602950cc38Schristos curr_peer->addr->address); 45612950cc38Schristos # endif 4562abb0f93cSkardel } 4563abb0f93cSkardel } 45642950cc38Schristos } 4565*eabc0478Schristos 45662950cc38Schristos 45672950cc38Schristos /* 45682950cc38Schristos * peer_name_resolved() 45692950cc38Schristos * 45702950cc38Schristos * Callback invoked when config_peers()'s DNS lookup completes. 45712950cc38Schristos */ 45722950cc38Schristos #ifdef WORKER 4573ea66d795Schristos static void 45742950cc38Schristos peer_name_resolved( 45752950cc38Schristos int rescode, 45762950cc38Schristos int gai_errno, 45772950cc38Schristos void * context, 45782950cc38Schristos const char * name, 45792950cc38Schristos const char * service, 45802950cc38Schristos const struct addrinfo * hints, 45812950cc38Schristos const struct addrinfo * res 45822950cc38Schristos ) 45832950cc38Schristos { 45842950cc38Schristos sockaddr_u peeraddr; 45852950cc38Schristos peer_resolved_ctx * ctx; 45862950cc38Schristos u_short af; 45872950cc38Schristos const char * fam_spec; 45882950cc38Schristos 4589ea66d795Schristos (void)gai_errno; 4590ea66d795Schristos (void)service; 4591ea66d795Schristos (void)hints; 45922950cc38Schristos ctx = context; 45932950cc38Schristos 45942950cc38Schristos DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode)); 45952950cc38Schristos 45962950cc38Schristos if (rescode) { 45972950cc38Schristos free(ctx); 45982950cc38Schristos msyslog(LOG_ERR, 45992950cc38Schristos "giving up resolving host %s: %s (%d)", 46002950cc38Schristos name, gai_strerror(rescode), rescode); 46012950cc38Schristos return; 46022950cc38Schristos } 46032950cc38Schristos 46042950cc38Schristos /* Loop to configure a single association */ 46052950cc38Schristos for (; res != NULL; res = res->ai_next) { 46062950cc38Schristos memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 46072950cc38Schristos if (is_sane_resolved_address(&peeraddr, 46082950cc38Schristos ctx->host_mode)) { 46092950cc38Schristos NLOG(NLOG_SYSINFO) { 46102950cc38Schristos af = ctx->family; 46112950cc38Schristos fam_spec = (AF_INET6 == af) 46122950cc38Schristos ? "(AAAA) " 46132950cc38Schristos : (AF_INET == af) 46142950cc38Schristos ? "(A) " 46152950cc38Schristos : ""; 46162950cc38Schristos msyslog(LOG_INFO, "DNS %s %s-> %s", 46172950cc38Schristos name, fam_spec, 46182950cc38Schristos stoa(&peeraddr)); 46192950cc38Schristos } 4620*eabc0478Schristos 4621*eabc0478Schristos /* 4622*eabc0478Schristos * peer_clear needs to know if this association was specified 4623*eabc0478Schristos * in the startup configuration file to set the next poll time. 4624*eabc0478Schristos */ 4625*eabc0478Schristos if (ctx->was_initializing) { 4626*eabc0478Schristos INSIST(!initializing); 4627*eabc0478Schristos initializing = TRUE; 4628*eabc0478Schristos } 4629*eabc0478Schristos 46302950cc38Schristos peer_config( 46312950cc38Schristos &peeraddr, 46322950cc38Schristos NULL, 46332950cc38Schristos NULL, 46344eea345dSchristos -1, 46352950cc38Schristos ctx->hmode, 46362950cc38Schristos ctx->version, 46372950cc38Schristos ctx->minpoll, 46382950cc38Schristos ctx->maxpoll, 46392950cc38Schristos ctx->flags, 46402950cc38Schristos ctx->ttl, 46412950cc38Schristos ctx->keyid, 46422950cc38Schristos ctx->group); 4643*eabc0478Schristos 4644*eabc0478Schristos if (ctx->was_initializing) { 4645*eabc0478Schristos initializing = FALSE; 4646*eabc0478Schristos } 4647*eabc0478Schristos 46482950cc38Schristos break; 46492950cc38Schristos } 46502950cc38Schristos } 46512950cc38Schristos free(ctx); 46522950cc38Schristos } 46532950cc38Schristos #endif /* WORKER */ 4654abb0f93cSkardel 4655abb0f93cSkardel 4656abb0f93cSkardel #ifdef FREE_CFG_T 4657abb0f93cSkardel static void 4658abb0f93cSkardel free_config_peers( 46592950cc38Schristos config_tree *ptree 4660abb0f93cSkardel ) 4661abb0f93cSkardel { 46622950cc38Schristos peer_node *curr_peer; 4663abb0f93cSkardel 46642950cc38Schristos if (ptree->peers != NULL) { 4665ea66d795Schristos for (;;) { 46662950cc38Schristos UNLINK_FIFO(curr_peer, *ptree->peers, link); 46672950cc38Schristos if (NULL == curr_peer) 46682950cc38Schristos break; 4669abb0f93cSkardel destroy_address_node(curr_peer->addr); 46702950cc38Schristos destroy_attr_val_fifo(curr_peer->peerflags); 46712950cc38Schristos free(curr_peer); 46722950cc38Schristos } 46732950cc38Schristos free(ptree->peers); 46742950cc38Schristos ptree->peers = NULL; 4675abb0f93cSkardel } 4676abb0f93cSkardel } 4677abb0f93cSkardel #endif /* FREE_CFG_T */ 4678abb0f93cSkardel 4679abb0f93cSkardel 4680abb0f93cSkardel static void 4681abb0f93cSkardel config_unpeers( 46822950cc38Schristos config_tree *ptree 4683abb0f93cSkardel ) 4684abb0f93cSkardel { 4685abb0f93cSkardel sockaddr_u peeraddr; 46862950cc38Schristos struct addrinfo hints; 46872950cc38Schristos unpeer_node * curr_unpeer; 46882950cc38Schristos struct peer * p; 46892950cc38Schristos const char * name; 46902950cc38Schristos int rc; 4691abb0f93cSkardel 46922950cc38Schristos curr_unpeer = HEAD_PFIFO(ptree->unpeers); 46932950cc38Schristos for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) { 4694abb0f93cSkardel /* 4695ccc794f0Schristos * If we have no address attached, assume we have to 4696ccc794f0Schristos * unpeer by AssocID. 4697abb0f93cSkardel */ 4698ccc794f0Schristos if (!curr_unpeer->addr) { 46992950cc38Schristos p = findpeerbyassoc(curr_unpeer->assocID); 47002950cc38Schristos if (p != NULL) { 47012950cc38Schristos msyslog(LOG_NOTICE, "unpeered %s", 47022950cc38Schristos stoa(&p->srcadr)); 47032950cc38Schristos peer_clear(p, "GONE"); 47042950cc38Schristos unpeer(p); 4705abb0f93cSkardel } 4706abb0f93cSkardel continue; 4707abb0f93cSkardel } 4708abb0f93cSkardel 47092950cc38Schristos ZERO(peeraddr); 47102950cc38Schristos AF(&peeraddr) = curr_unpeer->addr->type; 47112950cc38Schristos name = curr_unpeer->addr->address; 47122950cc38Schristos rc = getnetnum(name, &peeraddr, 0, t_UNK); 47132950cc38Schristos /* Do we have a numeric address? */ 47142950cc38Schristos if (rc > 0) { 47152950cc38Schristos DPRINTF(1, ("unpeer: searching for %s\n", 47162950cc38Schristos stoa(&peeraddr))); 47174eea345dSchristos p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 47182950cc38Schristos if (p != NULL) { 47192950cc38Schristos msyslog(LOG_NOTICE, "unpeered %s", 47202950cc38Schristos stoa(&peeraddr)); 47212950cc38Schristos peer_clear(p, "GONE"); 47222950cc38Schristos unpeer(p); 4723abb0f93cSkardel } 47242950cc38Schristos continue; 47252950cc38Schristos } 47262950cc38Schristos /* 47272950cc38Schristos * It's not a numeric IP address, it's a hostname. 47282950cc38Schristos * Check for associations with a matching hostname. 47292950cc38Schristos */ 47302950cc38Schristos for (p = peer_list; p != NULL; p = p->p_link) 47312950cc38Schristos if (p->hostname != NULL) 47322950cc38Schristos if (!strcasecmp(p->hostname, name)) 47332950cc38Schristos break; 47342950cc38Schristos if (p != NULL) { 47352950cc38Schristos msyslog(LOG_NOTICE, "unpeered %s", name); 47362950cc38Schristos peer_clear(p, "GONE"); 47372950cc38Schristos unpeer(p); 47382950cc38Schristos } 47392950cc38Schristos /* Resolve the hostname to address(es). */ 47402950cc38Schristos # ifdef WORKER 47412950cc38Schristos ZERO(hints); 47422950cc38Schristos hints.ai_family = curr_unpeer->addr->type; 47432950cc38Schristos hints.ai_socktype = SOCK_DGRAM; 47442950cc38Schristos hints.ai_protocol = IPPROTO_UDP; 47452950cc38Schristos getaddrinfo_sometime(name, "ntp", &hints, 47462950cc38Schristos INITIAL_DNS_RETRY, 47472950cc38Schristos &unpeer_name_resolved, NULL); 47482950cc38Schristos # else /* !WORKER follows */ 47492950cc38Schristos msyslog(LOG_ERR, 47502950cc38Schristos "hostname %s can not be used, please use IP address instead.", 47512950cc38Schristos name); 47522950cc38Schristos # endif 47532950cc38Schristos } 47542950cc38Schristos } 47552950cc38Schristos 47562950cc38Schristos 47572950cc38Schristos /* 47582950cc38Schristos * unpeer_name_resolved() 47592950cc38Schristos * 47602950cc38Schristos * Callback invoked when config_unpeers()'s DNS lookup completes. 47612950cc38Schristos */ 47622950cc38Schristos #ifdef WORKER 4763ea66d795Schristos static void 47642950cc38Schristos unpeer_name_resolved( 47652950cc38Schristos int rescode, 47662950cc38Schristos int gai_errno, 47672950cc38Schristos void * context, 47682950cc38Schristos const char * name, 47692950cc38Schristos const char * service, 47702950cc38Schristos const struct addrinfo * hints, 47712950cc38Schristos const struct addrinfo * res 47722950cc38Schristos ) 47732950cc38Schristos { 47742950cc38Schristos sockaddr_u peeraddr; 47752950cc38Schristos struct peer * peer; 47762950cc38Schristos u_short af; 47772950cc38Schristos const char * fam_spec; 47782950cc38Schristos 4779ea66d795Schristos (void)context; 4780ea66d795Schristos (void)hints; 47812950cc38Schristos DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode)); 47822950cc38Schristos 47832950cc38Schristos if (rescode) { 47842950cc38Schristos msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 47852950cc38Schristos name, gai_strerror(rescode), rescode); 47862950cc38Schristos return; 47872950cc38Schristos } 4788abb0f93cSkardel /* 4789abb0f93cSkardel * Loop through the addresses found 4790abb0f93cSkardel */ 47912950cc38Schristos for (; res != NULL; res = res->ai_next) { 4792ea66d795Schristos INSIST(res->ai_addrlen <= sizeof(peeraddr)); 4793abb0f93cSkardel memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 47942950cc38Schristos DPRINTF(1, ("unpeer: searching for peer %s\n", 47952950cc38Schristos stoa(&peeraddr))); 47964eea345dSchristos peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 47972950cc38Schristos if (peer != NULL) { 47982950cc38Schristos af = AF(&peeraddr); 47992950cc38Schristos fam_spec = (AF_INET6 == af) 48002950cc38Schristos ? "(AAAA) " 48012950cc38Schristos : (AF_INET == af) 48022950cc38Schristos ? "(A) " 48032950cc38Schristos : ""; 48042950cc38Schristos msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name, 48052950cc38Schristos fam_spec, stoa(&peeraddr)); 4806abb0f93cSkardel peer_clear(peer, "GONE"); 4807abb0f93cSkardel unpeer(peer); 4808abb0f93cSkardel } 4809abb0f93cSkardel } 4810abb0f93cSkardel } 48112950cc38Schristos #endif /* WORKER */ 4812abb0f93cSkardel 4813abb0f93cSkardel 4814abb0f93cSkardel #ifdef FREE_CFG_T 4815abb0f93cSkardel static void 4816abb0f93cSkardel free_config_unpeers( 48172950cc38Schristos config_tree *ptree 4818abb0f93cSkardel ) 4819abb0f93cSkardel { 48202950cc38Schristos unpeer_node *curr_unpeer; 4821abb0f93cSkardel 48222950cc38Schristos if (ptree->unpeers != NULL) { 4823ea66d795Schristos for (;;) { 48242950cc38Schristos UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link); 48252950cc38Schristos if (NULL == curr_unpeer) 48262950cc38Schristos break; 4827abb0f93cSkardel destroy_address_node(curr_unpeer->addr); 48282950cc38Schristos free(curr_unpeer); 4829abb0f93cSkardel } 48302950cc38Schristos free(ptree->unpeers); 48312950cc38Schristos } 48322950cc38Schristos } 48332950cc38Schristos #endif /* FREE_CFG_T */ 4834*eabc0478Schristos #endif /* !SIM */ 48352950cc38Schristos 48362950cc38Schristos 48372950cc38Schristos #ifndef SIM 48382950cc38Schristos static void 48392950cc38Schristos config_reset_counters( 48402950cc38Schristos config_tree *ptree 48412950cc38Schristos ) 48422950cc38Schristos { 48432950cc38Schristos int_node *counter_set; 48442950cc38Schristos 48452950cc38Schristos for (counter_set = HEAD_PFIFO(ptree->reset_counters); 48462950cc38Schristos counter_set != NULL; 48472950cc38Schristos counter_set = counter_set->link) { 48482950cc38Schristos switch (counter_set->i) { 48492950cc38Schristos default: 48502950cc38Schristos DPRINTF(1, ("config_reset_counters %s (%d) invalid\n", 48512950cc38Schristos keyword(counter_set->i), counter_set->i)); 48522950cc38Schristos break; 48532950cc38Schristos 48542950cc38Schristos case T_Allpeers: 48552950cc38Schristos peer_all_reset(); 48562950cc38Schristos break; 48572950cc38Schristos 48582950cc38Schristos case T_Auth: 48592950cc38Schristos reset_auth_stats(); 48602950cc38Schristos break; 48612950cc38Schristos 48622950cc38Schristos case T_Ctl: 48632950cc38Schristos ctl_clr_stats(); 48642950cc38Schristos break; 48652950cc38Schristos 48662950cc38Schristos case T_Io: 48672950cc38Schristos io_clr_stats(); 48682950cc38Schristos break; 48692950cc38Schristos 48702950cc38Schristos case T_Mem: 48712950cc38Schristos peer_clr_stats(); 48722950cc38Schristos break; 48732950cc38Schristos 48742950cc38Schristos case T_Sys: 48752950cc38Schristos proto_clr_stats(); 48762950cc38Schristos break; 48772950cc38Schristos 48782950cc38Schristos case T_Timer: 48792950cc38Schristos timer_clr_stats(); 48802950cc38Schristos break; 48812950cc38Schristos } 48822950cc38Schristos } 48832950cc38Schristos } 48842950cc38Schristos #endif /* !SIM */ 48852950cc38Schristos 48862950cc38Schristos 48872950cc38Schristos #ifdef FREE_CFG_T 48882950cc38Schristos static void 48892950cc38Schristos free_config_reset_counters( 48902950cc38Schristos config_tree *ptree 48912950cc38Schristos ) 48922950cc38Schristos { 48932950cc38Schristos FREE_INT_FIFO(ptree->reset_counters); 4894abb0f93cSkardel } 4895abb0f93cSkardel #endif /* FREE_CFG_T */ 4896abb0f93cSkardel 4897abb0f93cSkardel 4898abb0f93cSkardel #ifdef SIM 4899abb0f93cSkardel static void 4900abb0f93cSkardel config_sim( 49012950cc38Schristos config_tree *ptree 4902abb0f93cSkardel ) 4903abb0f93cSkardel { 4904abb0f93cSkardel int i; 4905abb0f93cSkardel server_info *serv_info; 49062950cc38Schristos attr_val *init_stmt; 49072950cc38Schristos sim_node *sim_n; 4908abb0f93cSkardel 4909abb0f93cSkardel /* Check if a simulate block was found in the configuration code. 4910abb0f93cSkardel * If not, return an error and exit 4911abb0f93cSkardel */ 49122950cc38Schristos sim_n = HEAD_PFIFO(ptree->sim_details); 49132950cc38Schristos if (NULL == sim_n) { 4914abb0f93cSkardel fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n"); 4915abb0f93cSkardel fprintf(stderr, "\tCheck your configuration file.\n"); 4916abb0f93cSkardel exit(1); 4917abb0f93cSkardel } 4918abb0f93cSkardel 4919abb0f93cSkardel /* Process the initialization statements 4920abb0f93cSkardel * ------------------------------------- 4921abb0f93cSkardel */ 49222950cc38Schristos init_stmt = HEAD_PFIFO(sim_n->init_opts); 49232950cc38Schristos for (; init_stmt != NULL; init_stmt = init_stmt->link) { 4924abb0f93cSkardel switch(init_stmt->attr) { 4925abb0f93cSkardel 4926abb0f93cSkardel case T_Beep_Delay: 4927abb0f93cSkardel simulation.beep_delay = init_stmt->value.d; 4928abb0f93cSkardel break; 4929abb0f93cSkardel 4930abb0f93cSkardel case T_Sim_Duration: 4931abb0f93cSkardel simulation.end_time = init_stmt->value.d; 4932abb0f93cSkardel break; 4933abb0f93cSkardel 4934abb0f93cSkardel default: 4935abb0f93cSkardel fprintf(stderr, 4936abb0f93cSkardel "Unknown simulator init token %d\n", 4937abb0f93cSkardel init_stmt->attr); 4938abb0f93cSkardel exit(1); 4939abb0f93cSkardel } 4940abb0f93cSkardel } 4941abb0f93cSkardel 4942abb0f93cSkardel /* Process the server list 4943abb0f93cSkardel * ----------------------- 4944abb0f93cSkardel */ 49452950cc38Schristos simulation.num_of_servers = 0; 49462950cc38Schristos serv_info = HEAD_PFIFO(sim_n->servers); 49472950cc38Schristos for (; serv_info != NULL; serv_info = serv_info->link) 49482950cc38Schristos simulation.num_of_servers++; 49495d681e99Schristos simulation.servers = eallocarray(simulation.num_of_servers, 49502950cc38Schristos sizeof(simulation.servers[0])); 4951abb0f93cSkardel 49522950cc38Schristos i = 0; 49532950cc38Schristos serv_info = HEAD_PFIFO(sim_n->servers); 49542950cc38Schristos for (; serv_info != NULL; serv_info = serv_info->link) { 4955abb0f93cSkardel if (NULL == serv_info) { 4956abb0f93cSkardel fprintf(stderr, "Simulator server list is corrupt\n"); 4957abb0f93cSkardel exit(1); 49582950cc38Schristos } else { 49592950cc38Schristos simulation.servers[i] = *serv_info; 49602950cc38Schristos simulation.servers[i].link = NULL; 49612950cc38Schristos i++; 49622950cc38Schristos } 4963abb0f93cSkardel } 4964abb0f93cSkardel 4965abb0f93cSkardel printf("Creating server associations\n"); 4966abb0f93cSkardel create_server_associations(); 4967abb0f93cSkardel fprintf(stderr,"\tServer associations successfully created!!\n"); 4968abb0f93cSkardel } 4969abb0f93cSkardel 4970abb0f93cSkardel 4971abb0f93cSkardel #ifdef FREE_CFG_T 4972abb0f93cSkardel static void 4973abb0f93cSkardel free_config_sim( 49742950cc38Schristos config_tree *ptree 4975abb0f93cSkardel ) 4976abb0f93cSkardel { 49772950cc38Schristos sim_node *sim_n; 49782950cc38Schristos server_info *serv_n; 49792950cc38Schristos script_info *script_n; 49802950cc38Schristos 4981abb0f93cSkardel if (NULL == ptree->sim_details) 4982abb0f93cSkardel return; 49832950cc38Schristos sim_n = HEAD_PFIFO(ptree->sim_details); 49842950cc38Schristos free(ptree->sim_details); 4985abb0f93cSkardel ptree->sim_details = NULL; 49862950cc38Schristos if (NULL == sim_n) 49872950cc38Schristos return; 49882950cc38Schristos 49892950cc38Schristos FREE_ATTR_VAL_FIFO(sim_n->init_opts); 4990ea66d795Schristos for (;;) { 49912950cc38Schristos UNLINK_FIFO(serv_n, *sim_n->servers, link); 49922950cc38Schristos if (NULL == serv_n) 49932950cc38Schristos break; 4994ea66d795Schristos free(serv_n->curr_script); 4995ea66d795Schristos if (serv_n->script != NULL) { 4996ea66d795Schristos for (;;) { 49972950cc38Schristos UNLINK_FIFO(script_n, *serv_n->script, 49982950cc38Schristos link); 4999ea66d795Schristos if (script_n == NULL) 50002950cc38Schristos break; 5001ea66d795Schristos free(script_n); 50022950cc38Schristos } 50032950cc38Schristos free(serv_n->script); 5004ea66d795Schristos } 50052950cc38Schristos free(serv_n); 50062950cc38Schristos } 50072950cc38Schristos free(sim_n); 5008abb0f93cSkardel } 5009abb0f93cSkardel #endif /* FREE_CFG_T */ 5010abb0f93cSkardel #endif /* SIM */ 5011abb0f93cSkardel 5012abb0f93cSkardel 5013abb0f93cSkardel /* Define two different config functions. One for the daemon and the other for 5014abb0f93cSkardel * the simulator. The simulator ignores a lot of the standard ntpd configuration 5015abb0f93cSkardel * options 5016abb0f93cSkardel */ 5017abb0f93cSkardel #ifndef SIM 5018abb0f93cSkardel static void 5019abb0f93cSkardel config_ntpd( 50205d681e99Schristos config_tree *ptree, 50215d681e99Schristos int/*BOOL*/ input_from_files 5022abb0f93cSkardel ) 5023abb0f93cSkardel { 50244eea345dSchristos /* [Bug 3435] check and esure clock sanity if configured from 50254eea345dSchristos * file and clock sanity parameters (-> basedate) are given. Do 50264eea345dSchristos * this ASAP, so we don't disturb the closed loop controller. 50274eea345dSchristos */ 50284eea345dSchristos if (input_from_files) { 50294eea345dSchristos if (config_tos_clock(ptree)) 50304eea345dSchristos clamp_systime(); 50314eea345dSchristos } 50324eea345dSchristos 50335d681e99Schristos config_nic_rules(ptree, input_from_files); 5034abb0f93cSkardel config_monitor(ptree); 5035abb0f93cSkardel config_auth(ptree); 5036abb0f93cSkardel config_tos(ptree); 5037abb0f93cSkardel config_access(ptree); 5038abb0f93cSkardel config_tinker(ptree); 50392950cc38Schristos config_rlimit(ptree); 5040abb0f93cSkardel config_system_opts(ptree); 5041abb0f93cSkardel config_logconfig(ptree); 5042abb0f93cSkardel config_phone(ptree); 5043a04a202dSchristos config_mdnstries(ptree); 5044abb0f93cSkardel config_setvar(ptree); 5045abb0f93cSkardel config_ttl(ptree); 5046abb0f93cSkardel config_vars(ptree); 50475d681e99Schristos 5048ccc794f0Schristos io_open_sockets(); /* [bug 2837] dep. on config_vars() */ 50495d681e99Schristos 5050ccc794f0Schristos config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */ 5051abb0f93cSkardel config_other_modes(ptree); 5052*eabc0478Schristos config_device(ptree); 5053abb0f93cSkardel config_peers(ptree); 5054abb0f93cSkardel config_unpeers(ptree); 5055abb0f93cSkardel config_fudge(ptree); 50562950cc38Schristos config_reset_counters(ptree); 50572950cc38Schristos 50584eea345dSchristos #ifdef DEBUG 50594eea345dSchristos if (debug > 1) { 50604eea345dSchristos dump_restricts(); 50614eea345dSchristos } 50624eea345dSchristos #endif 50634eea345dSchristos 50642950cc38Schristos #ifdef TEST_BLOCKING_WORKER 50652950cc38Schristos { 50662950cc38Schristos struct addrinfo hints; 50672950cc38Schristos 50682950cc38Schristos ZERO(hints); 50692950cc38Schristos hints.ai_socktype = SOCK_STREAM; 50702950cc38Schristos hints.ai_protocol = IPPROTO_TCP; 50712950cc38Schristos getaddrinfo_sometime("www.cnn.com", "ntp", &hints, 50722950cc38Schristos INITIAL_DNS_RETRY, 50732950cc38Schristos gai_test_callback, (void *)1); 50742950cc38Schristos hints.ai_family = AF_INET6; 50752950cc38Schristos getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, 50762950cc38Schristos INITIAL_DNS_RETRY, 50772950cc38Schristos gai_test_callback, (void *)0x600); 50782950cc38Schristos } 50792950cc38Schristos #endif 5080abb0f93cSkardel } 5081abb0f93cSkardel #endif /* !SIM */ 5082abb0f93cSkardel 5083abb0f93cSkardel 5084abb0f93cSkardel #ifdef SIM 5085abb0f93cSkardel static void 5086abb0f93cSkardel config_ntpdsim( 50872950cc38Schristos config_tree *ptree 5088abb0f93cSkardel ) 5089abb0f93cSkardel { 5090abb0f93cSkardel printf("Configuring Simulator...\n"); 5091abb0f93cSkardel printf("Some ntpd-specific commands in the configuration file will be ignored.\n"); 5092abb0f93cSkardel 5093abb0f93cSkardel config_tos(ptree); 5094abb0f93cSkardel config_monitor(ptree); 5095abb0f93cSkardel config_tinker(ptree); 5096ea66d795Schristos if (0) 5097ea66d795Schristos config_rlimit(ptree); /* not needed for the simulator */ 5098abb0f93cSkardel config_system_opts(ptree); 5099abb0f93cSkardel config_logconfig(ptree); 5100abb0f93cSkardel config_vars(ptree); 5101abb0f93cSkardel config_sim(ptree); 5102abb0f93cSkardel } 5103abb0f93cSkardel #endif /* SIM */ 5104abb0f93cSkardel 5105abb0f93cSkardel 5106abb0f93cSkardel /* 5107abb0f93cSkardel * config_remotely() - implements ntpd side of ntpq :config 5108abb0f93cSkardel */ 5109abb0f93cSkardel void 5110abb0f93cSkardel config_remotely( 5111abb0f93cSkardel sockaddr_u * remote_addr 5112abb0f93cSkardel ) 5113abb0f93cSkardel { 5114abb0f93cSkardel char origin[128]; 5115abb0f93cSkardel 5116abb0f93cSkardel snprintf(origin, sizeof(origin), "remote config from %s", 5117abb0f93cSkardel stoa(remote_addr)); 51185d681e99Schristos lex_init_stack(origin, NULL); /* no checking needed... */ 5119abb0f93cSkardel init_syntax_tree(&cfgt); 51205d681e99Schristos yyparse(); 51215d681e99Schristos lex_drop_stack(); 51225d681e99Schristos 5123abb0f93cSkardel cfgt.source.attr = CONF_SOURCE_NTPQ; 5124abb0f93cSkardel cfgt.timestamp = time(NULL); 5125abb0f93cSkardel cfgt.source.value.s = estrdup(stoa(remote_addr)); 5126abb0f93cSkardel 5127abb0f93cSkardel DPRINTF(1, ("Finished Parsing!!\n")); 5128abb0f93cSkardel 51295d681e99Schristos save_and_apply_config_tree(FALSE); 5130abb0f93cSkardel } 5131abb0f93cSkardel 5132abb0f93cSkardel 5133abb0f93cSkardel /* 5134abb0f93cSkardel * getconfig() - process startup configuration file e.g /etc/ntp.conf 5135abb0f93cSkardel */ 5136abb0f93cSkardel void 5137abb0f93cSkardel getconfig( 5138abb0f93cSkardel int argc, 51392950cc38Schristos char ** argv 5140abb0f93cSkardel ) 5141abb0f93cSkardel { 51422950cc38Schristos char line[256]; 5143abb0f93cSkardel 5144abb0f93cSkardel #ifdef DEBUG 5145abb0f93cSkardel atexit(free_all_config_trees); 5146abb0f93cSkardel #endif 5147abb0f93cSkardel #ifndef SYS_WINNT 5148abb0f93cSkardel config_file = CONFIG_FILE; 5149abb0f93cSkardel #else 5150abb0f93cSkardel temp = CONFIG_FILE; 51512950cc38Schristos if (!ExpandEnvironmentStringsA(temp, config_file_storage, 51522950cc38Schristos sizeof(config_file_storage))) { 51532950cc38Schristos msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m"); 5154abb0f93cSkardel exit(1); 5155abb0f93cSkardel } 5156abb0f93cSkardel config_file = config_file_storage; 5157abb0f93cSkardel 5158abb0f93cSkardel temp = ALT_CONFIG_FILE; 51592950cc38Schristos if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage, 51602950cc38Schristos sizeof(alt_config_file_storage))) { 51612950cc38Schristos msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m"); 5162abb0f93cSkardel exit(1); 5163abb0f93cSkardel } 5164abb0f93cSkardel alt_config_file = alt_config_file_storage; 5165abb0f93cSkardel #endif /* SYS_WINNT */ 5166abb0f93cSkardel 5167abb0f93cSkardel /* 5168abb0f93cSkardel * install a non default variable with this daemon version 5169abb0f93cSkardel */ 5170abb0f93cSkardel snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version); 5171abb0f93cSkardel set_sys_var(line, strlen(line) + 1, RO); 5172abb0f93cSkardel 5173abb0f93cSkardel /* 5174abb0f93cSkardel * Set up for the first time step to install a variable showing 5175abb0f93cSkardel * which syscall is being used to step. 5176abb0f93cSkardel */ 5177abb0f93cSkardel set_tod_using = &ntpd_set_tod_using; 5178abb0f93cSkardel 5179abb0f93cSkardel getCmdOpts(argc, argv); 5180abb0f93cSkardel init_syntax_tree(&cfgt); 5181abb0f93cSkardel if ( 51825d681e99Schristos !lex_init_stack(FindConfig(config_file), "r") 5183abb0f93cSkardel #ifdef HAVE_NETINFO 5184abb0f93cSkardel /* If there is no config_file, try NetInfo. */ 5185abb0f93cSkardel && check_netinfo && !(config_netinfo = get_netinfo_config()) 5186abb0f93cSkardel #endif /* HAVE_NETINFO */ 5187abb0f93cSkardel ) { 51887476e6e4Schristos msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file)); 5189abb0f93cSkardel #ifndef SYS_WINNT 5190abb0f93cSkardel io_open_sockets(); 5191abb0f93cSkardel 5192abb0f93cSkardel return; 5193abb0f93cSkardel #else 5194abb0f93cSkardel /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 5195abb0f93cSkardel 51965d681e99Schristos if (!lex_init_stack(FindConfig(alt_config_file), "r")) { 5197abb0f93cSkardel /* 5198abb0f93cSkardel * Broadcast clients can sometimes run without 5199abb0f93cSkardel * a configuration file. 5200abb0f93cSkardel */ 52017476e6e4Schristos msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file)); 5202abb0f93cSkardel io_open_sockets(); 5203abb0f93cSkardel 5204abb0f93cSkardel return; 5205abb0f93cSkardel } 5206abb0f93cSkardel cfgt.source.value.s = estrdup(alt_config_file); 5207abb0f93cSkardel #endif /* SYS_WINNT */ 5208*eabc0478Schristos } else { 5209abb0f93cSkardel cfgt.source.value.s = estrdup(config_file); 5210*eabc0478Schristos } 5211abb0f93cSkardel 5212abb0f93cSkardel /*** BULK OF THE PARSER ***/ 521315936e4aSchristos #if defined(DEBUG) && defined(YYDEBUG) 5214*eabc0478Schristos yydebug = (debug >= 9); 5215abb0f93cSkardel #endif 52165d681e99Schristos yyparse(); 52175d681e99Schristos lex_drop_stack(); 5218abb0f93cSkardel 5219abb0f93cSkardel DPRINTF(1, ("Finished Parsing!!\n")); 5220abb0f93cSkardel 5221abb0f93cSkardel cfgt.source.attr = CONF_SOURCE_FILE; 5222abb0f93cSkardel cfgt.timestamp = time(NULL); 5223abb0f93cSkardel 52245d681e99Schristos save_and_apply_config_tree(TRUE); 5225abb0f93cSkardel 5226abb0f93cSkardel #ifdef HAVE_NETINFO 5227abb0f93cSkardel if (config_netinfo) 5228abb0f93cSkardel free_netinfo_config(config_netinfo); 5229abb0f93cSkardel #endif /* HAVE_NETINFO */ 5230abb0f93cSkardel } 5231abb0f93cSkardel 5232abb0f93cSkardel 5233abb0f93cSkardel void 52345d681e99Schristos save_and_apply_config_tree(int/*BOOL*/ input_from_file) 5235abb0f93cSkardel { 52362950cc38Schristos config_tree *ptree; 5237abb0f93cSkardel #ifndef SAVECONFIG 52382950cc38Schristos config_tree *punlinked; 5239abb0f93cSkardel #endif 5240abb0f93cSkardel 5241abb0f93cSkardel /* 5242abb0f93cSkardel * Keep all the configuration trees applied since startup in 5243abb0f93cSkardel * a list that can be used to dump the configuration back to 5244abb0f93cSkardel * a text file. 5245abb0f93cSkardel */ 5246abb0f93cSkardel ptree = emalloc(sizeof(*ptree)); 5247abb0f93cSkardel memcpy(ptree, &cfgt, sizeof(*ptree)); 52482950cc38Schristos ZERO(cfgt); 5249abb0f93cSkardel 52502950cc38Schristos LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree); 5251abb0f93cSkardel 5252abb0f93cSkardel #ifdef SAVECONFIG 5253abb0f93cSkardel if (HAVE_OPT( SAVECONFIGQUIT )) { 5254abb0f93cSkardel FILE *dumpfile; 5255abb0f93cSkardel int err; 5256abb0f93cSkardel int dumpfailed; 5257abb0f93cSkardel 5258abb0f93cSkardel dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w"); 5259abb0f93cSkardel if (NULL == dumpfile) { 5260abb0f93cSkardel err = errno; 52612950cc38Schristos mfprintf(stderr, 52622950cc38Schristos "can not create save file %s, error %d %m\n", 52632950cc38Schristos OPT_ARG(SAVECONFIGQUIT), err); 5264abb0f93cSkardel exit(err); 5265abb0f93cSkardel } 5266abb0f93cSkardel 5267abb0f93cSkardel dumpfailed = dump_all_config_trees(dumpfile, 0); 5268abb0f93cSkardel if (dumpfailed) 5269abb0f93cSkardel fprintf(stderr, 5270abb0f93cSkardel "--saveconfigquit %s error %d\n", 5271abb0f93cSkardel OPT_ARG( SAVECONFIGQUIT ), 5272abb0f93cSkardel dumpfailed); 5273abb0f93cSkardel else 5274abb0f93cSkardel fprintf(stderr, 5275abb0f93cSkardel "configuration saved to %s\n", 5276abb0f93cSkardel OPT_ARG( SAVECONFIGQUIT )); 5277abb0f93cSkardel 5278abb0f93cSkardel exit(dumpfailed); 5279abb0f93cSkardel } 5280abb0f93cSkardel #endif /* SAVECONFIG */ 5281abb0f93cSkardel 5282abb0f93cSkardel /* The actual configuration done depends on whether we are configuring the 5283abb0f93cSkardel * simulator or the daemon. Perform a check and call the appropriate 5284abb0f93cSkardel * function as needed. 5285abb0f93cSkardel */ 5286abb0f93cSkardel 5287abb0f93cSkardel #ifndef SIM 52885d681e99Schristos config_ntpd(ptree, input_from_file); 5289abb0f93cSkardel #else 5290abb0f93cSkardel config_ntpdsim(ptree); 5291abb0f93cSkardel #endif 5292abb0f93cSkardel 5293abb0f93cSkardel /* 5294abb0f93cSkardel * With configure --disable-saveconfig, there's no use keeping 5295abb0f93cSkardel * the config tree around after application, so free it. 5296abb0f93cSkardel */ 5297abb0f93cSkardel #ifndef SAVECONFIG 5298abb0f93cSkardel UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link, 52992950cc38Schristos config_tree); 5300ea66d795Schristos INSIST(punlinked == ptree); 5301abb0f93cSkardel free_config_tree(ptree); 5302abb0f93cSkardel #endif 5303abb0f93cSkardel } 5304abb0f93cSkardel 5305ccc794f0Schristos /* Hack to disambiguate 'server' statements for refclocks and network peers. 5306ccc794f0Schristos * Please note the qualification 'hack'. It's just that. 5307ccc794f0Schristos */ 5308ccc794f0Schristos static int/*BOOL*/ 5309ccc794f0Schristos is_refclk_addr( 5310ccc794f0Schristos const address_node * addr 5311ccc794f0Schristos ) 5312ccc794f0Schristos { 531379045f13Schristos return addr && addr->address && !strncmp(addr->address, "127.127.", 8); 5314ccc794f0Schristos } 5315abb0f93cSkardel 5316ea66d795Schristos static void 5317abb0f93cSkardel ntpd_set_tod_using( 5318abb0f93cSkardel const char *which 5319abb0f93cSkardel ) 5320abb0f93cSkardel { 5321abb0f93cSkardel char line[128]; 5322abb0f93cSkardel 5323abb0f93cSkardel snprintf(line, sizeof(line), "settimeofday=\"%s\"", which); 5324abb0f93cSkardel set_sys_var(line, strlen(line) + 1, RO); 5325abb0f93cSkardel } 5326abb0f93cSkardel 5327abb0f93cSkardel 53282950cc38Schristos static char * 53292950cc38Schristos normal_dtoa( 53302950cc38Schristos double d 53312950cc38Schristos ) 53322950cc38Schristos { 53332950cc38Schristos char * buf; 53342950cc38Schristos char * pch_e; 53352950cc38Schristos char * pch_nz; 53362950cc38Schristos 53372950cc38Schristos LIB_GETBUF(buf); 53382950cc38Schristos snprintf(buf, LIB_BUFLENGTH, "%g", d); 53392950cc38Schristos 53402950cc38Schristos /* use lowercase 'e', strip any leading zeroes in exponent */ 53412950cc38Schristos pch_e = strchr(buf, 'e'); 53422950cc38Schristos if (NULL == pch_e) { 53432950cc38Schristos pch_e = strchr(buf, 'E'); 53442950cc38Schristos if (NULL == pch_e) 53452950cc38Schristos return buf; 53462950cc38Schristos *pch_e = 'e'; 53472950cc38Schristos } 53482950cc38Schristos pch_e++; 53492950cc38Schristos if ('-' == *pch_e) 53502950cc38Schristos pch_e++; 53512950cc38Schristos pch_nz = pch_e; 53522950cc38Schristos while ('0' == *pch_nz) 53532950cc38Schristos pch_nz++; 5354*eabc0478Schristos if (pch_nz > pch_e) { 5355*eabc0478Schristos memmove(pch_e, pch_nz, 1 + strlen(pch_nz)); 5356*eabc0478Schristos } 53572950cc38Schristos return buf; 53582950cc38Schristos } 53592950cc38Schristos 53602950cc38Schristos 5361abb0f93cSkardel /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c 5362abb0f93cSkardel * -------------------------------------------- 5363abb0f93cSkardel */ 5364abb0f93cSkardel 5365abb0f93cSkardel 5366abb0f93cSkardel /* 5367abb0f93cSkardel * get_pfxmatch - find value for prefixmatch 5368abb0f93cSkardel * and update char * accordingly 5369abb0f93cSkardel */ 53703123f114Skardel static u_int32 5371abb0f93cSkardel get_pfxmatch( 53723123f114Skardel const char ** pstr, 5373abb0f93cSkardel struct masks * m 5374abb0f93cSkardel ) 5375abb0f93cSkardel { 53763123f114Skardel while (m->name != NULL) { 53773123f114Skardel if (strncmp(*pstr, m->name, strlen(m->name)) == 0) { 53783123f114Skardel *pstr += strlen(m->name); 5379abb0f93cSkardel return m->mask; 5380abb0f93cSkardel } else { 5381abb0f93cSkardel m++; 5382abb0f93cSkardel } 5383abb0f93cSkardel } 5384abb0f93cSkardel return 0; 5385abb0f93cSkardel } 5386abb0f93cSkardel 5387abb0f93cSkardel /* 5388abb0f93cSkardel * get_match - find logmask value 5389abb0f93cSkardel */ 53903123f114Skardel static u_int32 5391abb0f93cSkardel get_match( 53923123f114Skardel const char * str, 5393abb0f93cSkardel struct masks * m 5394abb0f93cSkardel ) 5395abb0f93cSkardel { 53963123f114Skardel while (m->name != NULL) { 53973123f114Skardel if (strcmp(str, m->name) == 0) 5398abb0f93cSkardel return m->mask; 5399abb0f93cSkardel else 5400abb0f93cSkardel m++; 5401abb0f93cSkardel } 5402abb0f93cSkardel return 0; 5403abb0f93cSkardel } 5404abb0f93cSkardel 5405abb0f93cSkardel /* 5406abb0f93cSkardel * get_logmask - build bitmask for ntp_syslogmask 5407abb0f93cSkardel */ 54083123f114Skardel static u_int32 5409abb0f93cSkardel get_logmask( 54103123f114Skardel const char * str 5411abb0f93cSkardel ) 5412abb0f93cSkardel { 54133123f114Skardel const char * t; 54143123f114Skardel u_int32 offset; 54153123f114Skardel u_int32 mask; 5416abb0f93cSkardel 54173123f114Skardel mask = get_match(str, logcfg_noclass_items); 54183123f114Skardel if (mask != 0) 54193123f114Skardel return mask; 54203123f114Skardel 54213123f114Skardel t = str; 5422abb0f93cSkardel offset = get_pfxmatch(&t, logcfg_class); 54233123f114Skardel mask = get_match(t, logcfg_class_items); 5424abb0f93cSkardel 5425abb0f93cSkardel if (mask) 5426abb0f93cSkardel return mask << offset; 5427abb0f93cSkardel else 54283123f114Skardel msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored", 54293123f114Skardel str); 5430abb0f93cSkardel 5431abb0f93cSkardel return 0; 5432abb0f93cSkardel } 5433abb0f93cSkardel 5434abb0f93cSkardel 5435abb0f93cSkardel #ifdef HAVE_NETINFO 5436abb0f93cSkardel 5437abb0f93cSkardel /* 5438abb0f93cSkardel * get_netinfo_config - find the nearest NetInfo domain with an ntp 5439abb0f93cSkardel * configuration and initialize the configuration state. 5440abb0f93cSkardel */ 5441abb0f93cSkardel static struct netinfo_config_state * 5442abb0f93cSkardel get_netinfo_config(void) 5443abb0f93cSkardel { 5444abb0f93cSkardel ni_status status; 5445abb0f93cSkardel void *domain; 5446abb0f93cSkardel ni_id config_dir; 5447abb0f93cSkardel struct netinfo_config_state *config; 5448abb0f93cSkardel 5449abb0f93cSkardel if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; 5450abb0f93cSkardel 5451abb0f93cSkardel while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { 5452abb0f93cSkardel void *next_domain; 5453abb0f93cSkardel if (ni_open(domain, "..", &next_domain) != NI_OK) { 5454abb0f93cSkardel ni_free(next_domain); 5455abb0f93cSkardel break; 5456abb0f93cSkardel } 5457abb0f93cSkardel ni_free(domain); 5458abb0f93cSkardel domain = next_domain; 5459abb0f93cSkardel } 5460abb0f93cSkardel if (status != NI_OK) { 5461abb0f93cSkardel ni_free(domain); 5462abb0f93cSkardel return NULL; 5463abb0f93cSkardel } 5464abb0f93cSkardel 5465abb0f93cSkardel config = emalloc(sizeof(*config)); 5466abb0f93cSkardel config->domain = domain; 5467abb0f93cSkardel config->config_dir = config_dir; 5468abb0f93cSkardel config->prop_index = 0; 5469abb0f93cSkardel config->val_index = 0; 5470abb0f93cSkardel config->val_list = NULL; 5471abb0f93cSkardel 5472abb0f93cSkardel return config; 5473abb0f93cSkardel } 5474abb0f93cSkardel 5475abb0f93cSkardel 5476abb0f93cSkardel /* 5477abb0f93cSkardel * free_netinfo_config - release NetInfo configuration state 5478abb0f93cSkardel */ 5479abb0f93cSkardel static void 5480abb0f93cSkardel free_netinfo_config( 5481abb0f93cSkardel struct netinfo_config_state *config 5482abb0f93cSkardel ) 5483abb0f93cSkardel { 5484abb0f93cSkardel ni_free(config->domain); 5485abb0f93cSkardel free(config); 5486abb0f93cSkardel } 5487abb0f93cSkardel 5488abb0f93cSkardel 5489abb0f93cSkardel /* 5490abb0f93cSkardel * gettokens_netinfo - return tokens from NetInfo 5491abb0f93cSkardel */ 5492abb0f93cSkardel static int 5493abb0f93cSkardel gettokens_netinfo ( 5494abb0f93cSkardel struct netinfo_config_state *config, 5495abb0f93cSkardel char **tokenlist, 5496abb0f93cSkardel int *ntokens 5497abb0f93cSkardel ) 5498abb0f93cSkardel { 5499abb0f93cSkardel int prop_index = config->prop_index; 5500abb0f93cSkardel int val_index = config->val_index; 5501abb0f93cSkardel char **val_list = config->val_list; 5502abb0f93cSkardel 5503abb0f93cSkardel /* 5504abb0f93cSkardel * Iterate through each keyword and look for a property that matches it. 5505abb0f93cSkardel */ 5506abb0f93cSkardel again: 5507abb0f93cSkardel if (!val_list) { 5508abb0f93cSkardel for (; prop_index < COUNTOF(keywords); prop_index++) 5509abb0f93cSkardel { 5510abb0f93cSkardel ni_namelist namelist; 5511abb0f93cSkardel struct keyword current_prop = keywords[prop_index]; 5512abb0f93cSkardel ni_index index; 5513abb0f93cSkardel 5514abb0f93cSkardel /* 5515abb0f93cSkardel * For each value associated in the property, we're going to return 5516abb0f93cSkardel * a separate line. We squirrel away the values in the config state 5517abb0f93cSkardel * so the next time through, we don't need to do this lookup. 5518abb0f93cSkardel */ 5519abb0f93cSkardel NI_INIT(&namelist); 5520abb0f93cSkardel if (NI_OK == ni_lookupprop(config->domain, 5521abb0f93cSkardel &config->config_dir, current_prop.text, 5522abb0f93cSkardel &namelist)) { 5523abb0f93cSkardel 5524abb0f93cSkardel /* Found the property, but it has no values */ 5525abb0f93cSkardel if (namelist.ni_namelist_len == 0) continue; 5526abb0f93cSkardel 5527abb0f93cSkardel config->val_list = 55285d681e99Schristos eallocarray( 55295d681e99Schristos (namelist.ni_namelist_len + 1), 55305d681e99Schristos sizeof(char*)); 5531abb0f93cSkardel val_list = config->val_list; 5532abb0f93cSkardel 5533abb0f93cSkardel for (index = 0; 5534abb0f93cSkardel index < namelist.ni_namelist_len; 5535abb0f93cSkardel index++) { 5536abb0f93cSkardel char *value; 5537abb0f93cSkardel 5538abb0f93cSkardel value = namelist.ni_namelist_val[index]; 5539abb0f93cSkardel val_list[index] = estrdup(value); 5540abb0f93cSkardel } 5541abb0f93cSkardel val_list[index] = NULL; 5542abb0f93cSkardel 5543abb0f93cSkardel break; 5544abb0f93cSkardel } 5545abb0f93cSkardel ni_namelist_free(&namelist); 5546abb0f93cSkardel } 5547abb0f93cSkardel config->prop_index = prop_index; 5548abb0f93cSkardel } 5549abb0f93cSkardel 5550abb0f93cSkardel /* No list; we're done here. */ 5551abb0f93cSkardel if (!val_list) 5552abb0f93cSkardel return CONFIG_UNKNOWN; 5553abb0f93cSkardel 5554abb0f93cSkardel /* 5555abb0f93cSkardel * We have a list of values for the current property. 5556abb0f93cSkardel * Iterate through them and return each in order. 5557abb0f93cSkardel */ 5558abb0f93cSkardel if (val_list[val_index]) { 5559abb0f93cSkardel int ntok = 1; 5560abb0f93cSkardel int quoted = 0; 5561abb0f93cSkardel char *tokens = val_list[val_index]; 5562abb0f93cSkardel 5563abb0f93cSkardel msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); 5564abb0f93cSkardel 5565abb0f93cSkardel (const char*)tokenlist[0] = keywords[prop_index].text; 5566abb0f93cSkardel for (ntok = 1; ntok < MAXTOKENS; ntok++) { 5567abb0f93cSkardel tokenlist[ntok] = tokens; 5568abb0f93cSkardel while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) 5569abb0f93cSkardel quoted ^= (*tokens++ == '"'); 5570abb0f93cSkardel 5571abb0f93cSkardel if (ISEOL(*tokens)) { 5572abb0f93cSkardel *tokens = '\0'; 5573abb0f93cSkardel break; 5574abb0f93cSkardel } else { /* must be space */ 5575abb0f93cSkardel *tokens++ = '\0'; 5576abb0f93cSkardel while (ISSPACE(*tokens)) 5577abb0f93cSkardel tokens++; 5578abb0f93cSkardel if (ISEOL(*tokens)) 5579abb0f93cSkardel break; 5580abb0f93cSkardel } 5581abb0f93cSkardel } 5582abb0f93cSkardel 5583abb0f93cSkardel if (ntok == MAXTOKENS) { 5584abb0f93cSkardel /* HMS: chomp it to lose the EOL? */ 5585abb0f93cSkardel msyslog(LOG_ERR, 5586abb0f93cSkardel "gettokens_netinfo: too many tokens. Ignoring: %s", 5587abb0f93cSkardel tokens); 5588abb0f93cSkardel } else { 5589abb0f93cSkardel *ntokens = ntok + 1; 5590abb0f93cSkardel } 5591abb0f93cSkardel 5592abb0f93cSkardel config->val_index++; /* HMS: Should this be in the 'else'? */ 5593abb0f93cSkardel 5594abb0f93cSkardel return keywords[prop_index].keytype; 5595abb0f93cSkardel } 5596abb0f93cSkardel 5597abb0f93cSkardel /* We're done with the current property. */ 5598abb0f93cSkardel prop_index = ++config->prop_index; 5599abb0f93cSkardel 5600abb0f93cSkardel /* Free val_list and reset counters. */ 5601abb0f93cSkardel for (val_index = 0; val_list[val_index]; val_index++) 5602abb0f93cSkardel free(val_list[val_index]); 5603abb0f93cSkardel free(val_list); 5604abb0f93cSkardel val_list = config->val_list = NULL; 5605abb0f93cSkardel val_index = config->val_index = 0; 5606abb0f93cSkardel 5607abb0f93cSkardel goto again; 5608abb0f93cSkardel } 5609abb0f93cSkardel #endif /* HAVE_NETINFO */ 5610abb0f93cSkardel 56112950cc38Schristos 5612abb0f93cSkardel /* 5613abb0f93cSkardel * getnetnum - return a net number (this is crude, but careful) 5614abb0f93cSkardel * 56152950cc38Schristos * returns 1 for success, and mysteriously, 0 for most failures, and 56162950cc38Schristos * -1 if the address found is IPv6 and we believe IPv6 isn't working. 5617abb0f93cSkardel */ 5618abb0f93cSkardel static int 5619abb0f93cSkardel getnetnum( 5620abb0f93cSkardel const char *num, 5621abb0f93cSkardel sockaddr_u *addr, 5622*eabc0478Schristos int complain, /* ignored */ 56232950cc38Schristos enum gnn_type a_type /* ignored */ 5624abb0f93cSkardel ) 5625abb0f93cSkardel { 5626af12ab5eSchristos REQUIRE(AF_UNSPEC == AF(addr) || 56272950cc38Schristos AF_INET == AF(addr) || 56282950cc38Schristos AF_INET6 == AF(addr)); 5629abb0f93cSkardel 5630*eabc0478Schristos if (!is_ip_address(num, AF(addr), addr)) { 56312950cc38Schristos return 0; 5632*eabc0478Schristos } 56332950cc38Schristos # ifdef ISC_PLATFORM_HAVESALEN 56342950cc38Schristos addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr)); 56352950cc38Schristos # endif 56362950cc38Schristos SET_PORT(addr, NTP_PORT); 5637abb0f93cSkardel 5638*eabc0478Schristos if (IS_IPV6(addr) && !ipv6_works) { 5639*eabc0478Schristos return -1; 5640*eabc0478Schristos } else { 5641abb0f93cSkardel return 1; 5642abb0f93cSkardel } 5643*eabc0478Schristos } 5644*eabc0478Schristos 5645abb0f93cSkardel 56462950cc38Schristos #if defined(HAVE_SETRLIMIT) 56472950cc38Schristos void 56482950cc38Schristos ntp_rlimit( 56492950cc38Schristos int rl_what, 56502950cc38Schristos rlim_t rl_value, 56512950cc38Schristos int rl_scale, 56522950cc38Schristos const char * rl_sstr 5653abb0f93cSkardel ) 5654abb0f93cSkardel { 56552950cc38Schristos struct rlimit rl; 5656abb0f93cSkardel 56572950cc38Schristos switch (rl_what) { 56582950cc38Schristos # ifdef RLIMIT_MEMLOCK 56592950cc38Schristos case RLIMIT_MEMLOCK: 56604eea345dSchristos if (HAVE_OPT( SAVECONFIGQUIT )) { 56614eea345dSchristos break; 56624eea345dSchristos } 56632950cc38Schristos /* 56642950cc38Schristos * The default RLIMIT_MEMLOCK is very low on Linux systems. 56652950cc38Schristos * Unless we increase this limit malloc calls are likely to 56662950cc38Schristos * fail if we drop root privilege. To be useful the value 56672950cc38Schristos * has to be larger than the largest ntpd resident set size. 56682950cc38Schristos */ 56692950cc38Schristos DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n", 56702950cc38Schristos (int)(rl_value / rl_scale), rl_sstr)); 56712950cc38Schristos rl.rlim_cur = rl.rlim_max = rl_value; 56722950cc38Schristos if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 56732950cc38Schristos msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 56742950cc38Schristos break; 56752950cc38Schristos # endif /* RLIMIT_MEMLOCK */ 5676abb0f93cSkardel 56772950cc38Schristos # ifdef RLIMIT_NOFILE 56782950cc38Schristos case RLIMIT_NOFILE: 56792950cc38Schristos /* 56802950cc38Schristos * For large systems the default file descriptor limit may 56812950cc38Schristos * not be enough. 56822950cc38Schristos */ 56832950cc38Schristos DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n", 56842950cc38Schristos (int)(rl_value / rl_scale), rl_sstr)); 56852950cc38Schristos rl.rlim_cur = rl.rlim_max = rl_value; 56862950cc38Schristos if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 56872950cc38Schristos msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m"); 56882950cc38Schristos break; 56892950cc38Schristos # endif /* RLIMIT_NOFILE */ 5690abb0f93cSkardel 56912950cc38Schristos # ifdef RLIMIT_STACK 56922950cc38Schristos case RLIMIT_STACK: 56932950cc38Schristos /* 56942950cc38Schristos * Provide a way to set the stack limit to something 56952950cc38Schristos * smaller, so that we don't lock a lot of unused 56962950cc38Schristos * stack memory. 56972950cc38Schristos */ 56982950cc38Schristos DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n", 56992950cc38Schristos (int)(rl_value / rl_scale), rl_sstr)); 57002950cc38Schristos if (-1 == getrlimit(RLIMIT_STACK, &rl)) { 57015d681e99Schristos msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m"); 57023123f114Skardel } else { 57032950cc38Schristos if (rl_value > rl.rlim_max) { 5704abb0f93cSkardel msyslog(LOG_WARNING, 57052950cc38Schristos "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.", 57062950cc38Schristos (u_long)rl.rlim_max, 57072950cc38Schristos (u_long)rl_value); 57082950cc38Schristos rl_value = rl.rlim_max; 5709abb0f93cSkardel } 57105d681e99Schristos rl.rlim_cur = rl_value; 57112950cc38Schristos if (-1 == setrlimit(RLIMIT_STACK, &rl)) { 571202110410Smaya msyslog(LOG_DEBUG, 57135d681e99Schristos "ntp_rlimit: Cannot set RLIMIT_STACK: %m"); 5714abb0f93cSkardel } 5715abb0f93cSkardel } 57162950cc38Schristos break; 57172950cc38Schristos # endif /* RLIMIT_STACK */ 57182950cc38Schristos 57192950cc38Schristos default: 5720ccc794f0Schristos fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what); 5721abb0f93cSkardel } 57222950cc38Schristos } 57232950cc38Schristos #endif /* HAVE_SETRLIMIT */ 5724