aboutsummaryrefslogtreecommitdiff
path: root/ntpd/ntp_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_config.c')
-rw-r--r--ntpd/ntp_config.c5715
1 files changed, 3915 insertions, 1800 deletions
diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c
index beb4c4847e71..db9682a74cbd 100644
--- a/ntpd/ntp_config.c
+++ b/ntpd/ntp_config.c
@@ -1,6 +1,14 @@
-/*
- * ntp_config.c - read and apply configuration information
+/* ntp_config.c
+ *
+ * This file contains the ntpd configuration code.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Some parts borrowed from the older ntp_config.c
+ * Copyright (c) 2006
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -9,20 +17,30 @@
# include <netinfo/ni.h>
#endif
+#include "ntp.h"
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_filegen.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+#include "ntpd-opts.h"
+/*
+ * Sim header. Currently unconditionally included
+ * PDMXXX This needs to be a conditional include
+ */
+#include "ntpsim.h"
+
#include <ntp_random.h>
+#include "ntp_intres.h"
#include <isc/net.h>
#include <isc/result.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
+# include <sys/param.h>
#endif
#include <signal.h>
#ifndef SIGCHLD
@@ -36,7 +54,6 @@
#ifdef SYS_WINNT
# include <io.h>
-static HANDLE ResolverThreadHandle = NULL;
HANDLE ResolverEventHandle;
#else
int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
@@ -50,288 +67,55 @@ int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent p
#include "ntp_config.h"
#include "ntp_cmdargs.h"
-extern int priority_done;
-
-/*
- * These routines are used to read the configuration file at
- * startup time. An entry in the file must fit on a single line.
- * Entries are processed as multiple tokens separated by white space
- * Lines are considered terminated when a '#' is encountered. Blank
- * lines are ignored.
- */
-/*
- * Translation table - keywords to function index
- */
-struct keyword {
- const char *text;
- int keytype;
-};
-
-/*
- * Command keywords
- */
-static struct keyword keywords[] = {
- { "automax", CONFIG_AUTOMAX },
- { "broadcast", CONFIG_BROADCAST },
- { "broadcastclient", CONFIG_BROADCASTCLIENT },
- { "broadcastdelay", CONFIG_BDELAY },
- { "calldelay", CONFIG_CDELAY},
-#ifdef OPENSSL
- { "crypto", CONFIG_CRYPTO },
-#endif /* OPENSSL */
- { "controlkey", CONFIG_CONTROLKEY },
- { "disable", CONFIG_DISABLE },
- { "driftfile", CONFIG_DRIFTFILE },
- { "enable", CONFIG_ENABLE },
- { "end", CONFIG_END },
- { "filegen", CONFIG_FILEGEN },
- { "fudge", CONFIG_FUDGE },
- { "includefile", CONFIG_INCLUDEFILE },
- { "keys", CONFIG_KEYS },
- { "keysdir", CONFIG_KEYSDIR },
- { "logconfig", CONFIG_LOGCONFIG },
- { "logfile", CONFIG_LOGFILE },
- { "manycastclient", CONFIG_MANYCASTCLIENT },
- { "manycastserver", CONFIG_MANYCASTSERVER },
- { "multicastclient", CONFIG_MULTICASTCLIENT },
- { "peer", CONFIG_PEER },
- { "phone", CONFIG_PHONE },
- { "pidfile", CONFIG_PIDFILE },
- { "discard", CONFIG_DISCARD },
- { "requestkey", CONFIG_REQUESTKEY },
- { "restrict", CONFIG_RESTRICT },
- { "revoke", CONFIG_REVOKE },
- { "server", CONFIG_SERVER },
- { "setvar", CONFIG_SETVAR },
- { "statistics", CONFIG_STATISTICS },
- { "statsdir", CONFIG_STATSDIR },
- { "tick", CONFIG_ADJ },
- { "tinker", CONFIG_TINKER },
- { "tos", CONFIG_TOS },
- { "trap", CONFIG_TRAP },
- { "trustedkey", CONFIG_TRUSTEDKEY },
- { "ttl", CONFIG_TTL },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "peer", "server", "broadcast" modifier keywords
- */
-static struct keyword mod_keywords[] = {
- { "autokey", CONF_MOD_SKEY },
- { "burst", CONF_MOD_BURST },
- { "iburst", CONF_MOD_IBURST },
- { "key", CONF_MOD_KEY },
- { "maxpoll", CONF_MOD_MAXPOLL },
- { "minpoll", CONF_MOD_MINPOLL },
- { "mode", CONF_MOD_MODE }, /* refclocks */
- { "noselect", CONF_MOD_NOSELECT },
- { "preempt", CONF_MOD_PREEMPT },
- { "true", CONF_MOD_TRUE },
- { "prefer", CONF_MOD_PREFER },
- { "ttl", CONF_MOD_TTL }, /* NTP peers */
- { "version", CONF_MOD_VERSION },
- { "dynamic", CONF_MOD_DYNAMIC },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "restrict" modifier keywords
- */
-static struct keyword res_keywords[] = {
- { "ignore", CONF_RES_IGNORE },
- { "limited", CONF_RES_LIMITED },
- { "kod", CONF_RES_DEMOBILIZE },
- { "lowpriotrap", CONF_RES_LPTRAP },
- { "mask", CONF_RES_MASK },
- { "nomodify", CONF_RES_NOMODIFY },
- { "nopeer", CONF_RES_NOPEER },
- { "noquery", CONF_RES_NOQUERY },
- { "noserve", CONF_RES_NOSERVE },
- { "notrap", CONF_RES_NOTRAP },
- { "notrust", CONF_RES_NOTRUST },
- { "ntpport", CONF_RES_NTPPORT },
- { "version", CONF_RES_VERSION },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "trap" modifier keywords
- */
-static struct keyword trap_keywords[] = {
- { "port", CONF_TRAP_PORT },
- { "interface", CONF_TRAP_INTERFACE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "fudge" modifier keywords
- */
-static struct keyword fudge_keywords[] = {
- { "flag1", CONF_FDG_FLAG1 },
- { "flag2", CONF_FDG_FLAG2 },
- { "flag3", CONF_FDG_FLAG3 },
- { "flag4", CONF_FDG_FLAG4 },
- { "refid", CONF_FDG_REFID }, /* this mapping should be cleaned up (endianness, \0) - kd 20041031 */
- { "stratum", CONF_FDG_STRATUM },
- { "time1", CONF_FDG_TIME1 },
- { "time2", CONF_FDG_TIME2 },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "filegen" modifier keywords
- */
-static struct keyword filegen_keywords[] = {
- { "disable", CONF_FGEN_FLAG_DISABLE },
- { "enable", CONF_FGEN_FLAG_ENABLE },
- { "file", CONF_FGEN_FILE },
- { "link", CONF_FGEN_FLAG_LINK },
- { "nolink", CONF_FGEN_FLAG_NOLINK },
- { "type", CONF_FGEN_TYPE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "type" modifier keywords
- */
-static struct keyword fgen_types[] = {
- { "age", FILEGEN_AGE },
- { "day", FILEGEN_DAY },
- { "month", FILEGEN_MONTH },
- { "none", FILEGEN_NONE },
- { "pid", FILEGEN_PID },
- { "week", FILEGEN_WEEK },
- { "year", FILEGEN_YEAR },
- { "", CONFIG_UNKNOWN}
-};
-
-/*
- * "enable", "disable" modifier keywords
- */
-static struct keyword flags_keywords[] = {
- { "auth", PROTO_AUTHENTICATE },
- { "bclient", PROTO_BROADCLIENT },
- { "calibrate", PROTO_CAL },
- { "kernel", PROTO_KERNEL },
- { "monitor", PROTO_MONITOR },
- { "ntp", PROTO_NTP },
- { "stats", PROTO_FILEGEN },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "discard" modifier keywords
- */
-static struct keyword discard_keywords[] = {
- { "average", CONF_DISCARD_AVERAGE },
- { "minimum", CONF_DISCARD_MINIMUM },
- { "monitor", CONF_DISCARD_MONITOR },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tinker" modifier keywords
- */
-static struct keyword tinker_keywords[] = {
- { "step", CONF_CLOCK_MAX },
- { "panic", CONF_CLOCK_PANIC },
- { "dispersion", CONF_CLOCK_PHI },
- { "stepout", CONF_CLOCK_MINSTEP },
- { "allan", CONF_CLOCK_ALLAN },
- { "huffpuff", CONF_CLOCK_HUFFPUFF },
- { "freq", CONF_CLOCK_FREQ },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tos" modifier keywords
- */
-static struct keyword tos_keywords[] = {
- { "minclock", CONF_TOS_MINCLOCK },
- { "maxclock", CONF_TOS_MAXCLOCK },
- { "minsane", CONF_TOS_MINSANE },
- { "floor", CONF_TOS_FLOOR },
- { "ceiling", CONF_TOS_CEILING },
- { "cohort", CONF_TOS_COHORT },
- { "mindist", CONF_TOS_MINDISP },
- { "maxdist", CONF_TOS_MAXDIST },
- { "maxhop", CONF_TOS_MAXHOP },
- { "beacon", CONF_TOS_BEACON },
- { "orphan", CONF_TOS_ORPHAN },
- { "", CONFIG_UNKNOWN }
-};
-
-#ifdef OPENSSL
-/*
- * "crypto" modifier keywords
- */
-static struct keyword crypto_keywords[] = {
- { "cert", CONF_CRYPTO_CERT },
- { "gqpar", CONF_CRYPTO_GQPAR },
- { "host", CONF_CRYPTO_RSA },
- { "ident", CONF_CRYPTO_IDENT },
- { "iffpar", CONF_CRYPTO_IFFPAR },
- { "leap", CONF_CRYPTO_LEAP },
- { "mvpar", CONF_CRYPTO_MVPAR },
- { "pw", CONF_CRYPTO_PW },
- { "randfile", CONF_CRYPTO_RAND },
- { "sign", CONF_CRYPTO_SIGN },
- { "", CONFIG_UNKNOWN }
-};
-#endif /* OPENSSL */
+#include "ntp_scanner.h"
+#include "ntp_parser.h"
+#include "ntp_data_structures.h"
-/*
- * Address type selection, IPv4 or IPv4.
- * Used on various lines.
- */
-static struct keyword addr_type[] = {
- { "-4", CONF_ADDR_IPV4 },
- { "-6", CONF_ADDR_IPV6 },
- { "", CONFIG_UNKNOWN }
-};
/*
* "logconfig" building blocks
*/
struct masks {
- const char *name;
- unsigned long mask;
+ const char * const name;
+ const u_int32 mask;
};
static struct masks logcfg_class[] = {
- { "clock", NLOG_OCLOCK },
- { "peer", NLOG_OPEER },
- { "sync", NLOG_OSYNC },
- { "sys", NLOG_OSYS },
- { (char *)0, 0 }
+ { "clock", NLOG_OCLOCK },
+ { "peer", NLOG_OPEER },
+ { "sync", NLOG_OSYNC },
+ { "sys", NLOG_OSYS },
+ { NULL, 0 }
};
-static struct masks logcfg_item[] = {
+/* logcfg_noclass_items[] masks are complete and must not be shifted */
+static struct masks logcfg_noclass_items[] = {
+ { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
+ { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
+ { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
+ { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
+ { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
+ /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
+ { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
+ { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
+ { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
+ { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
+ { NULL, 0 }
+};
+
+/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
+static struct masks logcfg_class_items[] = {
+ { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
{ "info", NLOG_INFO },
- { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
{ "events", NLOG_EVENT },
- { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
{ "status", NLOG_STATUS },
- { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
{ "statistics", NLOG_STATIST },
- { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
- { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
- { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
- { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
- { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
- { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
- { (char *)0, 0 }
+ { NULL, 0 }
};
-/*
- * Limits on things
- */
-#define MAXTOKENS 20 /* 20 tokens on line */
-#define MAXLINE 1024 /* maximum length of line */
+/* Limits */
#define MAXPHONE 10 /* maximum number of phone strings */
#define MAXPPS 20 /* maximum length of PPS device string */
-#define MAXINCLUDELEVEL 5 /* maximum include file levels */
/*
* Miscellaneous macros
@@ -341,14 +125,11 @@ static struct masks logcfg_item[] = {
#define ISSPACE(c) ((c) == ' ' || (c) == '\t')
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-#define KEY_TYPE_MD5 4
-
/*
* File descriptor used by the resolver save routines, and temporary file
* name.
*/
int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
-static FILE *res_fp;
#ifndef SYS_WINNT
static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
#define RES_TEMPFILE "/tmp/ntpXXXXXX"
@@ -359,25 +140,38 @@ static char res_file[MAX_PATH];
/*
* Definitions of things either imported from or exported to outside
*/
-
-short default_ai_family = AF_UNSPEC; /* Default either IPv4 or IPv6 */
-char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
-char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
+extern int yydebug; /* ntp_parser.c (.y) */
+int curr_include_level; /* The current include level */
+struct FILE_INFO *fp[MAXINCLUDELEVEL+1];
+FILE *res_fp;
+struct config_tree cfgt; /* Parser output stored here */
+struct config_tree *cfg_tree_history = NULL; /* History of configs */
+char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
+char default_keysdir[] = NTP_KEYSDIR;
+char *keysdir = default_keysdir; /* crypto keys directory */
+char * saveconfigdir;
#if defined(HAVE_SCHED_SETSCHEDULER)
int config_priority_override = 0;
int config_priority;
#endif
const char *config_file;
+char default_ntp_signd_socket[] =
+#ifdef NTP_SIGND_PATH
+ NTP_SIGND_PATH;
+#else
+ "";
+#endif
+char *ntp_signd_socket = default_ntp_signd_socket;
#ifdef HAVE_NETINFO
- struct netinfo_config_state *config_netinfo = NULL;
- int check_netinfo = 1;
+struct netinfo_config_state *config_netinfo = NULL;
+int check_netinfo = 1;
#endif /* HAVE_NETINFO */
#ifdef SYS_WINNT
- char *alt_config_file;
- LPTSTR temp;
- char config_file_storage[MAX_PATH];
- char alt_config_file_storage[MAX_PATH];
+char *alt_config_file;
+LPTSTR temp;
+char config_file_storage[MAX_PATH];
+char alt_config_file_storage[MAX_PATH];
#endif /* SYS_WINNT */
#ifdef HAVE_NETINFO
@@ -393,1513 +187,3744 @@ struct netinfo_config_state {
};
#endif
+struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
+ pointer info */
+int input_from_file = 1; /* A boolean flag, which when set, indicates that
+ the input is to be taken from the configuration
+ file, instead of the remote-configuration buffer
+ */
+
+int old_config_style = 1; /* A boolean flag, which when set,
+ * indicates that the old configuration
+ * format with a newline at the end of
+ * every command is being used
+ */
+int cryptosw; /* crypto command called */
+
+extern int sys_maxclock;
+extern char *stats_drift_file; /* name of the driftfile */
+extern char *leapseconds_file_name; /*name of the leapseconds file */
+#ifdef HAVE_IPTOS_SUPPORT
+extern unsigned int qos; /* QoS setting */
+#endif /* HAVE_IPTOS_SUPPORT */
+
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
/*
- * Function prototypes
+ * backwards compatibility flags
*/
-static unsigned long get_pfxmatch P((char **, struct masks *));
-static unsigned long get_match P((char *, struct masks *));
-static unsigned long get_logmask P((char *));
-#ifdef HAVE_NETINFO
-static struct netinfo_config_state *get_netinfo_config P((void));
-static void free_netinfo_config P((struct netinfo_config_state *));
-static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
+bc_entry bc_list[] = {
+ { T_Bc_bugXXXX, 1 } /* default enabled */
+};
+
+/*
+ * declare an int pointer for each flag for quick testing without
+ * walking bc_list. If the pointer is consumed by libntp rather
+ * than ntpd, declare it in a libntp source file pointing to storage
+ * initialized with the appropriate value for other libntp clients, and
+ * redirect it to point into bc_list during ntpd startup.
+ */
+int *p_bcXXXX_enabled = &bc_list[0].enabled;
#endif
-static int gettokens P((FILE *, char *, char **, int *));
-static int matchkey P((char *, struct keyword *, int));
+
+/* FUNCTION PROTOTYPES */
+
+static void apply_enable_disable(queue *q, int enable);
+static void init_syntax_tree(struct config_tree *);
+
+#ifdef FREE_CFG_T
+static void free_auth_node(struct config_tree *);
+
+static void free_config_other_modes(struct config_tree *);
+static void free_config_auth(struct config_tree *);
+static void free_config_tos(struct config_tree *);
+static void free_config_monitor(struct config_tree *);
+static void free_config_access(struct config_tree *);
+static void free_config_tinker(struct config_tree *);
+static void free_config_system_opts(struct config_tree *);
+static void free_config_logconfig(struct config_tree *);
+static void free_config_phone(struct config_tree *);
+static void free_config_qos(struct config_tree *);
+static void free_config_setvar(struct config_tree *);
+static void free_config_ttl(struct config_tree *);
+static void free_config_trap(struct config_tree *);
+static void free_config_fudge(struct config_tree *);
+static void free_config_vars(struct config_tree *);
+static void free_config_peers(struct config_tree *);
+static void free_config_unpeers(struct config_tree *);
+static void free_config_nic_rules(struct config_tree *);
+#ifdef SIM
+static void free_config_sim(struct config_tree *);
+#endif
+
+ void free_all_config_trees(void); /* atexit() */
+static void free_config_tree(struct config_tree *ptree);
+#endif /* FREE_CFG_T */
+
+double *create_dval(double val);
+void destroy_restrict_node(struct restrict_node *my_node);
+static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
+static int get_correct_host_mode(int hmode);
+static void save_and_apply_config_tree(void);
+void getconfig(int argc,char *argv[]);
+#if !defined(SIM)
+static sockaddr_u *get_next_address(struct address_node *addr);
+#endif
+
+static void config_other_modes(struct config_tree *);
+static void config_auth(struct config_tree *);
+static void config_tos(struct config_tree *);
+static void config_monitor(struct config_tree *);
+static void config_access(struct config_tree *);
+static void config_tinker(struct config_tree *);
+static void config_system_opts(struct config_tree *);
+static void config_logconfig(struct config_tree *);
+static void config_phone(struct config_tree *);
+static void config_qos(struct config_tree *);
+static void config_setvar(struct config_tree *);
+static void config_ttl(struct config_tree *);
+static void config_trap(struct config_tree *);
+static void config_fudge(struct config_tree *);
+static void config_vars(struct config_tree *);
+static void config_peers(struct config_tree *);
+static void config_unpeers(struct config_tree *);
+static void config_nic_rules(struct config_tree *);
+
+#ifdef SIM
+static void config_sim(struct config_tree *);
+static void config_ntpdsim(struct config_tree *);
+#else
+static void config_ntpd(struct config_tree *);
+#endif
+
enum gnn_type {
t_UNK, /* Unknown */
t_REF, /* Refclock */
t_MSK /* Network Mask */
- };
-static int getnetnum P((const char *, struct sockaddr_storage *, int,
- enum gnn_type));
-static void save_resolve P((char *, int, int, int, int, u_int, int,
- keyid_t, u_char *));
-static void do_resolve_internal P((void));
-static void abort_resolve P((void));
-#if !defined(VMS) && !defined(SYS_WINNT)
-static RETSIGTYPE catchchild P((int));
-#endif /* VMS */
+};
-/*
- * get_pfxmatch - find value for prefixmatch
- * and update char * accordingly
+#define DESTROY_QUEUE(q) \
+do { \
+ if (q) { \
+ destroy_queue(q); \
+ (q) = NULL; \
+ } \
+} while (0)
+
+void ntpd_set_tod_using(const char *);
+static u_int32 get_pfxmatch(const char **, struct masks *);
+static u_int32 get_match(const char *, struct masks *);
+static u_int32 get_logmask(const char *);
+static int getnetnum(const char *num,sockaddr_u *addr, int complain,
+ enum gnn_type a_type);
+static int get_multiple_netnums(const char *num, sockaddr_u *addr,
+ struct addrinfo **res, int complain,
+ enum gnn_type a_type);
+static void save_resolve(char *name, int no_needed, int type,
+ int mode, int version, int minpoll, int maxpoll,
+ u_int flags, int ttl, keyid_t keyid, u_char *keystr);
+static void abort_resolve(void);
+static void do_resolve_internal(void);
+
+
+
+/* FUNCTIONS FOR INITIALIZATION
+ * ----------------------------
*/
-static unsigned long
-get_pfxmatch(
- char ** s,
- struct masks *m
+
+#ifdef FREE_CFG_T
+static void
+free_auth_node(
+ struct config_tree *ptree
)
{
- while (m->name) {
- if (strncmp(*s, m->name, strlen(m->name)) == 0) {
- *s += strlen(m->name);
- return m->mask;
- } else {
- m++;
- }
+ if (ptree->auth.keys) {
+ free(ptree->auth.keys);
+ ptree->auth.keys = NULL;
}
- return 0;
-}
-/*
- * get_match - find logmask value
- */
-static unsigned long
-get_match(
- char *s,
- struct masks *m
- )
-{
- while (m->name) {
- if (strcmp(s, m->name) == 0) {
- return m->mask;
- } else {
- m++;
- }
+ if (ptree->auth.keysdir) {
+ free(ptree->auth.keysdir);
+ ptree->auth.keysdir = NULL;
+ }
+
+ if (ptree->auth.ntp_signd_socket) {
+ free(ptree->auth.ntp_signd_socket);
+ ptree->auth.ntp_signd_socket = NULL;
}
- return 0;
}
+#endif /* DEBUG */
-/*
- * get_logmask - build bitmask for ntp_syslogmask
- */
-static unsigned long
-get_logmask(
- char *s
+
+static void
+init_syntax_tree(
+ struct config_tree *ptree
)
{
- char *t;
- unsigned long offset;
- unsigned long mask;
+ memset(ptree, 0, sizeof(*ptree));
+
+ ptree->peers = create_queue();
+ ptree->unpeers = create_queue();
+ ptree->orphan_cmds = create_queue();
+ ptree->manycastserver = create_queue();
+ ptree->multicastclient = create_queue();
+ ptree->stats_list = create_queue();
+ ptree->filegen_opts = create_queue();
+ ptree->discard_opts = create_queue();
+ ptree->restrict_opts = create_queue();
+ ptree->enable_opts = create_queue();
+ ptree->disable_opts = create_queue();
+ ptree->tinker = create_queue();
+ ptree->fudge = create_queue();
+ ptree->logconfig = create_queue();
+ ptree->phone = create_queue();
+ ptree->qos = create_queue();
+ ptree->setvar = create_queue();
+ ptree->ttl = create_queue();
+ ptree->trap = create_queue();
+ ptree->vars = create_queue();
+ ptree->nic_rules = create_queue();
+ ptree->auth.crypto_cmd_list = create_queue();
+ ptree->auth.trusted_key_list = create_queue();
+}
- t = s;
- offset = get_pfxmatch(&t, logcfg_class);
- mask = get_match(t, logcfg_item);
- if (mask)
- return mask << offset;
- else
- msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
+#ifdef FREE_CFG_T
+void
+free_all_config_trees(void)
+{
+ struct config_tree *ptree;
+ struct config_tree *pnext;
- return 0;
+ ptree = cfg_tree_history;
+
+ while (ptree != NULL) {
+ pnext = ptree->link;
+ free_config_tree(ptree);
+ ptree = pnext;
+ }
}
-/*
- * getconfig - get command line options and read the configuration file
- */
-void
-getconfig(
- int argc,
- char *argv[]
+static void
+free_config_tree(
+ struct config_tree *ptree
)
{
- register int i;
- int c;
- int errflg;
- int status;
- int istart;
- int peerversion;
- int minpoll;
- int maxpoll;
- int ttl;
- long stratum;
- unsigned long ul;
- keyid_t peerkey;
- u_char *peerkeystr;
- u_long fudgeflag;
- u_int peerflags;
- int hmode;
- struct sockaddr_storage peeraddr;
- struct sockaddr_storage maskaddr;
- FILE *fp[MAXINCLUDELEVEL+1];
- FILE *includefile;
- int includelevel = 0;
- char line[MAXLINE];
- char *(tokens[MAXTOKENS]);
- int ntokens = 0;
- int tok = CONFIG_UNKNOWN;
- struct interface *localaddr;
- struct refclockstat clock_stat;
- FILEGEN *filegen;
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+ if (ptree->source.value.s != NULL)
+ free(ptree->source.value.s);
+
+ free_config_other_modes(ptree);
+ free_config_auth(ptree);
+ free_config_tos(ptree);
+ free_config_monitor(ptree);
+ free_config_access(ptree);
+ free_config_tinker(ptree);
+ free_config_system_opts(ptree);
+ free_config_logconfig(ptree);
+ free_config_phone(ptree);
+ free_config_qos(ptree);
+ free_config_setvar(ptree);
+ free_config_ttl(ptree);
+ free_config_trap(ptree);
+ free_config_fudge(ptree);
+ free_config_vars(ptree);
+ free_config_peers(ptree);
+ free_config_unpeers(ptree);
+ free_config_nic_rules(ptree);
+#ifdef SIM
+ free_config_sim(ptree);
+#endif
/*
- * Initialize, initialize
+ * Most of these DESTROY_QUEUE()s are handled already by the
+ * free_config_*() routines above but it's safe to use twice.
+ * Please feel free to remove ones you verified are handled
+ * in a free_config_*() routine.
*/
- errflg = 0;
-
-#ifndef SYS_WINNT
- config_file = CONFIG_FILE;
-#else
- temp = CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
- exit(1);
- }
- config_file = config_file_storage;
+ DESTROY_QUEUE(ptree->peers);
+ DESTROY_QUEUE(ptree->unpeers);
+ DESTROY_QUEUE(ptree->orphan_cmds);
+ DESTROY_QUEUE(ptree->manycastserver);
+ DESTROY_QUEUE(ptree->multicastclient);
+ DESTROY_QUEUE(ptree->stats_list);
+ DESTROY_QUEUE(ptree->filegen_opts);
+ DESTROY_QUEUE(ptree->discard_opts);
+ DESTROY_QUEUE(ptree->restrict_opts);
+ DESTROY_QUEUE(ptree->enable_opts);
+ DESTROY_QUEUE(ptree->disable_opts);
+ DESTROY_QUEUE(ptree->tinker);
+ DESTROY_QUEUE(ptree->fudge);
+ DESTROY_QUEUE(ptree->logconfig);
+ DESTROY_QUEUE(ptree->phone);
+ DESTROY_QUEUE(ptree->qos);
+ DESTROY_QUEUE(ptree->setvar);
+ DESTROY_QUEUE(ptree->ttl);
+ DESTROY_QUEUE(ptree->trap);
+ DESTROY_QUEUE(ptree->vars);
+
+ free_auth_node(ptree);
+
+ free(ptree);
+
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+}
+#endif /* FREE_CFG_T */
- temp = ALT_CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
- exit(1);
+
+#ifdef SAVECONFIG
+/* Dump all trees */
+int
+dump_all_config_trees(
+ FILE *df,
+ int comment
+ )
+{
+ struct config_tree *cfg_ptr = cfg_tree_history;
+ int return_value = 0;
+
+ for (cfg_ptr = cfg_tree_history;
+ cfg_ptr != NULL;
+ cfg_ptr = cfg_ptr->link)
+ return_value |= dump_config_tree(cfg_ptr, df, comment);
+
+ return return_value;
+}
+
+
+/* The config dumper */
+int
+dump_config_tree(
+ struct config_tree *ptree,
+ FILE *df,
+ int comment
+ )
+{
+ struct peer_node *peer = NULL;
+ struct unpeer_node *unpeers = NULL;
+ struct attr_val *atrv = NULL;
+ struct address_node *addr = NULL;
+ struct address_node *peer_addr;
+ struct address_node *fudge_addr;
+ struct filegen_node *fgen_node = NULL;
+ struct restrict_node *rest_node = NULL;
+ struct addr_opts_node *addr_opts = NULL;
+ struct setvar_node *setv_node = NULL;
+ nic_rule_node *rule_node;
+
+ char **pstr = NULL;
+ char *s1;
+ char *s2;
+ int *intp = NULL;
+ void *fudge_ptr;
+ void *list_ptr = NULL;
+ void *options = NULL;
+ void *opt_ptr = NULL;
+ int *flags = NULL;
+ void *opts = NULL;
+ char timestamp[80];
+ int enable;
+
+ DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
+
+ if (comment) {
+ if (!strftime(timestamp, sizeof(timestamp),
+ "%Y-%m-%d %H:%M:%S",
+ localtime(&ptree->timestamp)))
+ timestamp[0] = '\0';
+
+ fprintf(df, "# %s %s %s\n",
+ timestamp,
+ (CONF_SOURCE_NTPQ == ptree->source.attr)
+ ? "ntpq remote config from"
+ : "startup configuration file",
+ ptree->source.value.s);
}
- alt_config_file = alt_config_file_storage;
-#endif /* SYS_WINNT */
- res_fp = NULL;
- ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+ /* For options I didn't find documentation I'll just output its name and the cor. value */
+ list_ptr = queue_head(ptree->vars);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
- /*
- * install a non default variable with this daemon version
- */
- (void) sprintf(line, "daemon_version=\"%s\"", Version);
- set_sys_var(line, strlen(line)+1, RO);
+ atrv = (struct attr_val *) list_ptr;
- /*
- * Say how we're setting the time of day
- */
- (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
- set_sys_var(line, strlen(line)+1, RO);
+ switch (atrv->attr) {
- /*
- * Initialize the loop.
- */
- loop_config(LOOP_DRIFTINIT, 0.);
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown vars token %s\n",
+ token_name(atrv->attr));
+ break;
- getCmdOpts(argc, argv);
+ /* doubles */
+ case T_Broadcastdelay:
+ case T_Tick:
+ case T_WanderThreshold:
+ fprintf(df, "%s %g\n",
+ keyword(atrv->attr),
+ atrv->value.d);
+ break;
+
+ /* ints */
+ case T_Calldelay:
+#ifdef OPENSSL
+ case T_Automax:
+#endif
+ fprintf(df, "%s %d\n",
+ keyword(atrv->attr),
+ atrv->value.i);
+ break;
- if (
- (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
-#ifdef HAVE_NETINFO
- /* If there is no config_file, try NetInfo. */
- && check_netinfo && !(config_netinfo = get_netinfo_config())
-#endif /* HAVE_NETINFO */
- ) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
-#ifdef SYS_WINNT
- /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
+ /* strings */
+ case T_Driftfile:
+ case T_Leapfile:
+ case T_Logfile:
+ case T_Pidfile:
+ case T_Saveconfigdir:
+ fprintf(df, "%s \"%s\"\n",
+ keyword(atrv->attr),
+ atrv->value.s);
+ break;
+ }
+ }
- if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
+ list_ptr = queue_head(ptree->logconfig);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "logconfig");
- /*
- * Broadcast clients can sometimes run without
- * a configuration file.
- */
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
- return;
+ atrv = list_ptr;
+ fprintf(df, " %c%s", atrv->attr, atrv->value.s);
}
-#else /* not SYS_WINNT */
- return;
-#endif /* not SYS_WINNT */
+ fprintf(df, "\n");
}
- for (;;) {
- if (tok == CONFIG_END)
- break;
- if (fp[includelevel])
- tok = gettokens(fp[includelevel], line, tokens, &ntokens);
-#ifdef HAVE_NETINFO
- else
- tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
-#endif /* HAVE_NETINFO */
+ if (ptree->stats_dir)
+ fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
- if (tok == CONFIG_UNKNOWN) {
- if (includelevel > 0) {
- fclose(fp[includelevel--]);
- continue;
- } else {
- break;
- }
- }
-
- switch(tok) {
- case CONFIG_PEER:
- case CONFIG_SERVER:
- case CONFIG_MANYCASTCLIENT:
- case CONFIG_BROADCAST:
- if (tok == CONFIG_PEER)
- hmode = MODE_ACTIVE;
- else if (tok == CONFIG_SERVER)
- hmode = MODE_CLIENT;
- else if (tok == CONFIG_MANYCASTCLIENT)
- hmode = MODE_CLIENT;
- else
- hmode = MODE_BROADCAST;
+ list_ptr = queue_head(ptree->stats_list);
+ if (list_ptr != NULL) {
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "No address for %s, line ignored",
- tokens[0]);
+ fprintf(df, "statistics");
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ intp = list_ptr;
+
+ fprintf(df, " %s", keyword(*intp));
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->filegen_opts);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ fgen_node = list_ptr;
+ opt_ptr = queue_head(fgen_node->options);
+
+ if (opt_ptr != NULL)
+ fprintf(df, "filegen %s",
+ keyword(fgen_node->filegen_token));
+
+ for(; opt_ptr != NULL;
+ opt_ptr = next_node(opt_ptr)) {
+
+ atrv = opt_ptr;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown filegen option token %s\n"
+ "filegen %s",
+ token_name(atrv->attr),
+ keyword(fgen_node->filegen_token));
break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+ case T_File:
+ fprintf(df, " file %s",
+ atrv->value.s);
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+
+ case T_Type:
+ fprintf(df, " type %s",
+ keyword(atrv->value.i));
+ break;
+
+ case T_Flag:
+ fprintf(df, " %s",
+ keyword(atrv->value.i));
break;
}
- status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
- if (status == -1)
- break; /* Found IPv6 address */
- if(status != 1) {
- errflg = -1;
- } else {
- errflg = 0;
+ }
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- ISBADADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
- break;
- }
- /*
- * Shouldn't be able to specify multicast
- * address for server/peer!
- * and unicast address for manycastclient!
- */
- if (peeraddr.ss_family == AF_INET) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->auth.crypto_cmd_list);
+ if (list_ptr != NULL) {
+ fprintf(df, "crypto");
+
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %s", keyword(atrv->attr),
+ atrv->value.s);
+ }
+ fprintf(df, "\n");
+ }
+
+ if (ptree->auth.revoke != 0)
+ fprintf(df, "revoke %d\n", ptree->auth.revoke);
+
+ if (NULL != ptree->auth.keysdir)
+ fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
+
+ if (NULL != ptree->auth.keys)
+ fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
+
+ atrv = queue_head(ptree->auth.trusted_key_list);
+ if (atrv != NULL) {
+ fprintf(df, "trustedkey");
+ do {
+ if ('i' == atrv->attr)
+ fprintf(df, " %d", atrv->value.i);
+ else if ('-' == atrv->attr)
+ fprintf(df, " (%u ... %u)",
+ atrv->value.u >> 16,
+ atrv->value.u & 0xffff);
+ else
+ fprintf(df, "\n# dump error:\n"
+ "# unknown trustedkey attr %d\n"
+ "trustedkey", atrv->attr);
+ } while (NULL != (atrv = next_node(atrv)));
+ fprintf(df, "\n");
+ }
+
+ if (ptree->auth.control_key)
+ fprintf(df, "controlkey %d\n", ptree->auth.control_key);
+
+ if (ptree->auth.request_key)
+ fprintf(df, "requestkey %d\n", ptree->auth.request_key);
+
+ /* dump enable list, then disable list */
+ for (enable = 1; enable >= 0; enable--) {
+
+ list_ptr = (enable)
+ ? queue_head(ptree->enable_opts)
+ : queue_head(ptree->disable_opts);
+
+ if (list_ptr != NULL) {
+ fprintf(df, (enable)
+ ? "enable"
+ : "disable");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = (struct attr_val *) list_ptr;
+
+ fprintf(df, " %s",
+ keyword(atrv->value.i));
+ }
+ fprintf(df, "\n");
+ }
+ }
+
+ list_ptr = queue_head(ptree->orphan_cmds);
+ if (list_ptr != NULL)
+ fprintf(df, "tos");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown tos token %s\n"
+ "tos", token_name(atrv->attr));
+ break;
+
+ /* ints */
+ case T_Ceiling:
+ case T_Floor:
+ case T_Cohort:
+ case T_Orphan:
+ case T_Minclock:
+ case T_Maxclock:
+ case T_Minsane:
+ case T_Beacon:
+ fprintf(df, " %s %d", keyword(atrv->attr),
+ (int)atrv->value.d);
+ break;
+
+ /* doubles */
+ case T_Mindist:
+ case T_Maxdist:
+ fprintf(df, " %s %g", keyword(atrv->attr),
+ atrv->value.d);
+ break;
+ }
+ }
+ if (queue_head(ptree->orphan_cmds) != NULL)
+ fprintf(df, "\n");
+
+ list_ptr = queue_head(ptree->tinker);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "tinker");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %g", keyword(atrv->attr),
+ atrv->value.d);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ if (ptree->broadcastclient)
+ fprintf(df, "broadcastclient\n");
+
+ list_ptr = queue_head(ptree->peers);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ peer = list_ptr;
+ addr = peer->addr;
+ fprintf(df, "%s", keyword(peer->host_mode));
+
+ switch (addr->type) {
+
+ default:
+ fprintf(df, "# dump error:\n"
+ "# unknown peer family %d for:\n"
+ "peer", addr->type);
+ break;
+
+ case AF_UNSPEC:
+ break;
+
+ case AF_INET:
+ fprintf(df, " -4");
+ break;
+
+ case AF_INET6:
+ fprintf(df, " -6");
+ break;
+ }
+ fprintf(df, " %s", addr->address);
+
+ if (peer->minpoll != 0)
+ fprintf(df, " minpoll %d", peer->minpoll);
+
+ if (peer->maxpoll != 0)
+ fprintf(df, " maxpoll %d", peer->maxpoll);
+
+ if (peer->ttl != 0) {
+ if (strlen(addr->address) > 8
+ && !memcmp(addr->address, "127.127.", 8))
+ fprintf(df, " mode %d", peer->ttl);
+ else
+ fprintf(df, " ttl %d", peer->ttl);
+ }
+
+ if (peer->peerversion != NTP_VERSION)
+ fprintf(df, " version %d", peer->peerversion);
+
+ if (peer->peerkey != 0)
+ fprintf(df, " key %d", peer->peerkey);
+
+ if (peer->bias != 0.)
+ fprintf(df, " bias %g", peer->bias);
+
+ for (atrv = queue_head(peer->peerflags);
+ atrv != NULL;
+ atrv = next_node(atrv)) {
+
+ NTP_INSIST(T_Flag == atrv->attr);
+ NTP_INSIST(T_Integer == atrv->type);
+
+ fprintf(df, " %s", keyword(atrv->value.i));
+ }
+
+ fprintf(df, "\n");
+
+ fudge_ptr = queue_head(ptree->fudge);
+ for(; fudge_ptr != NULL;
+ fudge_ptr = next_node(fudge_ptr)) {
+
+
+ addr_opts = (struct addr_opts_node *) fudge_ptr;
+ peer_addr = peer->addr;
+ fudge_addr = addr_opts->addr;
+
+ s1 = peer_addr->address;
+ s2 = fudge_addr->address;
+
+ if (!strcmp(s1, s2)) {
+
+ fprintf(df, "fudge %s", addr_opts->addr->address);
+
+ opts = queue_head(addr_opts->options);
+
+ for(; opts != NULL; opts = next_node(opts)) {
+ atrv = (struct attr_val *) opts;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown fudge option %s\n"
+ "fudge %s",
+ token_name(atrv->attr),
+ addr_opts->addr->address);
break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
+
+ /* doubles */
+ case T_Time1:
+ case T_Time2:
+ fprintf(df, " %s %g",
+ keyword(atrv->attr),
+ atrv->value.d);
+ break;
+
+ /* ints */
+ case T_Stratum:
+ case T_Flag1:
+ case T_Flag2:
+ case T_Flag3:
+ case T_Flag4:
+ fprintf(df, " %s %d",
+ keyword(atrv->attr),
+ atrv->value.i);
+ break;
+
+ /* strings */
+ case T_Refid:
+ fprintf(df, " %s %s",
+ keyword(atrv->attr),
+ atrv->value.s);
break;
}
}
- else if(peeraddr.ss_family == AF_INET6) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- }
+ fprintf(df, "\n");
}
- if (peeraddr.ss_family == AF_INET6 &&
- isc_net_probeipv6() != ISC_R_SUCCESS)
- break;
+ }
+ }
- peerversion = NTP_VERSION;
- minpoll = NTP_MINDPOLL;
- maxpoll = NTP_MAXDPOLL;
- peerkey = 0;
- peerkeystr = (u_char *)"*";
- peerflags = 0;
- ttl = 0;
- istart++;
- for (i = istart; i < ntokens; i++)
- switch (matchkey(tokens[i], mod_keywords, 1)) {
- case CONF_MOD_VERSION:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "peer/server version requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if ((u_char)peerversion > NTP_VERSION
- || (u_char)peerversion < NTP_OLDVERSION) {
- msyslog(LOG_ERR,
- "inappropriate version number %s, line ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_MOD_KEY:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "key: argument required");
- errflg = 1;
- break;
- }
- peerkey = (int)atol(tokens[++i]);
- peerflags |= FLAG_AUTHENABLE;
- break;
-
- case CONF_MOD_MINPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "minpoll: argument required");
- errflg = 1;
- break;
- }
- minpoll = atoi(tokens[++i]);
- if (minpoll < NTP_MINPOLL) {
- msyslog(LOG_INFO,
- "minpoll: provided value (%d) is below minimum (%d)",
- minpoll, NTP_MINPOLL);
- minpoll = NTP_MINPOLL;
- }
- break;
-
- case CONF_MOD_MAXPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "maxpoll: argument required"
- );
- errflg = 1;
- break;
- }
- maxpoll = atoi(tokens[++i]);
- if (maxpoll > NTP_MAXPOLL) {
- msyslog(LOG_INFO,
- "maxpoll: provided value (%d) is above maximum (%d)",
- maxpoll, NTP_MAXPOLL);
- maxpoll = NTP_MAXPOLL;
- }
- break;
-
- case CONF_MOD_PREFER:
- peerflags |= FLAG_PREFER;
- break;
-
- case CONF_MOD_PREEMPT:
- peerflags |= FLAG_PREEMPT;
- break;
-
- case CONF_MOD_NOSELECT:
- peerflags |= FLAG_NOSELECT;
- break;
-
- case CONF_MOD_TRUE:
- peerflags |= FLAG_TRUE;
-
- case CONF_MOD_BURST:
- peerflags |= FLAG_BURST;
- break;
-
- case CONF_MOD_IBURST:
- peerflags |= FLAG_IBURST;
- break;
-
- case CONF_MOD_DYNAMIC:
- msyslog(LOG_WARNING,
- "Warning: the \"dynamic\" keyword has been obsoleted"
- " and will be removed in the next release\n");
- break;
+ list_ptr = queue_head(ptree->manycastserver);
+ if (list_ptr != NULL) {
+ addr = list_ptr;
+ fprintf(df, "manycastserver %s", addr->address);
+ for (addr = next_node(addr);
+ addr != NULL;
+ addr = next_node(addr))
+ fprintf(df, " %s", addr->address);
+ fprintf(df, "\n");
+ }
-#ifdef OPENSSL
- case CONF_MOD_SKEY:
- peerflags |= FLAG_SKEY |
- FLAG_AUTHENABLE;
- break;
-#endif /* OPENSSL */
+ list_ptr = queue_head(ptree->multicastclient);
+ if (list_ptr != NULL) {
+ addr = list_ptr;
+ fprintf(df, "multicastclient %s", addr->address);
+ for (addr = next_node(addr);
+ addr != NULL;
+ addr = next_node(addr))
+ fprintf(df, " %s", addr->address);
+ fprintf(df, "\n");
+ }
- case CONF_MOD_TTL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "ttl: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- if (ttl >= MAX_TTL) {
- msyslog(LOG_ERR,
- "ttl: invalid argument");
- errflg = 1;
- }
- break;
+ list_ptr = queue_head(ptree->unpeers);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ unpeers = (struct unpeer_node *) list_ptr;
+
+ fprintf(df, "unpeer %s\n", (unpeers->addr)->address);
+ }
- case CONF_MOD_MODE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mode: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- break;
-
- case CONFIG_UNKNOWN:
- errflg = 1;
- break;
- }
- if (minpoll > maxpoll) {
- msyslog(LOG_ERR,
- "config error: minpoll > maxpoll");
- errflg = 1;
+ list_ptr = queue_head(ptree->discard_opts);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "discard");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %d", keyword(atrv->attr),
+ atrv->value.i);
+ }
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->restrict_opts);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ rest_node = list_ptr;
+ if (NULL == rest_node->addr)
+ s1 = "default";
+ else
+ s1 = rest_node->addr->address;
+
+ fprintf(df, "restrict %s", s1);
+
+ if (rest_node->mask != NULL)
+ fprintf(df, " mask %s",
+ rest_node->mask->address);
+
+ flags = queue_head(rest_node->flags);
+ for (; flags != NULL; flags = next_node(flags))
+ fprintf(df, " %s", keyword(*flags));
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->nic_rules);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ rule_node = list_ptr;
+ fprintf(df, "interface %s %s\n",
+ keyword(rule_node->action),
+ (rule_node->match_class)
+ ? keyword(rule_node->match_class)
+ : rule_node->if_name);
+ }
+
+ list_ptr = queue_head(ptree->phone);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "phone");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ pstr = list_ptr;
+ fprintf(df, " %s", *pstr);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->qos);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "qos");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s", atrv->value.s);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->setvar);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ setv_node = list_ptr;
+ s1 = quote_if_needed(setv_node->var);
+ s2 = quote_if_needed(setv_node->val);
+ fprintf(df, "setvar %s = %s", s1, s2);
+ free(s1);
+ free(s2);
+
+ if (setv_node->isdefault)
+ fprintf(df, " default");
+
+ fprintf(df, "\n");
+ }
+
+
+ list_ptr = queue_head(ptree->ttl);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "ttl");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ intp = list_ptr;
+ fprintf(df, " %d", *intp);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->trap);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ addr_opts = list_ptr;
+ addr = addr_opts->addr;
+
+ fprintf(df, "trap %s", addr->address);
+
+ options = queue_head(addr_opts->options);
+
+ for(; options != NULL;
+ options = next_node(options)) {
+
+ atrv = options;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown trap token %d\n"
+ "trap %s", atrv->attr,
+ addr->address);
+ break;
+
+ case T_Port:
+ fprintf(df, " port %d", atrv->value.i);
+ break;
+
+ case T_Interface:
+ addr = (struct address_node *) atrv->value.p;
+ fprintf(df, " interface %s", addr->address);
+ break;
}
- if (errflg == 0) {
- if (peer_config(&peeraddr,
- ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
- peerversion, minpoll, maxpoll, peerflags,
- ttl, peerkey, peerkeystr) == 0) {
- msyslog(LOG_ERR,
- "configuration of %s failed",
- stoa(&peeraddr));
- }
- } else if (errflg == -1) {
- save_resolve(tokens[1], hmode, peerversion,
- minpoll, maxpoll, peerflags, ttl,
- peerkey, peerkeystr);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ return 0;
+}
+#endif /* SAVECONFIG */
+
+
+/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
+ * -----------------------------------------------
+ */
+
+queue *
+enqueue_in_new_queue(
+ void *my_node
+ )
+{
+ queue *my_queue = create_queue();
+
+ enqueue(my_queue, my_node);
+ return my_queue;
+}
+
+struct attr_val *
+create_attr_dval(
+ int attr,
+ double value
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.d = value;
+ my_val->type = T_Double;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_ival(
+ int attr,
+ int value
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.i = value;
+ my_val->type = T_Integer;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_shorts(
+ int attr,
+ ntp_u_int16_t val1,
+ ntp_u_int16_t val2
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.u = (val1 << 16) | val2;
+ my_val->type = T_Integer;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_sval(
+ int attr,
+ char *s
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ if (NULL == s) /* free() hates NULL */
+ s = estrdup("");
+ my_val->value.s = s;
+ my_val->type = T_String;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_pval(
+ int attr,
+ void *p
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.p = p;
+ my_val->type = T_Void;
+ return my_val;
+}
+
+int *
+create_ival(
+ int val
+ )
+{
+ int *p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+double *
+create_dval(
+ double val
+ )
+{
+ double *p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+void **
+create_pval(
+ void *val
+ )
+{
+ void **p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+struct address_node *
+create_address_node(
+ char *addr,
+ int type
+ )
+{
+ struct address_node *my_node;
+
+ NTP_REQUIRE(NULL != addr);
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->address = addr;
+ my_node->type = type;
+
+ return my_node;
+}
+
+
+void
+destroy_address_node(
+ struct address_node *my_node
+ )
+{
+ NTP_REQUIRE(NULL != my_node);
+ NTP_REQUIRE(NULL != my_node->address);
+
+ free(my_node->address);
+ free_node(my_node);
+}
+
+
+struct peer_node *
+create_peer_node(
+ int hmode,
+ struct address_node *addr,
+ queue *options
+ )
+{
+ struct peer_node *my_node;
+ struct attr_val *option;
+ int freenode;
+ int errflag = 0;
+
+ my_node = get_node(sizeof(*my_node));
+
+ /* Initialize node values to default */
+ my_node->minpoll = 0;
+ my_node->maxpoll = 0;
+ my_node->ttl = 0;
+ my_node->peerversion = NTP_VERSION;
+ my_node->peerkey = 0;
+ my_node->bias = 0;
+ my_node->peerflags = create_queue();
+
+ /* Now set the node to the read values */
+ my_node->host_mode = hmode;
+ my_node->addr = addr;
+
+ /*
+ * the options list mixes items that will be saved in the
+ * peer_node as explicit members, such as minpoll, and
+ * those that are moved from the options queue intact
+ * to the peer_node's peerflags queue. The options
+ * queue is consumed and destroyed here.
+ */
+
+ while (options && NULL != (option = dequeue(options))) {
+
+ freenode = 1;
+ /* Check the kind of option being set */
+ switch (option->attr) {
+
+ case T_Flag:
+ enqueue(my_node->peerflags, option);
+ freenode = 0;
+ break;
+
+ case T_Minpoll:
+ if (option->value.i < NTP_MINPOLL) {
+ msyslog(LOG_INFO,
+ "minpoll: provided value (%d) is below minimum (%d)",
+ option->value.i, NTP_MINPOLL);
+ my_node->minpoll = NTP_MINPOLL;
}
+ else
+ my_node->minpoll = option->value.i;
break;
- case CONFIG_DRIFTFILE:
- if (ntokens >= 2)
- stats_config(STATS_FREQ_FILE, tokens[1]);
+ case T_Maxpoll:
+ if (option->value.i > NTP_MAXPOLL) {
+ msyslog(LOG_INFO,
+ "maxpoll: provided value (%d) is above maximum (%d)",
+ option->value.i, NTP_MAXPOLL);
+ my_node->maxpoll = NTP_MAXPOLL;
+ }
else
- stats_config(STATS_FREQ_FILE, (char *)0);
- stats_write_period = stats_write_tolerance = 0;
- if (ntokens >= 3)
- stats_write_period = 60 * atol(tokens[2]);
- if (stats_write_period <= 0)
- stats_write_period = 3600;
- if (ntokens >= 4) {
- double ftemp;
- sscanf(tokens[3], "%lf", &ftemp);
- stats_write_tolerance = ftemp / 100;
+ my_node->maxpoll = option->value.i;
+ break;
+
+ case T_Ttl:
+ if (my_node->ttl >= MAX_TTL) {
+ msyslog(LOG_ERR, "ttl: invalid argument");
+ errflag = 1;
}
+ else
+ my_node->ttl = option->value.i;
+ break;
+
+ case T_Mode:
+ my_node->ttl = option->value.i;
+ break;
+
+ case T_Key:
+ my_node->peerkey = option->value.i;
+ break;
+
+ case T_Version:
+ my_node->peerversion = option->value.i;
break;
+
+ case T_Bias:
+ my_node->bias = option->value.d;
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "Unknown peer/server option token %s",
+ token_name(option->attr));
+ errflag = 1;
+ }
+ if (freenode)
+ free_node(option);
+ }
+ DESTROY_QUEUE(options);
+
+ /* Check if errors were reported. If yes, ignore the node */
+ if (errflag) {
+ free_node(my_node);
+ my_node = NULL;
+ }
+ return my_node;
+}
+
+
+struct unpeer_node *
+create_unpeer_node(
+ struct address_node *addr
+ )
+{
+ struct unpeer_node * my_node;
+ char * pch;
+
+ my_node = get_node(sizeof(*my_node));
+
+ /*
+ * From the parser's perspective an association ID fits into
+ * its generic T_String definition of a name/address "address".
+ * We treat all valid 16-bit numbers as association IDs.
+ */
+ pch = addr->address;
+ while (*pch && isdigit(*pch))
+ pch++;
+
+ if (!*pch
+ && 1 == sscanf(addr->address, "%u", &my_node->assocID)
+ && my_node->assocID <= USHRT_MAX) {
+
+ destroy_address_node(addr);
+ my_node->addr = NULL;
+ } else {
+ my_node->assocID = 0;
+ my_node->addr = addr;
+ }
+
+ return my_node;
+}
+
+struct filegen_node *
+create_filegen_node(
+ int filegen_token,
+ queue * options
+ )
+{
+ struct filegen_node *my_node;
- case CONFIG_PIDFILE:
- if (ntokens >= 2)
- stats_config(STATS_PID_FILE, tokens[1]);
- else
- stats_config(STATS_PID_FILE, (char *)0);
+ my_node = get_node(sizeof *my_node);
+ my_node->filegen_token = filegen_token;
+ my_node->options = options;
+
+ return my_node;
+}
+
+
+struct restrict_node *
+create_restrict_node(
+ struct address_node *addr,
+ struct address_node *mask,
+ queue *flags,
+ int line_no
+ )
+{
+ struct restrict_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->addr = addr;
+ my_node->mask = mask;
+ my_node->flags = flags;
+ my_node->line_no = line_no;
+
+ return my_node;
+}
+
+void
+destroy_restrict_node(
+ struct restrict_node *my_node
+ )
+{
+ /* With great care, free all the memory occupied by
+ * the restrict node
+ */
+ if (my_node->addr)
+ destroy_address_node(my_node->addr);
+ if (my_node->mask)
+ destroy_address_node(my_node->mask);
+ DESTROY_QUEUE(my_node->flags);
+ free_node(my_node);
+}
+
+
+struct setvar_node *
+create_setvar_node(
+ char * var,
+ char * val,
+ int isdefault
+ )
+{
+ char * pch;
+ struct setvar_node *my_node;
+
+ /* do not allow = in the variable name */
+ if (NULL != (pch = strchr(var, '=')))
+ *pch = '\0';
+
+ /* Now store the string into a setvar_node */
+ my_node = get_node(sizeof *my_node);
+ my_node->var = var;
+ my_node->val = val;
+ my_node->isdefault = isdefault;
+
+ return my_node;
+}
+
+
+nic_rule_node *
+create_nic_rule_node(
+ int match_class,
+ char *if_name, /* interface name or numeric address */
+ int action
+ )
+{
+ nic_rule_node *my_node;
+
+ NTP_REQUIRE(match_class != 0 || if_name != NULL);
+
+ my_node = get_node(sizeof(*my_node));
+ my_node->match_class = match_class;
+ my_node->if_name = if_name;
+ my_node->action = action;
+
+ return my_node;
+}
+
+
+struct addr_opts_node *
+create_addr_opts_node(
+ struct address_node *addr,
+ queue *options
+ )
+{
+ struct addr_opts_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+ my_node->addr = addr;
+ my_node->options = options;
+ return my_node;
+}
+
+script_info *
+create_sim_script_info(
+ double duration,
+ queue *script_queue
+ )
+{
+#ifdef SIM
+ return NULL;
+#else
+ script_info *my_info;
+ struct attr_val *my_attr_val;
+
+ my_info = get_node(sizeof *my_info);
+
+ /* Initialize Script Info with default values*/
+ my_info->duration = duration;
+ my_info->freq_offset = 0;
+ my_info->wander = 0;
+ my_info->jitter = 0;
+ my_info->prop_delay = NET_DLY;
+ my_info->proc_delay = PROC_DLY;
+
+ /* Traverse the script_queue and fill out non-default values */
+ my_attr_val = queue_head(script_queue);
+ while (my_attr_val != NULL) {
+ /* Set the desired value */
+ switch (my_attr_val->attr) {
+
+ case T_Freq_Offset:
+ my_info->freq_offset = my_attr_val->value.d;
break;
- case CONFIG_END:
- for ( i = 0; i <= includelevel; i++ ) {
- fclose(fp[i]);
- }
+ case T_Wander:
+ my_info->wander = my_attr_val->value.d;
break;
-
- case CONFIG_INCLUDEFILE:
- if (ntokens < 2) {
- msyslog(LOG_ERR, "includefile needs one argument");
- break;
- }
- if (includelevel >= MAXINCLUDELEVEL) {
- fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
- msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
- break;
- }
- includefile = fopen(FindConfig(tokens[1]), "r");
- if (includefile == NULL) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
- break;
- }
- fp[++includelevel] = includefile;
+
+ case T_Jitter:
+ my_info->jitter = my_attr_val->value.d;
break;
- case CONFIG_LOGFILE:
- if (ntokens >= 2) {
- FILE *new_file;
+ case T_Prop_Delay:
+ my_info->prop_delay = my_attr_val->value.d;
+ break;
- new_file = fopen(tokens[1], "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
+ case T_Proc_Delay:
+ my_info->proc_delay = my_attr_val->value.d;
+ break;
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- tokens[1]);
- }
- else
- msyslog(LOG_ERR, "logfile needs one argument");
- break;
-
- case CONFIG_LOGCONFIG:
- for (i = 1; i < ntokens; i++)
- {
- int add = 1;
- int equals = 0;
- char * s = &tokens[i][0];
-
- switch (*s) {
- case '+':
- case '-':
- case '=':
- add = *s == '+';
- equals = *s == '=';
- s++;
- break;
+ default:
+ msyslog(LOG_ERR,
+ "Unknown script token %d",
+ my_attr_val->attr);
+ }
+ }
+ return (my_info);
+#endif
+}
- default:
- break;
- }
- if (equals) {
- ntp_syslogmask = get_logmask(s);
- } else {
- if (add) {
- ntp_syslogmask |= get_logmask(s);
- } else {
- ntp_syslogmask &= ~get_logmask(s);
- }
- }
-#ifdef DEBUG
- if (debug)
- printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
+
+#if !defined(SIM)
+
+#define ADDR_LENGTH 16 + 1
+
+static sockaddr_u *
+get_next_address(
+ struct address_node *addr
+ )
+{
+ const char addr_prefix[] = "192.168.0.";
+ static int curr_addr_no = 1;
+ char addr_string[ADDR_LENGTH];
+ sockaddr_u *final_addr;
+ struct addrinfo *ptr;
+ int retval;
+
+ final_addr = emalloc(sizeof *final_addr);
+
+ if (addr->type == T_String) {
+ snprintf(addr_string, ADDR_LENGTH, "%s%d", addr_prefix, curr_addr_no++);
+ printf("Selecting ip address %s for hostname %s\n", addr_string, addr->address);
+ retval = getaddrinfo(addr_string, "ntp", NULL, &ptr);
+ } else
+ retval = getaddrinfo(addr->address, "ntp", NULL, &ptr);
+
+ if (!retval) {
+ memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
+ fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", stoa(final_addr));
+ }
+ else {
+ fprintf(stderr, "ERROR!! Could not get a new address\n");
+ exit(1);
+ }
+ freeaddrinfo(ptr);
+ return final_addr;
+}
+#endif /* !SIM */
+
+
+server_info *
+create_sim_server(
+ struct address_node *addr,
+ double server_offset,
+ queue *script
+ )
+{
+#ifdef SIM
+ return NULL;
+#else
+ server_info *my_info;
+
+ my_info = get_node(sizeof *my_info);
+
+ my_info->server_time = server_offset;
+ my_info->addr = get_next_address(addr);
+ my_info->script = script;
+ my_info->curr_script = dequeue(my_info->script);
+ return my_info;
+#endif /* SIM */
+}
+
+struct sim_node *
+create_sim_node(
+ queue *init_opts,
+ queue *servers
+ )
+{
+ struct sim_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->init_opts = init_opts;
+ my_node->servers = servers;
+ return my_node;
+}
+
+
+
+
+/* FUNCTIONS FOR PERFORMING THE CONFIGURATION
+ * ------------------------------------------
+ */
+
+static void
+config_other_modes(
+ struct config_tree *ptree
+ )
+{
+ sockaddr_u addr_sock;
+ struct address_node *addr_node;
+
+ if (ptree->broadcastclient)
+ proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 0., NULL);
+
+ /* Configure the many-cast servers */
+ addr_node = queue_head(ptree->manycastserver);
+ if (addr_node != NULL) {
+ do {
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
+ proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+
+ addr_node = next_node(addr_node);
+ } while (addr_node != NULL);
+ sys_manycastserver = 1;
+ }
+
+ /* Configure the multicast clients */
+ addr_node = queue_head(ptree->multicastclient);
+ if (addr_node != NULL) {
+ do {
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
+ proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+
+ addr_node = next_node(addr_node);
+ } while (addr_node != NULL);
+ proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_other_modes(
+ struct config_tree *ptree
+ )
+{
+ struct address_node *addr_node;
+
+ while (NULL != (addr_node = dequeue(ptree->manycastserver)))
+ destroy_address_node(addr_node);
+
+ while (NULL != (addr_node = dequeue(ptree->multicastclient)))
+ destroy_address_node(addr_node);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_auth(
+ struct config_tree *ptree
+ )
+{
+ ntp_u_int16_t ufirst;
+ ntp_u_int16_t ulast;
+ ntp_u_int16_t u;
+ struct attr_val *my_val;
+#ifdef OPENSSL
+#ifndef NO_INTRES
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int digest_len;
+ EVP_MD_CTX ctx;
#endif
- }
+ int item;
+#endif
+
+ /* Crypto Command */
+#ifdef OPENSSL
+ item = -1; /* quiet warning */
+ my_val = queue_head(ptree->auth.crypto_cmd_list);
+ while (my_val != NULL) {
+ switch (my_val->attr) {
+
+ default:
+ NTP_INSIST(0);
break;
- case CONFIG_BROADCASTCLIENT:
- if (ntokens == 1) {
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
- } else {
- proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
- }
+ case T_Host:
+ item = CRYPTO_CONF_PRIV;
break;
- case CONFIG_MULTICASTCLIENT:
- case CONFIG_MANYCASTSERVER:
- if (ntokens > 1) {
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart],
- addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
- /*
- * Abuse maskaddr to store the prefered ip
- * version.
- */
- memset((char *)&maskaddr, 0, sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
-
- for (i = istart; i < ntokens; i++) {
- memset((char *)&peeraddr, 0,
- sizeof(peeraddr));
- peeraddr.ss_family = maskaddr.ss_family;
- if (getnetnum(tokens[i], &peeraddr, 1,
- t_UNK) == 1)
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., &peeraddr);
- }
- } else
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., NULL);
- if (tok == CONFIG_MULTICASTCLIENT)
- proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
- else if (tok == CONFIG_MANYCASTSERVER)
- sys_manycastserver = 1;
+ case T_Ident:
+ item = CRYPTO_CONF_IDENT;
break;
- case CONFIG_KEYS:
- if (ntokens >= 2) {
- getauthkeys(tokens[1]);
- }
+ case T_Pw:
+ item = CRYPTO_CONF_PW;
break;
- case CONFIG_KEYSDIR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "Keys directory name required");
- break;
- }
- keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
- strcpy(keysdir, tokens[1]);
+ case T_Randfile:
+ item = CRYPTO_CONF_RAND;
break;
- case CONFIG_TINKER:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
+ case T_Sign:
+ item = CRYPTO_CONF_SIGN;
+ break;
- temp = matchkey(tokens[i++], tinker_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tinker: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
+ case T_Digest:
+ item = CRYPTO_CONF_NID;
+ break;
+ }
+ crypto_config(item, my_val->value.s);
+ my_val = next_node(my_val);
+ }
+#endif /* OPENSSL */
- case CONF_CLOCK_MAX:
- loop_config(LOOP_MAX, ftemp);
- break;
+ /* Keysdir Command */
+ if (ptree->auth.keysdir) {
+ if (keysdir != default_keysdir)
+ free(keysdir);
+ keysdir = estrdup(ptree->auth.keysdir);
+ }
- case CONF_CLOCK_PANIC:
- loop_config(LOOP_PANIC, ftemp);
- break;
- case CONF_CLOCK_PHI:
- loop_config(LOOP_PHI, ftemp);
- break;
+ /* ntp_signd_socket Command */
+ if (ptree->auth.ntp_signd_socket) {
+ if (ntp_signd_socket != default_ntp_signd_socket)
+ free(ntp_signd_socket);
+ ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
+ }
- case CONF_CLOCK_MINSTEP:
- loop_config(LOOP_MINSTEP, ftemp);
- break;
+#ifdef OPENSSL
+ if (ptree->auth.cryptosw && !cryptosw) {
+ crypto_setup();
+ cryptosw = 1;
+ }
+#endif /* OPENSSL */
- case CONF_CLOCK_ALLAN:
- loop_config(LOOP_ALLAN, ftemp);
- break;
+ /* Keys Command */
+ if (ptree->auth.keys)
+ getauthkeys(ptree->auth.keys);
- case CONF_CLOCK_HUFFPUFF:
- loop_config(LOOP_HUFFPUFF, ftemp);
- break;
+ /* Control Key Command */
+ if (ptree->auth.control_key)
+ ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
- case CONF_CLOCK_FREQ:
- loop_config(LOOP_FREQ, ftemp);
- break;
- }
- }
- break;
+ /* Requested Key Command */
+ if (ptree->auth.request_key) {
+ DPRINTF(4, ("set info_auth_keyid to %08lx\n",
+ (u_long) ptree->auth.request_key));
+ info_auth_keyid = (keyid_t)ptree->auth.request_key;
+ }
- case CONFIG_TOS:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
+ /* Trusted Key Command */
+ my_val = queue_head(ptree->auth.trusted_key_list);
+ for (; my_val != NULL; my_val = next_node(my_val)) {
+ if ('i' == my_val->attr)
+ authtrust(my_val->value.i, 1);
+ else if ('-' == my_val->attr) {
+ ufirst = my_val->value.u >> 16;
+ ulast = my_val->value.u & 0xffff;
+ for (u = ufirst; u <= ulast; u++)
+ authtrust(u, 1);
+ }
+ }
- temp = matchkey(tokens[i++], tos_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tos: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
+#ifdef OPENSSL
+ /* crypto revoke command */
+ if (ptree->auth.revoke)
+ sys_revoke = ptree->auth.revoke;
+#endif /* OPENSSL */
- case CONF_TOS_MINCLOCK:
- proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
- break;
+#ifndef NO_INTRES
+ /* find a keyid */
+ if (info_auth_keyid == 0)
+ req_keyid = 65535;
+ else
+ req_keyid = info_auth_keyid;
- case CONF_TOS_MAXCLOCK:
- proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
- break;
+ /* if doesn't exist, make up one at random */
+ if (authhavekey(req_keyid)) {
+ req_keytype = cache_type;
+#ifndef OPENSSL
+ req_hashlen = 16;
+#else /* OPENSSL follows */
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(req_keytype));
+ EVP_DigestFinal(&ctx, digest, &digest_len);
+ req_hashlen = digest_len;
+#endif
+ } else {
+ int rankey;
- case CONF_TOS_MINSANE:
- proto_config(PROTO_MINSANE, 0, ftemp, NULL);
- break;
+ rankey = ntp_random();
+ req_keytype = NID_md5;
+ req_hashlen = 16;
+ MD5auth_setkey(req_keyid, req_keytype,
+ (u_char *)&rankey, sizeof(rankey));
+ authtrust(req_keyid, 1);
+ }
- case CONF_TOS_FLOOR:
- proto_config(PROTO_FLOOR, 0, ftemp, NULL);
- break;
+ /* save keyid so we will accept config requests with it */
+ info_auth_keyid = req_keyid;
+#endif /* !NO_INTRES */
- case CONF_TOS_CEILING:
- proto_config(PROTO_CEILING, 0, ftemp, NULL);
- break;
+}
- case CONF_TOS_COHORT:
- proto_config(PROTO_COHORT, 0, ftemp, NULL);
- break;
- case CONF_TOS_MINDISP:
- proto_config(PROTO_MINDISP, 0, ftemp, NULL);
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_auth(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_val;
- case CONF_TOS_MAXDIST:
- proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
- break;
+ while (NULL !=
+ (my_val = dequeue(ptree->auth.crypto_cmd_list))) {
- case CONF_TOS_MAXHOP:
- proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
- break;
+ free(my_val->value.s);
+ free_node(my_val);
+ }
+ DESTROY_QUEUE(ptree->auth.crypto_cmd_list);
- case CONF_TOS_ORPHAN:
- proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
- break;
+ DESTROY_QUEUE(ptree->auth.trusted_key_list);
+}
+#endif /* FREE_CFG_T */
- case CONF_TOS_BEACON:
- proto_config(PROTO_BEACON, 0, ftemp, NULL);
- break;
- }
- }
+
+static void
+config_tos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tos;
+ int item;
+
+ item = -1; /* quiet warning */
+ tos = queue_head(ptree->orphan_cmds);
+ while (tos != NULL) {
+ switch(tos->attr) {
+
+ default:
+ NTP_INSIST(0);
break;
- case CONFIG_TTL:
- for (i = 1; i < ntokens && i < MAX_TTL; i++) {
- sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
- sys_ttlmax = i - 1;
- }
+ case T_Ceiling:
+ item = PROTO_CEILING;
break;
- case CONFIG_DISCARD:
- for (i = 1; i < ntokens; i++) {
- int temp;
+ case T_Floor:
+ item = PROTO_FLOOR;
+ break;
- temp = matchkey(tokens[i++],
- discard_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "discard: missing argument");
- errflg++;
- break;
- }
- switch(temp) {
- case CONF_DISCARD_AVERAGE:
- res_avg_interval = atoi(tokens[i]);
- break;
+ case T_Cohort:
+ item = PROTO_COHORT;
+ break;
+
+ case T_Orphan:
+ item = PROTO_ORPHAN;
+ break;
- case CONF_DISCARD_MINIMUM:
- res_min_interval = atoi(tokens[i]);
+ case T_Mindist:
+ item = PROTO_MINDISP;
+ break;
+
+ case T_Maxdist:
+ item = PROTO_MAXDIST;
+ break;
+
+ case T_Minclock:
+ item = PROTO_MINCLOCK;
+ break;
+
+ case T_Maxclock:
+ item = PROTO_MAXCLOCK;
+ break;
+
+ case T_Minsane:
+ item = PROTO_MINSANE;
+ break;
+
+ case T_Beacon:
+ item = PROTO_BEACON;
+ break;
+ }
+ proto_config(item, 0, tos->value.d, NULL);
+ tos = next_node(tos);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_tos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tos;
+
+ while (!empty(ptree->orphan_cmds)) {
+ tos = dequeue(ptree->orphan_cmds);
+ free_node(tos);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_monitor(
+ struct config_tree *ptree
+ )
+{
+ int *pfilegen_token;
+ const char *filegen_string;
+ const char *filegen_file;
+ FILEGEN *filegen;
+ struct filegen_node *my_node;
+ struct attr_val *my_opts;
+ int filegen_type;
+ int filegen_flag;
+
+ /* Set the statistics directory */
+ if (ptree->stats_dir)
+ stats_config(STATS_STATSDIR, ptree->stats_dir);
+
+ /* NOTE:
+ * Calling filegen_get is brain dead. Doing a string
+ * comparison to find the relavant filegen structure is
+ * expensive.
+ *
+ * Through the parser, we already know which filegen is
+ * being specified. Hence, we should either store a
+ * pointer to the specified structure in the syntax tree
+ * or an index into a filegen array.
+ *
+ * Need to change the filegen code to reflect the above.
+ */
+
+ /* Turn on the specified statistics */
+ pfilegen_token = queue_head(ptree->stats_list);
+ while (pfilegen_token != NULL) {
+ filegen_string = keyword(*pfilegen_token);
+ filegen = filegen_get(filegen_string);
+
+ DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
+ filegen_string, filegen->prefix,
+ filegen->basename));
+ filegen->flag |= FGEN_FLAG_ENABLED;
+ pfilegen_token = next_node(pfilegen_token);
+ }
+
+ /* Configure the statistics with the options */
+ my_node = queue_head(ptree->filegen_opts);
+ while (my_node != NULL) {
+ filegen_file = keyword(my_node->filegen_token);
+ filegen = filegen_get(filegen_file);
+
+ /* Initialize the filegen variables to their pre-configurtion states */
+ filegen_flag = filegen->flag;
+ filegen_type = filegen->type;
+
+ /* "filegen ... enabled" is the default (when filegen is used) */
+ filegen_flag |= FGEN_FLAG_ENABLED;
+
+ my_opts = queue_head(my_node->options);
+ while (my_opts != NULL) {
+
+ switch (my_opts->attr) {
+
+ case T_File:
+ filegen_file = my_opts->value.p;
break;
- case CONF_DISCARD_MONITOR:
- mon_age = atoi(tokens[i]);
+ case T_Type:
+ switch (my_opts->value.i) {
+
+ default:
+ NTP_INSIST(0);
+ break;
+
+ case T_None:
+ filegen_type = FILEGEN_NONE;
+ break;
+
+ case T_Pid:
+ filegen_type = FILEGEN_PID;
+ break;
+
+ case T_Day:
+ filegen_type = FILEGEN_DAY;
+ break;
+
+ case T_Week:
+ filegen_type = FILEGEN_WEEK;
+ break;
+
+ case T_Month:
+ filegen_type = FILEGEN_MONTH;
+ break;
+
+ case T_Year:
+ filegen_type = FILEGEN_YEAR;
+ break;
+
+ case T_Age:
+ filegen_type = FILEGEN_AGE;
+ break;
+ }
break;
- default:
- msyslog(LOG_ERR,
- "discard: unknown keyword");
+ case T_Flag:
+ switch (my_opts->value.i) {
+
+ case T_Link:
+ filegen_flag |= FGEN_FLAG_LINK;
+ break;
+
+ case T_Nolink:
+ filegen_flag &= ~FGEN_FLAG_LINK;
+ break;
+
+ case T_Enable:
+ filegen_flag |= FGEN_FLAG_ENABLED;
+ break;
+
+ case T_Disable:
+ filegen_flag &= ~FGEN_FLAG_ENABLED;
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "Unknown filegen flag token %d",
+ my_opts->value.i);
+ exit(1);
+ }
break;
- }
+ default:
+ msyslog(LOG_ERR,
+ "Unknown filegen option token %d",
+ my_opts->attr);
+ exit(1);
}
+ my_opts = next_node(my_opts);
+ }
+ filegen_config(filegen, filegen_file, filegen_type,
+ filegen_flag);
+ my_node = next_node(my_node);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_monitor(
+ struct config_tree *ptree
+ )
+{
+ char **filegen_string;
+ struct filegen_node *my_node;
+ struct attr_val *my_opts;
+
+ if (ptree->stats_dir) {
+ free(ptree->stats_dir);
+ ptree->stats_dir = NULL;
+ }
+
+ while (NULL != (filegen_string = dequeue(ptree->stats_list)))
+ free_node(filegen_string);
+
+ while (NULL != (my_node = dequeue(ptree->filegen_opts))) {
+
+ while (NULL != (my_opts = dequeue(my_node->options)))
+ free_node(my_opts);
+
+ free_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_access(
+ struct config_tree *ptree
+ )
+{
+ static int warned_signd;
+ struct attr_val * my_opt;
+ struct restrict_node * my_node;
+ int * curr_flag;
+ sockaddr_u addr_sock;
+ sockaddr_u addr_mask;
+ u_short flags;
+ u_short mflags;
+ int restrict_default;
+ const char * signd_warning =
+#ifdef HAVE_NTP_SIGND
+ "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
+#else
+ "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
+#endif
+
+ /* Configure the discard options */
+ my_opt = queue_head(ptree->discard_opts);
+ while (my_opt != NULL) {
+
+ switch(my_opt->attr) {
+
+ case T_Average:
+ ntp_minpoll = my_opt->value.i;
break;
-#ifdef OPENSSL
- case CONFIG_REVOKE:
- if (ntokens >= 2)
- sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
+ case T_Minimum:
+ ntp_minpkt = my_opt->value.i;
break;
- case CONFIG_AUTOMAX:
- if (ntokens >= 2)
- sys_automax = 1 << max(atoi(tokens[1]), 10);
+ case T_Monitor:
+ mon_age = my_opt->value.i;
break;
- case CONFIG_CRYPTO:
- if (ntokens == 1) {
- crypto_config(CRYPTO_CONF_NONE, NULL);
- break;
- }
- for (i = 1; i < ntokens; i++) {
- int temp;
+ default:
+ msyslog(LOG_ERR,
+ "Unknown discard option token %d",
+ my_opt->attr);
+ exit(1);
+ }
+ my_opt = next_node(my_opt);
+ }
+
+ /* Configure the restrict options */
+ for (my_node = queue_head(ptree->restrict_opts);
+ my_node != NULL;
+ my_node = next_node(my_node)) {
+
+ ZERO_SOCK(&addr_sock);
+
+ if (NULL == my_node->addr) {
+ /*
+ * The user specified a default rule without a
+ * -4 / -6 qualifier, add to both lists
+ */
+ restrict_default = 1;
+ ZERO_SOCK(&addr_mask);
+ } else {
+ restrict_default = 0;
+ /* Resolve the specified address */
+ AF(&addr_sock) = (u_short)my_node->addr->type;
+
+ if (getnetnum(my_node->addr->address,
+ &addr_sock, 1, t_UNK) != 1) {
- temp = matchkey(tokens[i++],
- crypto_keywords, 1);
- if (i > ntokens - 1) {
msyslog(LOG_ERR,
- "crypto: missing argument");
- errflg++;
+ "restrict: error in address '%s' on line %d. Ignoring...",
+ my_node->addr->address, my_node->line_no);
+ continue;
+ }
+
+ SET_HOSTMASK(&addr_mask, AF(&addr_sock));
+
+ /* Resolve the mask */
+ if (my_node->mask) {
+ ZERO_SOCK(&addr_mask);
+ AF(&addr_mask) = (u_short)my_node->mask->type;
+ if (getnetnum(my_node->mask->address, &addr_mask, 1, t_MSK) != 1) {
+
+ msyslog(LOG_ERR,
+ "restrict: error in mask '%s' on line %d. Ignoring...",
+ my_node->mask->address, my_node->line_no);
+ continue;
+ }
+ }
+ }
+
+ /* Parse the flags */
+ flags = 0;
+ mflags = 0;
+
+ curr_flag = queue_head(my_node->flags);
+ while (curr_flag != NULL) {
+ switch (*curr_flag) {
+
+ default:
+ NTP_INSIST(0);
break;
- }
- switch(temp) {
- case CONF_CRYPTO_CERT:
- crypto_config(CRYPTO_CONF_CERT,
- tokens[i]);
+ case T_Ntpport:
+ mflags |= RESM_NTPONLY;
break;
- case CONF_CRYPTO_RSA:
- crypto_config(CRYPTO_CONF_PRIV,
- tokens[i]);
+ case T_Flake:
+ flags |= RES_TIMEOUT;
break;
- case CONF_CRYPTO_IDENT:
- crypto_config(CRYPTO_CONF_IDENT,
- tokens[i]);
+ case T_Ignore:
+ flags |= RES_IGNORE;
break;
- case CONF_CRYPTO_IFFPAR:
- crypto_config(CRYPTO_CONF_IFFPAR,
- tokens[i]);
+ case T_Kod:
+ flags |= RES_KOD;
break;
- case CONF_CRYPTO_GQPAR:
- crypto_config(CRYPTO_CONF_GQPAR,
- tokens[i]);
+ case T_Mssntp:
+ flags |= RES_MSSNTP;
break;
- case CONF_CRYPTO_MVPAR:
- crypto_config(CRYPTO_CONF_MVPAR,
- tokens[i]);
+ case T_Limited:
+ flags |= RES_LIMITED;
break;
- case CONF_CRYPTO_LEAP:
- crypto_config(CRYPTO_CONF_LEAP,
- tokens[i]);
+ case T_Lowpriotrap:
+ flags |= RES_LPTRAP;
break;
- case CONF_CRYPTO_PW:
- crypto_config(CRYPTO_CONF_PW,
- tokens[i]);
+ case T_Nomodify:
+ flags |= RES_NOMODIFY;
break;
- case CONF_CRYPTO_RAND:
- crypto_config(CRYPTO_CONF_RAND,
- tokens[i]);
+ case T_Nopeer:
+ flags |= RES_NOPEER;
break;
- case CONF_CRYPTO_SIGN:
- crypto_config(CRYPTO_CONF_SIGN,
- tokens[i]);
+ case T_Noquery:
+ flags |= RES_NOQUERY;
break;
- default:
- msyslog(LOG_ERR,
- "crypto: unknown keyword");
+ case T_Noserve:
+ flags |= RES_DONTSERVE;
break;
- }
- }
- break;
-#endif /* OPENSSL */
- case CONFIG_RESTRICT:
- if (ntokens < 2) {
- msyslog(LOG_ERR, "restrict requires an address");
+ case T_Notrap:
+ flags |= RES_NOTRAP;
break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+
+ case T_Notrust:
+ flags |= RES_DONTTRUST;
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+
+ case T_Version:
+ flags |= RES_VERSION;
break;
}
+ curr_flag = next_node(curr_flag);
+ }
+
+ /* Set the flags */
+ if (restrict_default) {
+ AF(&addr_sock) = AF_INET;
+ hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
+ mflags, flags);
+
+ AF(&addr_sock) = AF_INET6;
+ }
+
+ hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
+ mflags, flags);
+
+ if ((RES_MSSNTP & flags) && !warned_signd) {
+ warned_signd = 1;
+ fprintf(stderr, "%s\n", signd_warning);
+ msyslog(LOG_WARNING, signd_warning);
+ }
+ }
+}
+
+#ifdef FREE_CFG_T
+static void
+free_config_access(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val * my_opt;
+ struct restrict_node * my_node;
+ int * curr_flag;
+
+ while (NULL != (my_opt = dequeue(ptree->discard_opts)))
+ free_node(my_opt);
+
+ while (NULL != (my_node = dequeue(ptree->restrict_opts))) {
+ while (NULL != (curr_flag = dequeue(my_node->flags)))
+ free_node(curr_flag);
+
+ destroy_restrict_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_tinker(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tinker;
+ int item;
+
+ item = -1; /* quiet warning */
+ tinker = queue_head(ptree->tinker);
+ while (tinker != NULL) {
+ switch (tinker->attr) {
+
+ default:
+ NTP_INSIST(0);
+ break;
+
+ case T_Allan:
+ item = LOOP_ALLAN;
+ break;
+
+ case T_Dispersion:
+ item = LOOP_PHI;
+ break;
+
+ case T_Freq:
+ item = LOOP_FREQ;
+ break;
+
+ case T_Huffpuff:
+ item = LOOP_HUFFPUFF;
+ break;
+
+ case T_Panic:
+ item = LOOP_PANIC;
+ break;
+
+ case T_Step:
+ item = LOOP_MAX;
+ break;
+
+ case T_Stepout:
+ item = LOOP_MINSTEP;
+ break;
+ }
+ loop_config(item, tinker->value.d);
+ tinker = next_node(tinker);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_tinker(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tinker;
+
+ while (NULL != (tinker = dequeue(ptree->tinker)))
+ free_node(tinker);
+}
+#endif /* FREE_CFG_T */
+
+
+/*
+ * config_nic_rules - apply interface listen/ignore/drop items
+ */
+void
+config_nic_rules(
+ struct config_tree *ptree
+ )
+{
+ nic_rule_node * curr_node;
+ sockaddr_u addr;
+ nic_rule_match match_type;
+ nic_rule_action action;
+ char * if_name;
+ char * pchSlash;
+ int prefixlen;
+ int addrbits;
+
+ curr_node = queue_head(ptree->nic_rules);
+
+ if (curr_node != NULL
+ && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
+ msyslog(LOG_ERR,
+ "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
+ (input_from_file) ? ", exiting" : "");
+ if (input_from_file)
+ exit(1);
+ else
+ return;
+ }
+
+ for (;
+ curr_node != NULL;
+ curr_node = next_node(curr_node)) {
+
+ prefixlen = -1;
+ if_name = curr_node->if_name;
+ if (if_name != NULL)
+ if_name = estrdup(if_name);
+
+ switch (curr_node->match_class) {
+
+ default:
/*
- * Assume default means an IPv4 address, except
- * if forced by a -4 or -6.
+ * this assignment quiets a gcc "may be used
+ * uninitialized" warning and is here for no
+ * other reason.
*/
- if (STREQ(tokens[istart], "default")) {
- if (peeraddr.ss_family == 0)
- peeraddr.ss_family = AF_INET;
- } else if (getnetnum(tokens[istart], &peeraddr, 1,
- t_UNK) != 1)
- break;
+ match_type = MATCH_ALL;
+ NTP_INSIST(0);
+ break;
+ case 0:
/*
- * Use peerversion as flags, peerkey as mflags. Ick.
+ * 0 is out of range for valid token T_...
+ * and in a nic_rules_node indicates the
+ * interface descriptor is either a name or
+ * address, stored in if_name in either case.
*/
- peerversion = 0;
- peerkey = 0;
- errflg = 0;
- SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
- istart++;
- for (i = istart; i < ntokens; i++) {
- switch (matchkey(tokens[i], res_keywords, 1)) {
- case CONF_RES_MASK:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mask keyword needs argument");
- errflg++;
- break;
- }
- i++;
- if (getnetnum(tokens[i], &maskaddr, 1,
- t_MSK) != 1)
- errflg++;
- break;
+ NTP_INSIST(if_name != NULL);
+ pchSlash = strchr(if_name, '/');
+ if (pchSlash != NULL)
+ *pchSlash = '\0';
+ if (is_ip_address(if_name, &addr)) {
+ match_type = MATCH_IFADDR;
+ if (pchSlash != NULL) {
+ sscanf(pchSlash + 1, "%d",
+ &prefixlen);
+ addrbits = 8 *
+ SIZEOF_INADDR(AF(&addr));
+ prefixlen = max(-1, prefixlen);
+ prefixlen = min(prefixlen,
+ addrbits);
+ }
+ } else {
+ match_type = MATCH_IFNAME;
+ if (pchSlash != NULL)
+ *pchSlash = '/';
+ }
+ break;
- case CONF_RES_IGNORE:
- peerversion |= RES_IGNORE;
- break;
+ case T_All:
+ match_type = MATCH_ALL;
+ break;
- case CONF_RES_NOSERVE:
- peerversion |= RES_DONTSERVE;
- break;
+ case T_Ipv4:
+ match_type = MATCH_IPV4;
+ break;
- case CONF_RES_NOTRUST:
- peerversion |= RES_DONTTRUST;
- break;
+ case T_Ipv6:
+ match_type = MATCH_IPV6;
+ break;
- case CONF_RES_NOQUERY:
- peerversion |= RES_NOQUERY;
- break;
+ case T_Wildcard:
+ match_type = MATCH_WILDCARD;
+ break;
+ }
- case CONF_RES_NOMODIFY:
- peerversion |= RES_NOMODIFY;
- break;
+ switch (curr_node->action) {
- case CONF_RES_NOPEER:
- peerversion |= RES_NOPEER;
- break;
+ default:
+ /*
+ * this assignment quiets a gcc "may be used
+ * uninitialized" warning and is here for no
+ * other reason.
+ */
+ action = ACTION_LISTEN;
+ NTP_INSIST(0);
+ break;
- case CONF_RES_NOTRAP:
- peerversion |= RES_NOTRAP;
- break;
+ case T_Listen:
+ action = ACTION_LISTEN;
+ break;
- case CONF_RES_LPTRAP:
- peerversion |= RES_LPTRAP;
- break;
+ case T_Ignore:
+ action = ACTION_IGNORE;
+ break;
- case CONF_RES_NTPPORT:
- peerkey |= RESM_NTPONLY;
- break;
+ case T_Drop:
+ action = ACTION_DROP;
+ break;
+ }
- case CONF_RES_VERSION:
- peerversion |= RES_VERSION;
- break;
+ add_nic_rule(match_type, if_name, prefixlen,
+ action);
+ timer_interfacetimeout(current_time + 2);
+ if (if_name != NULL)
+ free(if_name);
+ }
+}
- case CONF_RES_DEMOBILIZE:
- peerversion |= RES_DEMOBILIZE;
- break;
- case CONF_RES_LIMITED:
- peerversion |= RES_LIMITED;
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_nic_rules(
+ struct config_tree *ptree
+ )
+{
+ nic_rule_node *curr_node;
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
- }
- if (SOCKNUL(&peeraddr))
- ANYSOCK(&maskaddr);
- if (!errflg)
- hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
- (int)peerkey, peerversion);
+ while (NULL != (curr_node = dequeue(ptree->nic_rules))) {
+ if (curr_node->if_name != NULL)
+ free(curr_node->if_name);
+ free_node(curr_node);
+ }
+ DESTROY_QUEUE(ptree->nic_rules);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+apply_enable_disable(
+ queue * q,
+ int enable
+ )
+{
+ struct attr_val *curr_flag;
+ int option;
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
+ bc_entry *pentry;
+#endif
+
+ for (curr_flag = queue_head(q);
+ curr_flag != NULL;
+ curr_flag = next_node(curr_flag)) {
+
+ option = curr_flag->value.i;
+ switch (option) {
+
+ default:
+ msyslog(LOG_ERR,
+ "can not apply enable/disable token %d, unknown",
+ option);
break;
- case CONFIG_BDELAY:
- if (ntokens >= 2) {
- double tmp;
+ case T_Auth:
+ proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
+ break;
- if (sscanf(tokens[1], "%lf", &tmp) != 1) {
- msyslog(LOG_ERR,
- "broadcastdelay value %s undecodable",
- tokens[1]);
- } else {
- proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
- }
- }
+ case T_Bclient:
+ proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
break;
- case CONFIG_CDELAY:
- if (ntokens >= 2) {
- u_long ui;
+ case T_Calibrate:
+ proto_config(PROTO_CAL, enable, 0., NULL);
+ break;
- if (sscanf(tokens[1], "%ld", &ui) != 1)
- msyslog(LOG_ERR,
- "illegal value - line ignored");
- else
- proto_config(PROTO_CALLDELAY, ui, 0, NULL);
- }
+ case T_Kernel:
+ proto_config(PROTO_KERNEL, enable, 0., NULL);
break;
- case CONFIG_TRUSTEDKEY:
- for (i = 1; i < ntokens; i++) {
- keyid_t tkey;
+ case T_Monitor:
+ proto_config(PROTO_MONITOR, enable, 0., NULL);
+ break;
- tkey = atol(tokens[i]);
- if (tkey == 0) {
- msyslog(LOG_ERR,
- "trusted key %s unlikely",
- tokens[i]);
- } else {
- authtrust(tkey, 1);
- }
+ case T_Ntp:
+ proto_config(PROTO_NTP, enable, 0., NULL);
+ break;
+
+ case T_Stats:
+ proto_config(PROTO_FILEGEN, enable, 0., NULL);
+ break;
+
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
+ case T_Bc_bugXXXX:
+ pentry = bc_list;
+ while (pentry->token) {
+ if (pentry->token == option)
+ break;
+ pentry++;
}
+ if (!pentry->token) {
+ msyslog(LOG_ERR,
+ "compat token %d not in bc_list[]",
+ option);
+ continue;
+ }
+ pentry->enabled = enable;
break;
+#endif
+ }
+ }
+}
- case CONFIG_REQUESTKEY:
- if (ntokens >= 2) {
- if (!atouint(tokens[1], &ul)) {
- msyslog(LOG_ERR,
- "%s is undecodable as request key",
- tokens[1]);
- } else if (ul == 0) {
- msyslog(LOG_ERR,
- "%s makes a poor request keyid",
- tokens[1]);
- } else {
-#ifdef DEBUG
- if (debug > 3)
- printf(
- "set info_auth_key to %08lx\n", ul);
+
+static void
+config_system_opts(
+ struct config_tree *ptree
+ )
+{
+ apply_enable_disable(ptree->enable_opts, 1);
+ apply_enable_disable(ptree->disable_opts, 0);
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_system_opts(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *flag;
+
+ while (NULL != (flag = dequeue(ptree->enable_opts)))
+ free_node(flag);
+
+ while (NULL != (flag = dequeue(ptree->disable_opts)))
+ free_node(flag);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_logconfig(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_logconfig;
+
+ my_logconfig = queue_head(ptree->logconfig);
+ while (my_logconfig != NULL) {
+
+ switch (my_logconfig->attr) {
+ case '+':
+ ntp_syslogmask |= get_logmask(my_logconfig->value.s);
+ break;
+ case '-':
+ ntp_syslogmask &= ~get_logmask(my_logconfig->value.s);
+ break;
+ case '=':
+ ntp_syslogmask = get_logmask(my_logconfig->value.s);
+ break;
+ }
+ my_logconfig = next_node(my_logconfig);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_logconfig(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_logconfig;
+
+ while (NULL != (my_logconfig = dequeue(ptree->logconfig))) {
+ free(my_logconfig->value.s);
+ free_node(my_logconfig);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_phone(
+ struct config_tree *ptree
+ )
+{
+ int i = 0;
+ char **s;
+
+ s = queue_head(ptree->phone);
+ while (s != NULL) {
+ if (i < COUNTOF(sys_phone) - 1) {
+ sys_phone[i++] = estrdup(*s);
+ sys_phone[i] = NULL;
+ } else {
+ msyslog(LOG_INFO,
+ "phone: Number of phone entries exceeds %lu. Ignoring phone %s...",
+ (u_long)(COUNTOF(sys_phone) - 1), *s);
+ }
+ s = next_node(s);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_phone(
+ struct config_tree *ptree
+ )
+{
+ char **s;
+
+ while (NULL != (s = dequeue(ptree->phone))) {
+ free(*s);
+ free_node(s);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_qos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_qosconfig;
+ char *s;
+#ifdef HAVE_IPTOS_SUPPORT
+ unsigned int qtos = 0;
#endif
- info_auth_keyid = (keyid_t)ul;
+
+ my_qosconfig = queue_head(ptree->qos);
+ while (my_qosconfig != NULL) {
+ s = my_qosconfig->value.s;
+#ifdef HAVE_IPTOS_SUPPORT
+ if (!strcmp(s, "lowdelay"))
+ qtos = CONF_QOS_LOWDELAY;
+ else if (!strcmp(s, "throughput"))
+ qtos = CONF_QOS_THROUGHPUT;
+ else if (!strcmp(s, "reliability"))
+ qtos = CONF_QOS_RELIABILITY;
+ else if (!strcmp(s, "mincost"))
+ qtos = CONF_QOS_MINCOST;
+#ifdef IPTOS_PREC_INTERNETCONTROL
+ else if (!strcmp(s, "routine") || !strcmp(s, "cs0"))
+ qtos = CONF_QOS_CS0;
+ else if (!strcmp(s, "priority") || !strcmp(s, "cs1"))
+ qtos = CONF_QOS_CS1;
+ else if (!strcmp(s, "immediate") || !strcmp(s, "cs2"))
+ qtos = CONF_QOS_CS2;
+ else if (!strcmp(s, "flash") || !strcmp(s, "cs3"))
+ qtos = CONF_QOS_CS3; /* overlapping prefix on keyword */
+ if (!strcmp(s, "flashoverride") || !strcmp(s, "cs4"))
+ qtos = CONF_QOS_CS4;
+ else if (!strcmp(s, "critical") || !strcmp(s, "cs5"))
+ qtos = CONF_QOS_CS5;
+ else if(!strcmp(s, "internetcontrol") || !strcmp(s, "cs6"))
+ qtos = CONF_QOS_CS6;
+ else if (!strcmp(s, "netcontrol") || !strcmp(s, "cs7"))
+ qtos = CONF_QOS_CS7;
+#endif /* IPTOS_PREC_INTERNETCONTROL */
+ if (qtos == 0)
+ msyslog(LOG_ERR, "parse error, qos %s not accepted\n", s);
+ else
+ qos = qtos;
+#endif /* HAVE IPTOS_SUPPORT */
+ /*
+ * value is set, but not being effective. Need code to
+ * change the current connections to notice. Might
+ * also consider logging a message about the action.
+ * XXX msyslog(LOG_INFO, "QoS %s requested by config\n", s);
+ */
+ my_qosconfig = next_node(my_qosconfig);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_qos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_qosconfig;
+
+ while (NULL != (my_qosconfig = dequeue(ptree->qos))) {
+ free(my_qosconfig->value.s);
+ free_node(my_qosconfig);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_setvar(
+ struct config_tree *ptree
+ )
+{
+ struct setvar_node *my_node;
+ size_t varlen, vallen, octets;
+ char * str;
+
+ str = NULL;
+ my_node = queue_head(ptree->setvar);
+ while (my_node != NULL) {
+ varlen = strlen(my_node->var);
+ vallen = strlen(my_node->val);
+ octets = varlen + vallen + 1 + 1;
+ str = erealloc(str, octets);
+ snprintf(str, octets, "%s=%s", my_node->var,
+ my_node->val);
+ set_sys_var(str, octets, (my_node->isdefault)
+ ? DEF
+ : 0);
+ my_node = next_node(my_node);
+ }
+ if (str != NULL)
+ free(str);
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_setvar(
+ struct config_tree *ptree
+ )
+{
+ struct setvar_node *my_node;
+
+ while (NULL != (my_node = dequeue(ptree->setvar))) {
+ free(my_node->var);
+ free(my_node->val);
+ free_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_ttl(
+ struct config_tree *ptree
+ )
+{
+ int i = 0;
+ int *curr_ttl;
+
+ curr_ttl = queue_head(ptree->ttl);
+ while (curr_ttl != NULL) {
+ if (i < COUNTOF(sys_ttl))
+ sys_ttl[i++] = (u_char)*curr_ttl;
+ else
+ msyslog(LOG_INFO,
+ "ttl: Number of TTL entries exceeds %lu. Ignoring TTL %d...",
+ (u_long)COUNTOF(sys_ttl), *curr_ttl);
+
+ curr_ttl = next_node(curr_ttl);
+ }
+ sys_ttlmax = i - 1;
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_ttl(
+ struct config_tree *ptree
+ )
+{
+ /* coming DESTROY_QUEUE(ptree->ttl) is enough */
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_trap(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_trap;
+ struct attr_val *curr_opt;
+ sockaddr_u addr_sock;
+ sockaddr_u peeraddr;
+ struct address_node *addr_node;
+ struct interface *localaddr;
+ u_short port_no;
+ int err_flag;
+
+ /* silence warning about addr_sock potentially uninitialized */
+ AF(&addr_sock) = AF_UNSPEC;
+
+ for (curr_trap = queue_head(ptree->trap);
+ curr_trap != NULL;
+ curr_trap = next_node(curr_trap)) {
+
+ err_flag = 0;
+ port_no = 0;
+ localaddr = NULL;
+
+ curr_opt = queue_head(curr_trap->options);
+ while (curr_opt != NULL) {
+ if (T_Port == curr_opt->attr) {
+ if (curr_opt->value.i < 1
+ || curr_opt->value.i > USHRT_MAX) {
+ msyslog(LOG_ERR,
+ "invalid port number "
+ "%d, trap ignored",
+ curr_opt->value.i);
+ err_flag = 1;
}
+ port_no = (u_short)curr_opt->value.i;
}
- break;
+ else if (T_Interface == curr_opt->attr) {
+ addr_node = curr_opt->value.p;
+
+ /* Resolve the interface address */
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address,
+ &addr_sock, 1, t_UNK) != 1) {
+ err_flag = 1;
+ break;
+ }
- case CONFIG_CONTROLKEY:
- if (ntokens >= 2) {
- keyid_t ckey;
+ localaddr = findinterface(&addr_sock);
- ckey = atol(tokens[1]);
- if (ckey == 0) {
+ if (NULL == localaddr) {
msyslog(LOG_ERR,
- "%s makes a poor control keyid",
- tokens[1]);
- } else {
- ctl_auth_keyid = ckey;
+ "can't find interface with address %s",
+ stoa(&addr_sock));
+ err_flag = 1;
}
}
- break;
+ curr_opt = next_node(curr_opt);
+ }
- case CONFIG_TRAP:
- if (ntokens < 2) {
+ /* Now process the trap for the specified interface
+ * and port number
+ */
+ if (!err_flag) {
+ ZERO_SOCK(&peeraddr);
+ if (1 != getnetnum(curr_trap->addr->address,
+ &peeraddr, 1, t_UNK))
+ continue;
+
+ /* port is at same location for v4 and v6 */
+ SET_PORT(&peeraddr, port_no ? port_no : TRAPPORT);
+
+ if (NULL == localaddr)
+ localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
+ else
+ AF(&peeraddr) = AF(&addr_sock);
+
+ if (!ctlsettrap(&peeraddr, localaddr, 0,
+ NTP_VERSION))
msyslog(LOG_ERR,
- "no address for trap command, line ignored");
- break;
+ "can't set trap for %s",
+ stoa(&peeraddr));
+ }
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_trap(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_trap;
+ struct attr_val *curr_opt;
+ struct address_node *addr_node;
+
+ while (NULL != (curr_trap = dequeue(ptree->trap))) {
+ while (curr_trap->options != NULL && NULL !=
+ (curr_opt = dequeue(curr_trap->options))) {
+
+ if (T_Interface == curr_opt->attr) {
+ addr_node = curr_opt->value.p;
+ destroy_address_node(addr_node);
}
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+ free_node(curr_opt);
+ }
+ DESTROY_QUEUE(curr_trap->options);
+ free_node(curr_trap);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_fudge(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_fudge;
+ struct attr_val *curr_opt;
+ sockaddr_u addr_sock;
+ struct address_node *addr_node;
+ struct refclockstat clock_stat;
+ int err_flag;
+
+ curr_fudge = queue_head(ptree->fudge);
+ while (curr_fudge != NULL) {
+ err_flag = 0;
+
+ /* Get the reference clock address and
+ * ensure that it is sane
+ */
+ addr_node = curr_fudge->addr;
+ ZERO_SOCK(&addr_sock);
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
+ != 1)
+ err_flag = 1;
+
+ if (!ISREFCLOCKADR(&addr_sock)) {
+ msyslog(LOG_ERR,
+ "inappropriate address %s for the fudge command, line ignored",
+ stoa(&addr_sock));
+ err_flag = 1;
+ }
+
+ /* Parse all the options to the fudge command */
+ memset(&clock_stat, 0, sizeof(clock_stat));
+ curr_opt = queue_head(curr_fudge->options);
+ while (curr_opt != NULL) {
+ switch (curr_opt->attr) {
+ case T_Time1:
+ clock_stat.haveflags |= CLK_HAVETIME1;
+ clock_stat.fudgetime1 = curr_opt->value.d;
+ break;
+ case T_Time2:
+ clock_stat.haveflags |= CLK_HAVETIME2;
+ clock_stat.fudgetime2 = curr_opt->value.d;
+ break;
+ case T_Stratum:
+ clock_stat.haveflags |= CLK_HAVEVAL1;
+ clock_stat.fudgeval1 = curr_opt->value.i;
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+ case T_Refid:
+ clock_stat.haveflags |= CLK_HAVEVAL2;
+ clock_stat.fudgeval2 = 0;
+ memcpy(&clock_stat.fudgeval2,
+ curr_opt->value.s,
+ min(strlen(curr_opt->value.s), 4));
break;
+ case T_Flag1:
+ clock_stat.haveflags |= CLK_HAVEFLAG1;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG1;
+ else
+ clock_stat.flags &= ~CLK_FLAG1;
+ break;
+ case T_Flag2:
+ clock_stat.haveflags |= CLK_HAVEFLAG2;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG2;
+ else
+ clock_stat.flags &= ~CLK_FLAG2;
+ break;
+ case T_Flag3:
+ clock_stat.haveflags |= CLK_HAVEFLAG3;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG3;
+ else
+ clock_stat.flags &= ~CLK_FLAG3;
+ break;
+ case T_Flag4:
+ clock_stat.haveflags |= CLK_HAVEFLAG4;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG4;
+ else
+ clock_stat.flags &= ~CLK_FLAG4;
+ break;
+ default:
+ msyslog(LOG_ERR,
+ "Unexpected fudge internal flag 0x%x for %s\n",
+ curr_opt->attr, stoa(&addr_sock));
+ exit(curr_opt->attr ? curr_opt->attr : 1);
}
- if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
- break;
+ curr_opt = next_node(curr_opt);
+ }
- /*
- * Use peerversion for port number. Barf.
- */
- errflg = 0;
- peerversion = 0;
- localaddr = 0;
- istart++;
- for (i = istart; i < ntokens-1; i++)
- switch (matchkey(tokens[i], trap_keywords, 1)) {
- case CONF_TRAP_PORT:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap port requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if (peerversion <= 0
- || peerversion > 32767) {
- msyslog(LOG_ERR,
- "invalid port number %s, trap ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_TRAP_INTERFACE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap interface requires an argument");
- errflg = 1;
- break;
- }
-
- memset((char *)&maskaddr, 0,
- sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
- if (getnetnum(tokens[++i],
- &maskaddr, 1, t_UNK) != 1) {
- errflg = 1;
- break;
- }
-
- localaddr = findinterface(&maskaddr);
- if (localaddr == NULL) {
- msyslog(LOG_ERR,
- "can't find interface with address %s",
- stoa(&maskaddr));
- errflg = 1;
- }
- break;
-
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
-
- if (!errflg) {
- if (peerversion != 0)
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
- else
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
- if (localaddr == NULL)
- localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
- if (!ctlsettrap(&peeraddr, localaddr, 0,
- NTP_VERSION))
- msyslog(LOG_ERR,
- "can't set trap for %s, no resources",
- stoa(&peeraddr));
+#ifdef REFCLOCK
+ if (!err_flag)
+ refclock_control(&addr_sock, &clock_stat,
+ (struct refclockstat *)0);
+#endif
+
+ curr_fudge = next_node(curr_fudge);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_fudge(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_fudge;
+ struct attr_val *curr_opt;
+
+ while (NULL != (curr_fudge = dequeue(ptree->fudge))) {
+ while (NULL != (curr_opt = dequeue(curr_fudge->options))) {
+
+ switch (curr_opt->attr) {
+ case CLK_HAVEVAL2:
+ free(curr_opt->value.s);
}
- break;
- case CONFIG_FUDGE:
- if (ntokens < 2) {
+ free_node(curr_opt);
+ }
+
+ DESTROY_QUEUE(curr_fudge->options);
+ free_node(curr_fudge);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_vars(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *curr_var;
+ FILE *new_file;
+ int len;
+
+ curr_var = queue_head(ptree->vars);
+ while (curr_var != NULL) {
+ /* Determine which variable to set and set it */
+ switch (curr_var->attr) {
+ case T_Broadcastdelay:
+ proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
+ break;
+ case T_Calldelay:
+ proto_config(PROTO_CALLDELAY, curr_var->value.i, 0, NULL);
+ break;
+ case T_Tick:
+ proto_config(PROTO_ADJ, 0, curr_var->value.d, NULL);
+ break;
+ case T_Driftfile:
+ if ('\0' == curr_var->value.s[0]) {
+ stats_drift_file = 0;
+ msyslog(LOG_INFO, "config: driftfile disabled\n");
+ } else
+ stats_config(STATS_FREQ_FILE, curr_var->value.s);
+ break;
+ case T_WanderThreshold:
+ wander_threshold = curr_var->value.d;
+ break;
+ case T_Leapfile:
+ stats_config(STATS_LEAP_FILE, curr_var->value.s);
+ break;
+ case T_Pidfile:
+ stats_config(STATS_PID_FILE, curr_var->value.s);
+ break;
+ case T_Logfile:
+ new_file = fopen(curr_var->value.s, "a");
+ if (new_file != NULL) {
+ NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
+ msyslog(LOG_NOTICE, "logging to file %s", curr_var->value.s);
+ if (syslog_file != NULL &&
+ fileno(syslog_file) != fileno(new_file))
+ (void)fclose(syslog_file);
+
+ syslog_file = new_file;
+ syslogit = 0;
+ }
+ else
msyslog(LOG_ERR,
- "no address for fudge command, line ignored");
+ "Cannot open log file %s",
+ curr_var->value.s);
+ break;
+
+ case T_Saveconfigdir:
+ if (saveconfigdir != NULL)
+ free(saveconfigdir);
+ len = strlen(curr_var->value.s);
+ if (0 == len)
+ saveconfigdir = NULL;
+ else if (DIR_SEP != curr_var->value.s[len - 1]
+#ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
+ && '/' != curr_var->value.s[len - 1]
+#endif
+ ) {
+ len++;
+ saveconfigdir = emalloc(len + 1);
+ snprintf(saveconfigdir, len + 1,
+ "%s%c",
+ curr_var->value.s,
+ DIR_SEP);
+ } else
+ saveconfigdir = estrdup(
+ curr_var->value.s);
+ break;
+
+ case T_Automax:
+#ifdef OPENSSL
+ sys_automax = curr_var->value.i;
+#endif
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "config_vars(): unexpected token %d",
+ curr_var->attr);
+ }
+ curr_var = next_node(curr_var);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_vars(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *curr_var;
+
+ while (NULL != (curr_var = dequeue(ptree->vars))) {
+ /* Determine which variable to set and set it */
+ switch (curr_var->attr) {
+ case T_Driftfile:
+ case T_Leapfile:
+ case T_Pidfile:
+ case T_Logfile:
+ free(curr_var->value.s);
+ }
+ free_node(curr_var);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+/* Define a function to check if a resolved address is sane.
+ * If yes, return 1, else return 0;
+ */
+static int
+is_sane_resolved_address(
+ sockaddr_u * peeraddr,
+ int hmode
+ )
+{
+ if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+ /*
+ * Shouldn't be able to specify multicast
+ * address for server/peer!
+ * and unicast address for manycastclient!
+ */
+ if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
+ && IS_MCAST(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+ if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+
+ if (IS_IPV6(peeraddr) && !ipv6_works)
+ return 0;
+
+ /* Ok, all tests succeeded, now we can return 1 */
+ return 1;
+}
+
+static int
+get_correct_host_mode(
+ int hmode
+ )
+{
+ switch (hmode) {
+ case T_Server:
+ case T_Pool:
+ case T_Manycastclient:
+ return MODE_CLIENT;
+ break;
+ case T_Peer:
+ return MODE_ACTIVE;
+ break;
+ case T_Broadcast:
+ return MODE_BROADCAST;
+ break;
+ default:
+ return -1;
+ }
+}
+
+static void
+config_peers(
+ struct config_tree *ptree
+ )
+{
+ struct addrinfo *res, *res_bak;
+ sockaddr_u peeraddr;
+ struct peer_node *curr_peer;
+ struct attr_val *option;
+ int hmode;
+ int peerflags;
+ int status;
+ int no_needed;
+ int i;
+
+ curr_peer = queue_head(ptree->peers);
+ while (curr_peer != NULL) {
+ /* Find the number of associations needed.
+ * If a pool coomand is specified, then sys_maxclock needed
+ * else, only one is needed
+ */
+ no_needed = (T_Pool == curr_peer->host_mode)
+ ? sys_maxclock
+ : 1;
+
+ /* Find the correct host-mode */
+ hmode = get_correct_host_mode(curr_peer->host_mode);
+ NTP_INSIST(hmode != -1);
+
+ /* translate peerflags options to bits */
+ peerflags = 0;
+ option = queue_head(curr_peer->peerflags);
+ for (; option != NULL; option = next_node(option))
+ switch (option->value.i) {
+
+ default:
+ NTP_INSIST(0);
break;
- }
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
- break;
- if (!ISREFCLOCKADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "%s is inappropriate address for the fudge command, line ignored",
- stoa(&peeraddr));
+ case T_Autokey:
+ peerflags |= FLAG_SKEY;
break;
- }
- memset((void *)&clock_stat, 0, sizeof clock_stat);
- fudgeflag = 0;
- errflg = 0;
- for (i = 2; i < ntokens-1; i++) {
- switch (c = matchkey(tokens[i],
- fudge_keywords, 1)) {
- case CONF_FDG_TIME1:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime1) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time1 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME1;
- break;
+ case T_Burst:
+ peerflags |= FLAG_BURST;
+ break;
- case CONF_FDG_TIME2:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime2) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time2 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME2;
- break;
+ case T_Iburst:
+ peerflags |= FLAG_IBURST;
+ break;
+ case T_Noselect:
+ peerflags |= FLAG_NOSELECT;
+ break;
- case CONF_FDG_STRATUM:
- if (!atoint(tokens[++i], &stratum))
- {
- msyslog(LOG_ERR,
- "fudge %s stratum value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.fudgeval1 = stratum;
- clock_stat.haveflags |= CLK_HAVEVAL1;
- break;
+ case T_Preempt:
+ peerflags |= FLAG_PREEMPT;
+ break;
- case CONF_FDG_REFID:
- i++;
- memcpy(&clock_stat.fudgeval2,
- tokens[i], min(strlen(tokens[i]),
- 4));
- clock_stat.haveflags |= CLK_HAVEVAL2;
- break;
+ case T_Prefer:
+ peerflags |= FLAG_PREFER;
+ break;
- case CONF_FDG_FLAG1:
- case CONF_FDG_FLAG2:
- case CONF_FDG_FLAG3:
- case CONF_FDG_FLAG4:
- if (!atouint(tokens[++i], &fudgeflag)
- || fudgeflag > 1) {
- msyslog(LOG_ERR,
- "fudge %s flag value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- switch(c) {
- case CONF_FDG_FLAG1:
- c = CLK_FLAG1;
- clock_stat.haveflags|=CLK_HAVEFLAG1;
- break;
- case CONF_FDG_FLAG2:
- c = CLK_FLAG2;
- clock_stat.haveflags|=CLK_HAVEFLAG2;
- break;
- case CONF_FDG_FLAG3:
- c = CLK_FLAG3;
- clock_stat.haveflags|=CLK_HAVEFLAG3;
- break;
- case CONF_FDG_FLAG4:
- c = CLK_FLAG4;
- clock_stat.haveflags|=CLK_HAVEFLAG4;
- break;
- }
- if (fudgeflag == 0)
- clock_stat.flags &= ~c;
- else
- clock_stat.flags |= c;
- break;
+ case T_True:
+ peerflags |= FLAG_TRUE;
+ break;
- case CONFIG_UNKNOWN:
- errflg = -1;
- break;
- }
+ case T_Xleave:
+ peerflags |= FLAG_XLEAVE;
+ break;
}
-#ifdef REFCLOCK
+ /* Attempt to resolve the address */
+ ZERO_SOCK(&peeraddr);
+ AF(&peeraddr) = (u_short)curr_peer->addr->type;
+
+ status = get_multiple_netnums(curr_peer->addr->address,
+ &peeraddr, &res, 0, t_UNK);
+
+#ifdef FORCE_DEFER_DNS
+ /* Hack for debugging Deferred DNS
+ * Pretend working names didn't work.
+ */
+ if (status == 1) {
+ /* Deferring everything breaks refclocks. */
+ memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
+ if (!ISREFCLOCKADR(&peeraddr)) {
+ status = 0; /* force deferred DNS path */
+ msyslog(LOG_INFO, "Forcing Deferred DNS for %s, %s",
+ curr_peer->addr->address, stoa(&peeraddr));
+ } else {
+ msyslog(LOG_INFO, "NOT Deferring DNS for %s, %s",
+ curr_peer->addr->address, stoa(&peeraddr));
+ }
+ }
+#endif
+
+ /* I don't know why getnetnum would return -1.
+ * The old code had this test, so I guess it must be
+ * useful
+ */
+ if (status == -1) {
+ /* Do nothing, apparently we found an IPv6
+ * address and can't do anything about it */
+ }
+ /* Check if name resolution failed. If yes, store the
+ * peer information in a file for asynchronous
+ * resolution later
+ */
+ else if (status != 1) {
+ msyslog(LOG_INFO, "Deferring DNS for %s %d", curr_peer->addr->address, no_needed);
+ save_resolve(curr_peer->addr->address,
+ no_needed,
+ curr_peer->addr->type,
+ hmode,
+ curr_peer->peerversion,
+ curr_peer->minpoll,
+ curr_peer->maxpoll,
+ peerflags,
+ curr_peer->ttl,
+ curr_peer->peerkey,
+ (u_char *)"*");
+ }
+ /* Yippie!! Name resolution has succeeded!!!
+ * Now we can proceed to some more sanity checks on
+ * the resolved address before we start to configure
+ * the peer
+ */
+ else {
+ res_bak = res;
+
/*
- * If reference clock support isn't defined the
- * fudge line will still be accepted and syntax
- * checked, but will essentially do nothing.
+ * Loop to configure the desired number of
+ * associations
*/
- if (!errflg) {
- refclock_control(&peeraddr, &clock_stat,
- (struct refclockstat *)0);
+ for (i = 0; (i < no_needed) && res; res =
+ res->ai_next) {
+ ++i;
+ memcpy(&peeraddr, res->ai_addr,
+ res->ai_addrlen);
+ if (is_sane_resolved_address(
+ &peeraddr,
+ curr_peer->host_mode))
+
+ peer_config(&peeraddr,
+ NULL,
+ hmode,
+ curr_peer->peerversion,
+ curr_peer->minpoll,
+ curr_peer->maxpoll,
+ peerflags,
+ curr_peer->ttl,
+ curr_peer->peerkey,
+ (u_char *)"*");
}
-#endif
- break;
+ freeaddrinfo(res_bak);
+ }
+ curr_peer = next_node(curr_peer);
+ }
+}
- case CONFIG_STATSDIR:
- if (ntokens >= 2)
- stats_config(STATS_STATSDIR,tokens[1]);
- break;
- case CONFIG_STATISTICS:
- for (i = 1; i < ntokens; i++) {
- filegen = filegen_get(tokens[i]);
+#ifdef FREE_CFG_T
+static void
+free_config_peers(
+ struct config_tree *ptree
+ )
+{
+ struct peer_node *curr_peer;
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "no statistics named %s available",
- tokens[i]);
- continue;
- }
-#ifdef DEBUG
- if (debug > 3)
- printf("enabling filegen for %s statistics \"%s%s\"\n",
- tokens[i], filegen->prefix, filegen->basename);
-#endif
- filegen->flag |= FGEN_FLAG_ENABLED;
- }
- break;
+ while (NULL != (curr_peer = dequeue(ptree->peers))) {
+ destroy_address_node(curr_peer->addr);
+ DESTROY_QUEUE(curr_peer->peerflags);
+ free_node(curr_peer);
+ }
+}
+#endif /* FREE_CFG_T */
- case CONFIG_FILEGEN:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no id for filegen command, line ignored");
- break;
- }
- filegen = filegen_get(tokens[1]);
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "unknown filegen \"%s\" ignored",
- tokens[1]);
- break;
- }
+static void
+config_unpeers(
+ struct config_tree *ptree
+ )
+{
+ struct addrinfo *res, *res_bak;
+ sockaddr_u peeraddr;
+ struct unpeer_node *curr_unpeer;
+ struct peer *peer;
+ int status;
+ int found;
+
+ for (curr_unpeer = queue_head(ptree->unpeers);
+ curr_unpeer != NULL;
+ curr_unpeer = next_node(curr_unpeer)) {
+
+ /*
+ * Either AssocID will be zero, and we unpeer by name/
+ * address addr, or it is nonzero and addr NULL.
+ */
+ if (curr_unpeer->assocID) {
+ peer = findpeerbyassoc((u_int)curr_unpeer->assocID);
+ if (peer != NULL) {
+ peer_clear(peer, "GONE");
+ unpeer(peer);
+ }
+
+ continue;
+ }
+
+ /* Attempt to resolve the name or address */
+ ZERO_SOCK(&peeraddr);
+ AF(&peeraddr) = (u_short)curr_unpeer->addr->type;
+
+ status = get_multiple_netnums(
+ curr_unpeer->addr->address, &peeraddr, &res, 0,
+ t_UNK);
+
+ /* I don't know why getnetnum would return -1.
+ * The old code had this test, so I guess it must be
+ * useful
+ */
+ if (status == -1) {
+ /* Do nothing, apparently we found an IPv6
+ * address and can't do anything about it */
+ }
+ /* Check if name resolution failed. If yes, throw
+ * up our hands.
+ */
+ else if (status != 1) {
+ /* Do nothing */
+ }
+ /* Yippie!! Name resolution has succeeded!!!
+ */
+ else {
+ res_bak = res;
+
/*
- * peerversion is (ab)used for filegen file (index)
- * peerkey is (ab)used for filegen type
- * peerflags is (ab)used for filegen flags
+ * Loop through the addresses found
*/
- peerversion = 0;
- peerkey = filegen->type;
- peerflags = filegen->flag;
- errflg = 0;
-
- for (i = 2; i < ntokens; i++) {
- switch (matchkey(tokens[i],
- filegen_keywords, 1)) {
- case CONF_FGEN_FILE:
- if (i >= ntokens - 1) {
- msyslog(LOG_ERR,
- "filegen %s file requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerversion = ++i;
- break;
- case CONF_FGEN_TYPE:
- if (i >= ntokens -1) {
- msyslog(LOG_ERR,
- "filegen %s type requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerkey = matchkey(tokens[++i],
- fgen_types, 1);
- if (peerkey == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "filegen %s unknown type \"%s\"",
- tokens[1], tokens[i]);
- errflg = i;
- break;
- }
- break;
+ while (res) {
+ memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
- case CONF_FGEN_FLAG_LINK:
- peerflags |= FGEN_FLAG_LINK;
- break;
+ found = 0;
+ peer = NULL;
- case CONF_FGEN_FLAG_NOLINK:
- peerflags &= ~FGEN_FLAG_LINK;
- break;
+ DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
- case CONF_FGEN_FLAG_ENABLE:
- peerflags |= FGEN_FLAG_ENABLED;
- break;
+ while (!found) {
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
+ if (!peer)
+ break;
+ if (peer->flags & FLAG_CONFIG)
+ found = 1;
+ }
- case CONF_FGEN_FLAG_DISABLE:
- peerflags &= ~FGEN_FLAG_ENABLED;
- break;
+ if (found) {
+ peer_clear(peer, "GONE");
+ unpeer(peer);
}
- }
- if (!errflg)
- filegen_config(filegen, tokens[peerversion],
- (u_char)peerkey, (u_char)peerflags);
- break;
- case CONFIG_SETVAR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no value for setvar command - line ignored");
- } else {
- set_sys_var(tokens[1], strlen(tokens[1])+1,
- (u_short) (RW |
- ((((ntokens > 2)
- && !strcmp(tokens[2],
- "default")))
- ? DEF
- : 0)));
+ res = res->ai_next;
}
- break;
+ freeaddrinfo(res_bak);
+ }
+ }
+}
- case CONFIG_ENABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "enable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 1, 0., NULL);
- }
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_unpeers(
+ struct config_tree *ptree
+ )
+{
+ struct unpeer_node *curr_unpeer;
+
+ while (NULL != (curr_unpeer = dequeue(ptree->unpeers))) {
+ destroy_address_node(curr_unpeer->addr);
+ free_node(curr_unpeer);
+ }
+}
+#endif /* FREE_CFG_T */
- case CONFIG_DISABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "disable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 0, 0., NULL);
- }
- break;
+#ifdef SIM
+static void
+config_sim(
+ struct config_tree *ptree
+ )
+{
+ int i;
+ server_info *serv_info;
+ struct attr_val *init_stmt;
- case CONFIG_PHONE:
- for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
- sys_phone[i - 1] =
- emalloc(strlen(tokens[i]) + 1);
- strcpy(sys_phone[i - 1], tokens[i]);
- }
- sys_phone[i] = NULL;
- break;
+ /* Check if a simulate block was found in the configuration code.
+ * If not, return an error and exit
+ */
+ if (NULL == ptree->sim_details) {
+ fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
+ fprintf(stderr, "\tCheck your configuration file.\n");
+ exit(1);
+ }
- case CONFIG_ADJ: {
- double ftemp;
+ /* Process the initialization statements
+ * -------------------------------------
+ */
+ init_stmt = queue_head(ptree->sim_details->init_opts);
+ while (init_stmt != NULL) {
- sscanf(tokens[1], "%lf", &ftemp);
- proto_config(PROTO_ADJ, 0, ftemp, NULL);
- }
+ switch(init_stmt->attr) {
+
+ case T_Beep_Delay:
+ simulation.beep_delay = init_stmt->value.d;
break;
+ case T_Sim_Duration:
+ simulation.end_time = init_stmt->value.d;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Unknown simulator init token %d\n",
+ init_stmt->attr);
+ exit(1);
}
+ init_stmt = next_node(init_stmt);
+ }
+
+
+ /* Process the server list
+ * -----------------------
+ */
+ simulation.num_of_servers =
+ get_no_of_elements(ptree->sim_details->servers);
+ simulation.servers = emalloc(simulation.num_of_servers
+ * sizeof(server_info));
+
+ serv_info = queue_head(ptree->sim_details->servers);
+ for (i = 0;i < simulation.num_of_servers; i++) {
+ if (NULL == serv_info) {
+ fprintf(stderr, "Simulator server list is corrupt\n");
+ exit(1);
+ } else
+ memcpy(&simulation.servers[i], serv_info, sizeof(server_info));
+ serv_info = next_node(serv_info);
}
- if (fp[0])
- (void)fclose(fp[0]);
+ /* Create server associations */
+ printf("Creating server associations\n");
+ create_server_associations();
+ fprintf(stderr,"\tServer associations successfully created!!\n");
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_sim(
+ struct config_tree *ptree
+ )
+{
+ if (NULL == ptree->sim_details)
+ return;
+
+ DESTROY_QUEUE(ptree->sim_details->init_opts);
+ DESTROY_QUEUE(ptree->sim_details->servers);
+
+ /* Free the sim_node memory and set the sim_details as NULL */
+ free_node(ptree->sim_details);
+ ptree->sim_details = NULL;
+}
+#endif /* FREE_CFG_T */
+#endif /* SIM */
+
+
+/* Define two different config functions. One for the daemon and the other for
+ * the simulator. The simulator ignores a lot of the standard ntpd configuration
+ * options
+ */
+#ifndef SIM
+static void
+config_ntpd(
+ struct config_tree *ptree
+ )
+{
+ config_nic_rules(ptree);
+ io_open_sockets();
+ config_monitor(ptree);
+ config_auth(ptree);
+ config_tos(ptree);
+ config_access(ptree);
+ config_tinker(ptree);
+ config_system_opts(ptree);
+ config_logconfig(ptree);
+ config_phone(ptree);
+ config_setvar(ptree);
+ config_ttl(ptree);
+ config_trap(ptree);
+ config_vars(ptree);
+ config_other_modes(ptree);
+ config_peers(ptree);
+ config_unpeers(ptree);
+ config_fudge(ptree);
+ config_qos(ptree);
+}
+#endif /* !SIM */
+
+
+#ifdef SIM
+static void
+config_ntpdsim(
+ struct config_tree *ptree
+ )
+{
+ printf("Configuring Simulator...\n");
+ printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
+
+ config_tos(ptree);
+ config_monitor(ptree);
+ config_tinker(ptree);
+ config_system_opts(ptree);
+ config_logconfig(ptree);
+ config_vars(ptree);
+ config_sim(ptree);
+}
+#endif /* SIM */
+
+
+/*
+ * config_remotely() - implements ntpd side of ntpq :config
+ */
+void
+config_remotely(
+ sockaddr_u * remote_addr
+ )
+{
+ struct FILE_INFO remote_cuckoo;
+ char origin[128];
+
+ snprintf(origin, sizeof(origin), "remote config from %s",
+ stoa(remote_addr));
+ memset(&remote_cuckoo, 0, sizeof(remote_cuckoo));
+ remote_cuckoo.fname = origin;
+ remote_cuckoo.line_no = 1;
+ remote_cuckoo.col_no = 1;
+ ip_file = &remote_cuckoo;
+ input_from_file = 0;
+
+ init_syntax_tree(&cfgt);
+ yyparse();
+ cfgt.source.attr = CONF_SOURCE_NTPQ;
+ cfgt.timestamp = time(NULL);
+ cfgt.source.value.s = estrdup(stoa(remote_addr));
+
+ DPRINTF(1, ("Finished Parsing!!\n"));
+
+ save_and_apply_config_tree();
+
+ input_from_file = 1;
+}
+
+
+/*
+ * getconfig() - process startup configuration file e.g /etc/ntp.conf
+ */
+void
+getconfig(
+ int argc,
+ char *argv[]
+ )
+{
+ char line[MAXLINE];
+
+#ifdef DEBUG
+ atexit(free_all_config_trees);
+#endif
+#ifndef SYS_WINNT
+ config_file = CONFIG_FILE;
+#else
+ temp = CONFIG_FILE;
+ if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
+ msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
+ exit(1);
+ }
+ config_file = config_file_storage;
+
+ temp = ALT_CONFIG_FILE;
+ if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
+ msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
+ exit(1);
+ }
+ alt_config_file = alt_config_file_storage;
+
+#endif /* SYS_WINNT */
+ res_fp = NULL;
+ ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+
+ /*
+ * install a non default variable with this daemon version
+ */
+ snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
+ set_sys_var(line, strlen(line)+1, RO);
+
+ /*
+ * Set up for the first time step to install a variable showing
+ * which syscall is being used to step.
+ */
+ set_tod_using = &ntpd_set_tod_using;
+
+ /*
+ * On Windows, the variable has already been set, on the rest,
+ * initialize it to "UNKNOWN".
+ */
+#ifndef SYS_WINNT
+ strncpy(line, "settimeofday=\"UNKNOWN\"", sizeof(line));
+ set_sys_var(line, strlen(line) + 1, RO);
+#endif
+
+ /*
+ * Initialize the loop.
+ */
+ loop_config(LOOP_DRIFTINIT, 0.);
+
+ getCmdOpts(argc, argv);
+
+ init_syntax_tree(&cfgt);
+
+ curr_include_level = 0;
+ if (
+ (fp[curr_include_level] = F_OPEN(FindConfig(config_file), "r")) == NULL
#ifdef HAVE_NETINFO
- if (config_netinfo)
- free_netinfo_config(config_netinfo);
+ /* If there is no config_file, try NetInfo. */
+ && check_netinfo && !(config_netinfo = get_netinfo_config())
#endif /* HAVE_NETINFO */
+ ) {
+ msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
+#ifndef SYS_WINNT
+ io_open_sockets();
-#if !defined(VMS) && !defined(SYS_VXWORKS)
- /* find a keyid */
- if (info_auth_keyid == 0)
- req_keyid = 65535;
- else
- req_keyid = info_auth_keyid;
+ return;
+#else
+ /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
- /* if doesn't exist, make up one at random */
- if (!authhavekey(req_keyid)) {
- char rankey[9];
- int j;
-
- for (i = 0; i < 8; i++)
- for (j = 1; j < 100; ++j) {
- rankey[i] = (char) (ntp_random() & 0xff);
- if (rankey[i] != 0) break;
- }
- rankey[8] = 0;
- authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
- authtrust(req_keyid, 1);
- if (!authhavekey(req_keyid)) {
- msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
- /* HMS: Should this be fatal? */
+ if ((fp[curr_include_level] = F_OPEN(FindConfig(alt_config_file), "r")) == NULL) {
+
+ /*
+ * Broadcast clients can sometimes run without
+ * a configuration file.
+ */
+ msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
+ io_open_sockets();
+
+ return;
}
- }
+ cfgt.source.value.s = estrdup(alt_config_file);
+#endif /* SYS_WINNT */
+ } else
+ cfgt.source.value.s = estrdup(config_file);
- /* save keyid so we will accept config requests with it */
- info_auth_keyid = req_keyid;
-#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
+
+ /*** BULK OF THE PARSER ***/
+#ifdef DEBUG
+ yydebug = !!(debug >= 5);
+#endif
+ ip_file = fp[curr_include_level];
+ yyparse();
+
+ DPRINTF(1, ("Finished Parsing!!\n"));
+
+ cfgt.source.attr = CONF_SOURCE_FILE;
+ cfgt.timestamp = time(NULL);
+
+ save_and_apply_config_tree();
+
+ while (curr_include_level != -1)
+ FCLOSE(fp[curr_include_level--]);
+
+#ifdef HAVE_NETINFO
+ if (config_netinfo)
+ free_netinfo_config(config_netinfo);
+#endif /* HAVE_NETINFO */
+
+ /*
+ printf("getconfig: res_fp <%p> call_resolver: %d", res_fp, call_resolver);
+ */
if (res_fp != NULL) {
if (call_resolver) {
@@ -1912,19 +3937,180 @@ getconfig(
}
+void
+save_and_apply_config_tree(void)
+{
+ struct config_tree *ptree;
+#ifndef SAVECONFIG
+ struct config_tree *punlinked;
+#endif
+
+ /*
+ * Keep all the configuration trees applied since startup in
+ * a list that can be used to dump the configuration back to
+ * a text file.
+ */
+ ptree = emalloc(sizeof(*ptree));
+ memcpy(ptree, &cfgt, sizeof(*ptree));
+ memset(&cfgt, 0, sizeof(cfgt));
+
+ LINK_TAIL_SLIST(cfg_tree_history, ptree, link,
+ struct config_tree);
+
+#ifdef SAVECONFIG
+ if (HAVE_OPT( SAVECONFIGQUIT )) {
+ FILE *dumpfile;
+ int err;
+ int dumpfailed;
+
+ dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
+ if (NULL == dumpfile) {
+ err = errno;
+ fprintf(stderr,
+ "can not create save file %s, error %d %s\n",
+ OPT_ARG( SAVECONFIGQUIT ), err,
+ strerror(err));
+ exit(err);
+ }
+
+ dumpfailed = dump_all_config_trees(dumpfile, 0);
+ if (dumpfailed)
+ fprintf(stderr,
+ "--saveconfigquit %s error %d\n",
+ OPT_ARG( SAVECONFIGQUIT ),
+ dumpfailed);
+ else
+ fprintf(stderr,
+ "configuration saved to %s\n",
+ OPT_ARG( SAVECONFIGQUIT ));
+
+ exit(dumpfailed);
+ }
+#endif /* SAVECONFIG */
+
+ /* The actual configuration done depends on whether we are configuring the
+ * simulator or the daemon. Perform a check and call the appropriate
+ * function as needed.
+ */
+
+#ifndef SIM
+ config_ntpd(ptree);
+#else
+ config_ntpdsim(ptree);
+#endif
+
+ /*
+ * With configure --disable-saveconfig, there's no use keeping
+ * the config tree around after application, so free it.
+ */
+#ifndef SAVECONFIG
+ UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
+ struct config_tree);
+ NTP_INSIST(punlinked == ptree);
+ free_config_tree(ptree);
+#endif
+}
+
+
+void
+ntpd_set_tod_using(
+ const char *which
+ )
+{
+ char line[128];
+
+ snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
+ set_sys_var(line, strlen(line) + 1, RO);
+}
+
+
+/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
+ * --------------------------------------------
+ */
+
+
+/*
+ * get_pfxmatch - find value for prefixmatch
+ * and update char * accordingly
+ */
+static u_int32
+get_pfxmatch(
+ const char ** pstr,
+ struct masks * m
+ )
+{
+ while (m->name != NULL) {
+ if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
+ *pstr += strlen(m->name);
+ return m->mask;
+ } else {
+ m++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * get_match - find logmask value
+ */
+static u_int32
+get_match(
+ const char * str,
+ struct masks * m
+ )
+{
+ while (m->name != NULL) {
+ if (strcmp(str, m->name) == 0)
+ return m->mask;
+ else
+ m++;
+ }
+ return 0;
+}
+
+/*
+ * get_logmask - build bitmask for ntp_syslogmask
+ */
+static u_int32
+get_logmask(
+ const char * str
+ )
+{
+ const char * t;
+ u_int32 offset;
+ u_int32 mask;
+
+ mask = get_match(str, logcfg_noclass_items);
+ if (mask != 0)
+ return mask;
+
+ t = str;
+ offset = get_pfxmatch(&t, logcfg_class);
+ mask = get_match(t, logcfg_class_items);
+
+ if (mask)
+ return mask << offset;
+ else
+ msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
+ str);
+
+ return 0;
+}
+
+
#ifdef HAVE_NETINFO
-/*
+/*
* get_netinfo_config - find the nearest NetInfo domain with an ntp
* configuration and initialize the configuration state.
*/
static struct netinfo_config_state *
-get_netinfo_config()
+get_netinfo_config(void)
{
ni_status status;
void *domain;
ni_id config_dir;
- struct netinfo_config_state *config;
+ struct netinfo_config_state *config;
if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
@@ -1942,12 +4128,12 @@ get_netinfo_config()
return NULL;
}
- config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
- config->domain = domain;
- config->config_dir = config_dir;
- config->prop_index = 0;
- config->val_index = 0;
- config->val_list = NULL;
+ config = emalloc(sizeof(*config));
+ config->domain = domain;
+ config->config_dir = config_dir;
+ config->prop_index = 0;
+ config->val_index = 0;
+ config->val_list = NULL;
return config;
}
@@ -1958,7 +4144,9 @@ get_netinfo_config()
* free_netinfo_config - release NetInfo configuration state
*/
static void
-free_netinfo_config(struct netinfo_config_state *config)
+free_netinfo_config(
+ struct netinfo_config_state *config
+ )
{
ni_free(config->domain);
free(config);
@@ -1983,35 +4171,39 @@ gettokens_netinfo (
/*
* Iterate through each keyword and look for a property that matches it.
*/
- again:
+ again:
if (!val_list) {
- for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
- {
- ni_namelist namelist;
+ for (; prop_index < COUNTOF(keywords); prop_index++)
+ {
+ ni_namelist namelist;
struct keyword current_prop = keywords[prop_index];
+ ni_index index;
/*
* For each value associated in the property, we're going to return
* a separate line. We squirrel away the values in the config state
* so the next time through, we don't need to do this lookup.
*/
- NI_INIT(&namelist);
- if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
- ni_index index;
+ NI_INIT(&namelist);
+ if (NI_OK == ni_lookupprop(config->domain,
+ &config->config_dir, current_prop.text,
+ &namelist)) {
/* Found the property, but it has no values */
if (namelist.ni_namelist_len == 0) continue;
- if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
+ config->val_list =
+ emalloc(sizeof(char*) *
+ (namelist.ni_namelist_len + 1));
+ val_list = config->val_list;
- for (index = 0; index < namelist.ni_namelist_len; index++) {
- char *value = namelist.ni_namelist_val[index];
-
- if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
-
- strcpy(val_list[index], value);
+ for (index = 0;
+ index < namelist.ni_namelist_len;
+ index++) {
+ char *value;
+
+ value = namelist.ni_namelist_val[index];
+ val_list[index] = estrdup(value);
}
val_list[index] = NULL;
@@ -2023,14 +4215,14 @@ gettokens_netinfo (
}
/* No list; we're done here. */
- if (!val_list) return CONFIG_UNKNOWN;
+ if (!val_list)
+ return CONFIG_UNKNOWN;
/*
* We have a list of values for the current property.
* Iterate through them and return each in order.
*/
- if (val_list[val_index])
- {
+ if (val_list[val_index]) {
int ntok = 1;
int quoted = 0;
char *tokens = val_list[val_index];
@@ -2048,16 +4240,18 @@ gettokens_netinfo (
break;
} else { /* must be space */
*tokens++ = '\0';
- while (ISSPACE(*tokens)) tokens++;
- if (ISEOL(*tokens)) break;
+ while (ISSPACE(*tokens))
+ tokens++;
+ if (ISEOL(*tokens))
+ break;
}
}
if (ntok == MAXTOKENS) {
/* HMS: chomp it to lose the EOL? */
msyslog(LOG_ERR,
- "gettokens_netinfo: too many tokens. Ignoring: %s",
- tokens);
+ "gettokens_netinfo: too many tokens. Ignoring: %s",
+ tokens);
} else {
*ntokens = ntok + 1;
}
@@ -2073,220 +4267,144 @@ gettokens_netinfo (
/* Free val_list and reset counters. */
for (val_index = 0; val_list[val_index]; val_index++)
free(val_list[val_index]);
- free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
+ free(val_list);
+ val_list = config->val_list = NULL;
+ val_index = config->val_index = 0;
goto again;
}
#endif /* HAVE_NETINFO */
-
/*
- * gettokens - read a line and return tokens
+ * getnetnum - return a net number (this is crude, but careful)
+ *
+ * returns 1 for success, and mysteriously, 0 or -1 for failure
*/
static int
-gettokens (
- FILE *fp,
- char *line,
- char **tokenlist,
- int *ntokens
+getnetnum(
+ const char *num,
+ sockaddr_u *addr,
+ int complain,
+ enum gnn_type a_type
)
{
- register char *cp;
- register int ntok;
- register int quoted = 0;
-
- /*
- * Find start of first token
- */
- again:
- while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
- cp = line;
- while (ISSPACE(*cp))
- cp++;
- if (!ISEOL(*cp))
- break;
- }
- if (cp == NULL) {
- *ntokens = 0;
- return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
- }
-
- /*
- * Now separate out the tokens
- */
- for (ntok = 0; ntok < MAXTOKENS; ntok++) {
- tokenlist[ntok] = cp;
- while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
- quoted ^= (*cp++ == '"');
-
- if (ISEOL(*cp)) {
- *cp = '\0';
- break;
- } else { /* must be space */
- *cp++ = '\0';
- while (ISSPACE(*cp))
- cp++;
- if (ISEOL(*cp))
- break;
- }
- }
+ int retval;
+ struct addrinfo *res;
- /* Heiko: Remove leading and trailing quotes around tokens */
- {
- int i,j = 0;
-
-
- for (i = 0; i < ntok; i++) {
- /* Now check if the first char is a quote and remove that */
- if ( tokenlist[ntok][0] == '"' )
- tokenlist[ntok]++;
-
- /* Now check the last char ... */
- j = strlen(tokenlist[ntok])-1;
- if ( tokenlist[ntok][j] == '"' )
- tokenlist[ntok][j] = '\0';
- }
-
- }
+ /* Get all the addresses that resolve to this name */
+ retval = get_multiple_netnums(num, addr, &res, complain, a_type);
- if (ntok == MAXTOKENS) {
- --ntok;
- /* HMS: chomp it to lose the EOL? */
- msyslog(LOG_ERR,
- "gettokens: too many tokens on the line. Ignoring %s",
- cp);
- } else {
- /*
- * Return the match
- */
- *ntokens = ntok + 1;
- ntok = matchkey(tokenlist[0], keywords, 1);
- if (ntok == CONFIG_UNKNOWN)
- goto again;
+ if (retval != 1) {
+ /* Name resolution failed */
+ return retval;
}
- return ntok;
-}
-
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
-/*
- * matchkey - match a keyword to a list
- */
-static int
-matchkey(
- register char *word,
- register struct keyword *keys,
- int complain
- )
-{
- for (;;) {
- if (keys->keytype == CONFIG_UNKNOWN) {
- if (complain)
- msyslog(LOG_ERR,
- "configure: keyword \"%s\" unknown, line ignored",
- word);
- return CONFIG_UNKNOWN;
- }
- if (STRSAME(word, keys->text))
- return keys->keytype;
- keys++;
- }
+ freeaddrinfo(res);
+ return 1;
}
/*
- * getnetnum - return a net number (this is crude, but careful)
+ * get_multiple_netnums
+ *
+ * returns 1 for success, and mysteriously, 0 or -1 for failure
*/
static int
-getnetnum(
- const char *num,
- struct sockaddr_storage *addr,
+get_multiple_netnums(
+ const char *nameornum,
+ sockaddr_u *addr,
+ struct addrinfo **res,
int complain,
enum gnn_type a_type
)
{
+ char lookbuf[1024];
+ const char *lookup;
+ char *pch;
struct addrinfo hints;
struct addrinfo *ptr;
int retval;
+ sockaddr_u ipaddr;
-#if 0
- printf("getnetnum: <%s> is a %s (%d)\n",
- num,
- (a_type == t_UNK)
- ? "t_UNK"
- : (a_type == t_REF)
- ? "t_REF"
- : (a_type == t_MSK)
- ? "t_MSK"
- : "???",
- a_type);
-#endif
-
- /* Get host address. Looking for UDP datagram connection */
- memset(&hints, 0, sizeof (hints));
- if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
- hints.ai_family = addr->ss_family;
- else
- hints.ai_family = AF_UNSPEC;
- /*
- * If we don't have an IPv6 stack, just look up IPv4 addresses
- */
- if (isc_net_probeipv6() != ISC_R_SUCCESS)
- hints.ai_family = AF_INET;
+ memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM;
+ if (strlen(nameornum) >= sizeof(lookbuf)) {
+ NTP_INSIST(strlen(nameornum) < sizeof(lookbuf));
+ return 0;
+ }
- if (a_type != t_UNK) {
+ lookup = nameornum;
+ if (is_ip_address(nameornum, &ipaddr)) {
hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF(&ipaddr);
+ if ('[' == nameornum[0]) {
+ lookup = lookbuf;
+ strncpy(lookbuf, &nameornum[1],
+ sizeof(lookbuf));
+ pch = strchr(lookbuf, ']');
+ if (pch != NULL)
+ *pch = '\0';
+ }
+ pch = strchr(lookup, '%');
+ if (pch != NULL) {
+ if (lookup != lookbuf) {
+ lookup = lookbuf;
+ strncpy(lookbuf, nameornum,
+ sizeof(lookbuf));
+ pch = strchr(lookup, '%');
+ }
+ *pch = '\0';
+ }
}
-#ifdef DEBUG
- if (debug > 3)
- printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
-#endif
- retval = getaddrinfo(num, "ntp", &hints, &ptr);
- if (retval != 0 ||
- (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
+ if (AF_INET6 == hints.ai_family && !ipv6_works)
+ return 0;
+
+ if (AF_UNSPEC == hints.ai_family) {
+ if (!ipv6_works)
+ hints.ai_family = AF_INET;
+ else if (!ipv4_works)
+ hints.ai_family = AF_INET6;
+ else if (IS_IPV4(addr) || IS_IPV6(addr))
+ hints.ai_family = AF(addr);
+ }
+
+ /* Get host address. Looking for UDP datagram connection */
+ hints.ai_socktype = SOCK_DGRAM;
+
+ DPRINTF(4, ("getaddrinfo %s%s\n",
+ (AF_UNSPEC == hints.ai_family)
+ ? ""
+ : (AF_INET == hints.ai_family)
+ ? "v4 "
+ : "v6 ",
+ lookup));
+
+ retval = getaddrinfo(lookup, "ntp", &hints, &ptr);
+
+ if (retval || (AF_INET6 == ptr->ai_family && !ipv6_works)) {
if (complain)
msyslog(LOG_ERR,
"getaddrinfo: \"%s\" invalid host address, ignored",
- num);
-#ifdef DEBUG
- if (debug > 0)
- printf(
- "getaddrinfo: \"%s\" invalid host address%s.\n",
- num, (complain)
- ? ", ignored"
- : "");
-#endif
- if (retval == 0 &&
- ptr->ai_family == AF_INET6 &&
- isc_net_probeipv6() != ISC_R_SUCCESS)
- {
+ lookup);
+ else
+ DPRINTF(1, ("getaddrinfo: \"%s\" invalid host address.\n",
+ lookup));
+
+ if (!retval) {
+ freeaddrinfo(ptr);
return -1;
- }
- else {
+ } else {
return 0;
}
}
+ *res = ptr;
- memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
-#ifdef DEBUG
- if (debug > 1)
- printf("getnetnum given %s, got %s (%s/%d)\n",
- num, stoa(addr),
- (a_type == t_UNK)
- ? "t_UNK"
- : (a_type == t_REF)
- ? "t_REF"
- : (a_type == t_MSK)
- ? "t_MSK"
- : "???",
- a_type);
-#endif
- freeaddrinfo(ptr);
return 1;
}
@@ -2318,6 +4436,8 @@ catchchild(
static void
save_resolve(
char *name,
+ int no_needed,
+ int type,
int mode,
int version,
int minpoll,
@@ -2331,16 +4451,26 @@ save_resolve(
#ifndef SYS_VXWORKS
if (res_fp == NULL) {
#ifndef SYS_WINNT
- (void) strcpy(res_file, RES_TEMPFILE);
+ strcpy(res_file, RES_TEMPFILE);
#else
+ int len;
+
/* no /tmp directory under NT */
- {
- if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
- msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
- return;
- }
- (void) strcat(res_file, "ntpdXXXXXX");
+ if (!GetTempPath(sizeof res_file, res_file)) {
+ msyslog(LOG_ERR, "can not get temp dir: %m");
+ exit(1);
}
+
+ len = strlen(res_file);
+ if (sizeof res_file < len + sizeof "ntpdXXXXXX") {
+ msyslog(LOG_ERR,
+ "temporary directory path %s too long",
+ res_file);
+ exit(1);
+ }
+
+ memmove(res_file + len, "ntpdXXXXXX",
+ sizeof "ntpdXXXXXX");
#endif /* SYS_WINNT */
#ifdef HAVE_MKSTEMP
{
@@ -2351,7 +4481,7 @@ save_resolve(
res_fp = fdopen(fd, "r+");
}
#else
- (void) mktemp(res_file);
+ mktemp(res_file);
res_fp = fopen(res_file, "w");
#endif
if (res_fp == NULL) {
@@ -2365,12 +4495,15 @@ save_resolve(
}
#endif
- (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
- mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+ (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %d %u %s\n",
+ name, no_needed, type,
+ mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
#ifdef DEBUG
if (debug > 1)
- printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
- version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+ printf("config: %s %d %d %d %d %d %d %x %d %u %s\n",
+ name, no_needed, type,
+ mode, version, minpoll, maxpoll, flags,
+ ttl, keyid, keystr);
#endif
#else /* SYS_VXWORKS */
@@ -2397,7 +4530,10 @@ abort_resolve(void)
#ifndef SYS_VXWORKS /* we don't open the file to begin with */
#if !defined(VMS)
- (void) unlink(res_file);
+ if (unlink(res_file))
+ msyslog(LOG_WARNING,
+ "Unable to remove temporary resolver file %s, %m",
+ res_file);
#else
(void) delete(res_file);
#endif /* VMS */
@@ -2407,9 +4543,9 @@ abort_resolve(void)
/*
* do_resolve_internal - start up the resolver function (not program)
- */
-/*
- * On VMS, this routine will simply refuse to resolve anything.
+ *
+ * On VMS, VxWorks, and Unix-like systems lacking fork(), this routine
+ * will simply refuse to resolve anything.
*
* Possible implementation: keep `res_file' in memory, do async
* name resolution via QIO, update from within completion AST.
@@ -2418,7 +4554,9 @@ abort_resolve(void)
static void
do_resolve_internal(void)
{
+#ifndef SYS_WINNT
int i;
+#endif
if (res_fp == NULL) {
/* belch */
@@ -2431,12 +4569,11 @@ do_resolve_internal(void)
(void) fclose(res_fp);
res_fp = NULL;
-#if !defined(VMS) && !defined (SYS_VXWORKS)
+#ifndef NO_INTRES
req_file = res_file; /* set up pointer to res file */
#ifndef SYS_WINNT
(void) signal_no_reset(SIGCHLD, catchchild);
-#ifndef SYS_VXWORKS
/* the parent process will write to the pipe
* in order to wake up to child process
* which may be waiting in a select() call
@@ -2487,36 +4624,19 @@ do_resolve_internal(void)
* THUS:
*/
- /* This is the child process who will read the pipe,
- * so we close the write fd */
- close(resolver_pipe_fd[1]);
+ /*
+ msyslog(LOG_INFO, "do_resolve_internal: pre-closelog");
+ */
closelog();
kill_asyncio(0);
(void) signal_no_reset(SIGCHLD, SIG_DFL);
-#ifdef DEBUG
- if (0)
- debug = 2;
-#endif
-
-# ifndef LOG_DAEMON
- openlog("ntpd_initres", LOG_PID);
-# else /* LOG_DAEMON */
-
-# ifndef LOG_NTP
-# define LOG_NTP LOG_DAEMON
-# endif
- openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
-#ifndef SYS_CYGWIN32
-# ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-# endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
-# endif /* LOG_DAEMON */
-#endif
+ init_logging("ntpd_intres", 0);
+ setup_logfile();
+ /*
+ msyslog(LOG_INFO, "do_resolve_internal: post-closelog");
+ */
ntp_intres();
@@ -2528,52 +4648,47 @@ do_resolve_internal(void)
abort_resolve();
exit(1);
}
-#else
- /* vxWorks spawns a thread... -casey */
- i = sp (ntp_intres);
- /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
-#endif
if (i == -1) {
msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
(void) signal_no_reset(SIGCHLD, SIG_DFL);
abort_resolve();
- }
- else {
+ } else
/* This is the parent process who will write to the pipe,
* so we close the read fd */
close(resolver_pipe_fd[0]);
- }
#else /* SYS_WINNT */
{
/* NT's equivalent of fork() is _spawn(), but the start point
* of the new process is an executable filename rather than
* a function name as desired here.
*/
- DWORD dwThreadId;
+ unsigned thread_id;
+ uintptr_t res_thd_handle;
+
fflush(stdout);
ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ResolverEventHandle == NULL) {
msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
abort_resolve();
}
- ResolverThreadHandle = CreateThread(
- NULL, /* no security attributes */
- 0, /* use default stack size */
- (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
- NULL, /* argument to thread function */
- 0, /* use default creation flags */
- &dwThreadId); /* returns the thread identifier */
- if (ResolverThreadHandle == NULL) {
- msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
+ res_thd_handle = _beginthreadex(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ ntp_intres_thread, /* thread function */
+ NULL, /* argument to thread function */
+ 0, /* use default creation flags */
+ &thread_id); /* receives thread identifier */
+ if (!res_thd_handle) {
+ msyslog(LOG_ERR, "_beginthreadex ntp_intres_thread failed %m");
CloseHandle(ResolverEventHandle);
ResolverEventHandle = NULL;
abort_resolve();
}
}
#endif /* SYS_WINNT */
-#else /* VMS VX_WORKS */
+#else /* NO_INTRES follows */
msyslog(LOG_ERR,
- "Name resolution not implemented for VMS - use numeric addresses");
+ "Deferred DNS not implemented - use numeric addresses");
abort_resolve();
-#endif /* VMS VX_WORKS */
+#endif
}