]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
This changeset should now contain the remainder of the changes needed to incorporate...
authorSachin Kamboj <kamboj@cis.udel.edu>
Tue, 16 Jan 2007 05:27:25 +0000 (00:27 -0500)
committerSachin Kamboj <kamboj@cis.udel.edu>
Tue, 16 Jan 2007 05:27:25 +0000 (00:27 -0500)
bk: 45ac623dwJygL7rJ_bP1MyfKxw9rIQ

include/ntp_config.h
include/ntpsim.h
libntp/systime.c
ntpd/cmd_args.c
ntpd/ntp_config.c
ntpd/ntp_control.c
ntpd/ntp_io.c
ntpd/ntpsim.c
ntpq/ntpq-subs.c
ntpq/ntpq.c

index ae657a9919549bafed0dd5ca29f6b51ea02a5666..1b3d25f525559c6f36d183eef2a49e0518a22b4d 100644 (file)
@@ -1,3 +1,9 @@
+#ifndef __NTP_CONFIG_H__
+#define __NTP_CONFIG_H__
+
+#include "ntp_data_structures.h"
+
+
 /*
  * Configuration file name
  */
 # endif /* SYS_WINNT */
 #endif /* not CONFIG_FILE */
 
-/*
- * Types of entries we understand.
- */
-#define CONFIG_UNKNOWN         0
 
-/*
- * Command keywords
- */
-#define CONFIG_PEER            1
-#define CONFIG_SERVER          2
-#define CONFIG_AUTOMAX         3
-#define CONFIG_DRIFTFILE       4
-#define CONFIG_BROADCAST       5
-#define CONFIG_BROADCASTCLIENT 6
-#define CONFIG_AUTHENTICATE    7
-#define CONFIG_KEYS            8
-#define CONFIG_REVOKE          9
-#define CONFIG_CDELAY          10
-#define CONFIG_RESTRICT                11
-#define CONFIG_BDELAY          12
-#define CONFIG_TRUSTEDKEY      13
-#define CONFIG_REQUESTKEY      14
-#define CONFIG_CONTROLKEY      15
-#define CONFIG_TRAP            16
-#define CONFIG_FUDGE           17
-#define CONFIG_TINKER          18
-#define CONFIG_STATSDIR                19
-#define CONFIG_FILEGEN         20
-#define CONFIG_STATISTICS      21
-#define CONFIG_PIDFILE         22
-#define CONFIG_SETVAR          23
-#define CONFIG_DISCARD         24
-#define CONFIG_ADJ             25
-#define CONFIG_MULTICASTCLIENT 26
-#define CONFIG_ENABLE          27
-#define CONFIG_DISABLE         28
-#define CONFIG_PHONE           29
-#define CONFIG_LOGFILE         30
-#define CONFIG_LOGCONFIG       31
-#define CONFIG_MANYCASTCLIENT  32
-#define CONFIG_MANYCASTSERVER  33
-#define CONFIG_TOS             34
-#define CONFIG_TTL             35
-#define CONFIG_INCLUDEFILE      36
-#define CONFIG_KEYSDIR         37
-#define CONFIG_END             38
-#ifdef OPENSSL
-#define CONFIG_CRYPTO          39
-#endif /* OPENSSL */
+/* Limits */
+#define MAXLINE 1024
 
-/*
- * "peer", "server", "broadcast" modifier keywords
- */
-#define CONF_MOD_VERSION       1
-#define CONF_MOD_KEY           2
-#define CONF_MOD_MINPOLL       3
-#define CONF_MOD_MAXPOLL       4
-#define CONF_MOD_PREFER                5
-#define CONF_MOD_BURST         6
-#define CONF_MOD_IBURST                7
-#define CONF_MOD_SKEY          8
-#define CONF_MOD_TTL           9
-#define CONF_MOD_MODE          10
-#define CONF_MOD_NOSELECT      11
-#define CONF_MOD_TRUE          12
-#define        CONF_MOD_PREEMPT        13
-#define CONF_MOD_DYNAMIC       14
 
-/*
- * "restrict" modifier keywords
- */
-#define CONF_RES_MASK          1
-#define CONF_RES_IGNORE                2
-#define CONF_RES_NOSERVE       3
-#define CONF_RES_NOTRUST       4
-#define CONF_RES_NOQUERY       5
-#define CONF_RES_NOMODIFY      6
-#define CONF_RES_NOPEER                7
-#define CONF_RES_NOTRAP                8
-#define CONF_RES_LPTRAP                9
-#define CONF_RES_NTPPORT       10
-#define CONF_RES_LIMITED       11
-#define CONF_RES_VERSION       12
-#define CONF_RES_DEMOBILIZE    13
+/* Structure for storing an attribute-value pair  */
+struct attr_val {
+    int attr;
+    union val{
+        double d;
+        int i;
+        char *s;
+        void *p;
+    } value;
+    int type;
+};
 
-/*
- * "trap" modifier keywords
- */
-#define CONF_TRAP_PORT         1
-#define CONF_TRAP_INTERFACE    2
+/* Structure for nodes on the syntax tree */
+struct address_node {
+    char *address;
+    int type;
+};
 
-/*
- * "fudge" modifier keywords
- */
-#define CONF_FDG_TIME1         1
-#define CONF_FDG_TIME2         2
-#define CONF_FDG_STRATUM       3
-#define CONF_FDG_REFID         4
-#define CONF_FDG_FLAG1         5
-#define CONF_FDG_FLAG2         6
-#define CONF_FDG_FLAG3         7
-#define CONF_FDG_FLAG4         8
+struct restrict_node {
+    struct address_node *addr;
+    struct address_node *mask;
+    queue *flags;
+    int line_no;
+};
 
-/*
- * "filegen" modifier keywords
- */
-#define CONF_FGEN_FILE         1
-#define CONF_FGEN_TYPE         2
-#define CONF_FGEN_FLAG_LINK    3
-#define CONF_FGEN_FLAG_NOLINK  4
-#define CONF_FGEN_FLAG_ENABLE  5
-#define CONF_FGEN_FLAG_DISABLE 6
+struct peer_node {
+    int host_mode;
+    struct address_node *addr;
+    int minpoll;
+    int maxpoll;
+    int ttl;
+    int peerversion;
+    int peerkey;
+    int peerflags;
+};
 
-/*
- * "discard" modifier keywords
- */
-#define CONF_DISCARD_AVERAGE   1
-#define CONF_DISCARD_MINIMUM   2
-#define        CONF_DISCARD_MONITOR    3
+struct auth_node {
+    int autokey;
+    int control_key;
+    queue *crypto_cmd_list;
+    char *keys;
+    char *keysdir;
+    int requested_key;
+    int revoke;
+    queue *trusted_key_list;
+};
 
-/*
- * "tinker" modifier keywords
- */
-#define CONF_CLOCK_MAX         1
-#define CONF_CLOCK_PANIC       2
-#define CONF_CLOCK_PHI         3
-#define CONF_CLOCK_MINSTEP     4
-#define CONF_CLOCK_ALLAN       5
-#define CONF_CLOCK_HUFFPUFF    6
-#define CONF_CLOCK_FREQ                7
-#define CONF_CLOCK_CODEC       8
+struct filegen_node {
+    char *name;
+    queue *options;
+};
 
-/*
- * "tos" modifier keywords
- */
-#define CONF_TOS_MINCLOCK      1
-#define        CONF_TOS_MAXCLOCK       2
-#define CONF_TOS_MINSANE       3
-#define CONF_TOS_FLOOR         4
-#define CONF_TOS_CEILING       5
-#define CONF_TOS_COHORT                6
-#define CONF_TOS_MINDISP       7
-#define CONF_TOS_MAXDIST       8
-#define        CONF_TOS_MAXHOP         9
-#define        CONF_TOS_BEACON         10
-#define        CONF_TOS_ORPHAN         11
-
-#ifdef OPENSSL
-/*
- * "crypto" modifier keywords
- */
-#define        CONF_CRYPTO_RSA         1       
-#define        CONF_CRYPTO_SIGN        2
-#define CONF_CRYPTO_LEAP       3
-#define CONF_CRYPTO_CERT       4
-#define CONF_CRYPTO_RAND       5
-#define CONF_CRYPTO_KEYS       6
-#define        CONF_CRYPTO_IDENT       7
-#define        CONF_CRYPTO_IFFPAR      8
-#define CONF_CRYPTO_GQPAR      9
-#define CONF_CRYPTO_MVPAR      10
-#define CONF_CRYPTO_PW         11
-#endif /* OPENSSL */
+struct setvar_node {
+    char *data;
+    u_long len;
+    u_short def;
+};
 
-/*
- * Address selection, IPv4 or IPv6
- */
-#define        CONF_ADDR_IPV4          1
-#define        CONF_ADDR_IPV6          2
+struct addr_opts_node {
+    struct address_node *addr;
+    queue *options;
+};
+
+struct sim_node {
+    queue *init_opts;
+    queue *servers;
+};
+
+enum broadcastclienttype {
+    SIMPLE = 1,
+    NOVOLLEY
+};
+
+/* The syntax tree */
+struct config_tree {
+    queue *peers;
+
+    /* Other Modes */
+    int broadcastclient;
+    queue *manycastserver;
+    queue *multicastclient;
+
+    queue *orphan_cmds;
+
+    /* Monitoring Configuration */
+    queue *stats_list;
+    char *stats_dir;
+    queue *filegen_opts;
+
+    /* Access Control Configuration */
+    queue *discard_opts;
+    queue *restrict_opts;
+
+    queue *fudge;
+    queue *tinker;
+    queue *enable_opts;
+    queue *disable_opts;
+    struct auth_node auth;
+
+    queue *logconfig;
+    queue *phone;
+    queue *setvar;
+    queue *ttl;
+    queue *trap;
+    queue *vars;
+
+    struct sim_node *sim_details;
+};
+
+/* Structure to hold a filename, file pointer and positional info */
+struct FILE_INFO {
+    char *fname;               /* Path to the file */
+    FILE *fd;                  /* File Descriptor */
+    int line_no;               /* Line Number in the file being scanned */
+    int col_no;                /* Column Number in the file being scanned */
+    int prev_line_col_no;      /* Col No on the previous line when a '\n' is
+                                  seen */
+};
+
+/* Structure for holding a remote configuration command */
+struct REMOTE_CONFIG_INFO {
+    char buffer[MAXLINE];
+    char err_msg[MAXLINE];
+    int pos;
+    int err_pos;
+    int no_errors;
+};
+
+extern struct REMOTE_CONFIG_INFO remote_config;
+void config_remotely();
+
+#endif
index c48dc59542be50bbc6b6fa217abda55cb3fc2e9c..45014e7ce021b28df1c5e9904a0ff93e4a6b059a 100644 (file)
@@ -1,9 +1,15 @@
-/*
- * ntpsim.h - Prototypes for ntpsim
+/* ntpsim.h
+ *
+ * The header file for the ntp discrete event simulator. 
+ *
+ * Written By: Sachin Kamboj
+ *             University of Delaware
+ *             Newark, DE 19711
+ * Copyright (c) 2006
  */
 
-#ifndef __ntpsim_h
-#define __ntpsim_h
+#ifndef __NTPSIM_H__
+#define __NTPSIM_H__
 
 #include <stdio.h>
 #include <math.h>
 #include "ntp_io.h"
 #include "ntp_stdlib.h"
 
-#define PI 3.1415926535
+/* #include "config.tab.h"*/         /* Bison generated header file for flex */
+#include "ntp_data_structures.h"
 
-/*
- * ntpsim declarations
+/* CONSTANTS */
+
+#define PI 3.1415926535         /* The world's most famous constant */
+#define SIM_TIME 86400         /* end simulation time */
+#define NET_DLY .001            /* network delay */
+#define PROC_DLY .001          /* processing delay */
+#define BEEP_DLY 3600           /* beep interval (s) */
+#define        SLEW    500e-6          /* correction rate (PPM) */
+
+
+/* Discrete Event Queue
+ * --------------------
+ * The NTP simulator is a discrete event simulator.
+ *
+ * Central to this simulator is an event queue which is a priority queue
+ * in which the "priority" is given by the time of arrival of the event.
+ *
+ * A discrete set of events can happen and are stored in the queue to arrive
+ * at a particular time.
  */
+
+/* Possible Discrete Events */
+
 typedef enum {
-        BEEP, CLOCK, TIMER, PACKET
+    BEEP,          /* Event to record simulator stats */
+    CLOCK,         /* Event to advance the clock to the specified time */
+    TIMER,         /* Event that designates a timer interrupt. */
+    PACKET         /* Event that designates arrival of a packet */
 } funcTkn;
 
+
+/* Event information */
+
 typedef struct {
-        double time;
-        union {
-                struct pkt evnt_pkt;
-               struct recvbuf evnt_buf;
-        } buffer;
+    double time;       /* Time at which event occurred */
+    funcTkn function;  /* Type of event that occured */
+    union {
+        struct pkt evnt_pkt;
+        struct recvbuf evnt_buf;
+    } buffer;          /* Other data associated with the event */
 #define ntp_pkt buffer.evnt_pkt
 #define rcv_buf buffer.evnt_buf
-        funcTkn function;
 } Event;
 
-typedef struct List {
-        Event event;
-        struct List *next;
-} *Queue;
-
-typedef struct nde {
-        double time;                   /* simulation time */
-       double  sim_time;               /* end simulation time */
-       double  ntp_time;               /* client disciplined time */
-       double  adj;                    /* remaining time correction */
-       double  slew;                   /* correction slew rate */
-
-       double  clk_time;               /* server time */
-       double  ferr;                   /* frequency errort */
-       double  fnse;                   /* random walk noise */
-       double  ndly;                   /* network delay */
-       double  snse;                   /* phase noise */
-       double  pdly;                   /* processing delay */
-       double  bdly;                   /* beep interval */
-
-       double  last_time;              /* last clock read time */
-        Queue  events;                 /* Node Event Queue */
-       struct recvbuf *rbuflist;       /* Node Receive Buffer */
-} Node;
-
-/*
- * Function prototypes
- */
-int    ntpsim          P((int argc, char *argv[]));
-Event  event           P((double, funcTkn));
-Queue  queue           P((Event, Queue ));
-Node   node            P((void));
-void   push            P((Event, Queue *));
-Event  pop             P((Queue *));
-void   ndbeep          P((Node *, Event));
-void   ndeclk          P((Node *, Event));
-void   ntptmr          P((Node *, Event));
-void   netpkt          P((Node *, Event));
-int    srvr_rply       P((Node *, struct sockaddr_storage *,
-                           struct interface *, struct pkt *));
-double gauss           P((double, double));
-double poisson         P((double, double));
-int    node_clock      P((Node *, double));
-void   abortsim        P((char *));
-
-/*
- * The global Node
- */
-Node ntp_node;
+
+/* Server Script Information */
+
+typedef struct {
+    double duration;
+ // double time_offset;
+    double freq_offset;
+    double wander;
+    double jitter; 
+    double prop_delay;
+    double proc_delay;
+} script_info;   
+
+
+
+/* Server Structures */
+
+typedef struct {
+    double server_time;             /* Server time */
+    struct sockaddr_storage *addr;  /* Server Address */
+    queue *script;                  /* Server Script */
+    script_info *curr_script;       /* Current Script */
+} server_info;
+
+
+/* Simulation control information */
+
+typedef struct Sim_Info {
+    double sim_time;      /* Time in the simulation */
+    double end_time;      /* Time at which simulation needs to be ended */
+    double beep_delay;    /* Delay between simulation "beeps" at which
+                             simulation  stats are recorded. */
+    int num_of_servers;   /* Number of servers in the simulation */
+    server_info *servers; /* Pointer to array of servers */
+} sim_info;
+
+
+/* Local Clock (Client) Variables */
+
+typedef struct Local_Clock_Info {
+    double local_time;     /* Client disciplined time */
+    double adj;            /* Remaining time correction */
+    double slew;           /* Correction Slew Rate */
+    double last_read_time; /* Last time the clock was read */
+} local_clock_info;
+
+extern local_clock_info simclock;   /* Local Clock Variables */
+extern sim_info simulation;         /* Simulation Control Variables */
+
+/* Function Prototypes */
+
+Event    *event                  (double t, funcTkn f);
+void     sim_event_timer         (Event *e);
+int      simulate_server         (struct sockaddr_storage *serv_addr,
+                                 struct interface *inter,
+                                 struct pkt *rpkt);
+void     sim_update_clocks       (Event *e);
+void     sim_event_recv_packet   (Event *e);
+void     sim_event_beep          (Event *e);
+void     abortsim                (char *errmsg);
+double  gauss                   (double, double);
+double  poisson                 (double, double);
+int      yyparse                 (void);
+void     create_server_associations (void);
+
 
 #endif
 
+
+
index 4539b5fec3ce4bf92d31dd6cac6fce90c92952e9..cbb8a74c52157b198531e42d168c7ac2ddf354fc 100644 (file)
 #include "ntp_random.h"
 #include "ntpd.h"              /* for sys_precision */
 
-#ifdef SIM
-# include "ntpsim.h"
-#endif /*SIM */
-
 #ifdef HAVE_SYS_PARAM_H
 # include <sys/param.h>
 #endif
@@ -363,180 +359,10 @@ step_systime(
 /*
  * Clock routines for the simulator - Harish Nair, with help
  */
-/*
- * get_systime - return the system time in NTP timestamp format 
- */
-void
-get_systime(
-        l_fp *now              /* current system time in l_fp */        )
-{
-       /*
-        * To fool the code that determines the local clock precision,
-        * we advance the clock a minimum of 200 nanoseconds on every
-        * clock read. This is appropriate for a typical modern machine
-        * with nanosecond clocks. Note we make no attempt here to
-        * simulate reading error, since the error is so small. This may
-        * change when the need comes to implement picosecond clocks.
-        */
-       if (ntp_node.ntp_time == ntp_node.last_time)
-               ntp_node.ntp_time += 200e-9;
-       ntp_node.last_time = ntp_node.ntp_time;
-       DTOLFP(ntp_node.ntp_time, now);
-}
-/*
- * adj_systime - advance or retard the system clock exactly like the
- * real thng.
- */
-int                            /* always succeeds */
-adj_systime(
-        double now             /* time adjustment (s) */
-        )
-{
-       struct timeval adjtv;   /* new adjustment */
-       double  dtemp;
-       long    ticks;
-       int     isneg = 0;
-
-       /*
-        * Most Unix adjtime() implementations adjust the system clock
-        * in microsecond quanta, but some adjust in 10-ms quanta. We
-        * carefully round the adjustment to the nearest quantum, then
-        * adjust in quanta and keep the residue for later.
-        */
-       dtemp = now + sys_residual;
-       if (dtemp < 0) {
-               isneg = 1;
-               dtemp = -dtemp;
-       }
-       adjtv.tv_sec = (long)dtemp;
-       dtemp -= adjtv.tv_sec;
-       ticks = (long)(dtemp / sys_tick + .5);
-       adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
-       dtemp -= adjtv.tv_usec / 1e6;
-       sys_residual = dtemp;
-
-       /*
-        * Convert to signed seconds and microseconds for the Unix
-        * adjtime() system call. Note we purposely lose the adjtime()
-        * leftover.
-        */
-       if (isneg) {
-               adjtv.tv_sec = -adjtv.tv_sec;
-               adjtv.tv_usec = -adjtv.tv_usec;
-               sys_residual = -sys_residual;
-       }
-       ntp_node.adj = now;
-       return (1);
-}
-/*
- * step_systime - step the system clock. We are religious here.
- */
-int                            /* always succeeds */
-step_systime(
-        double now             /* step adjustment (s) */
-        )
-{
-#ifdef DEBUG
-       if (debug)
-               printf("step_systime: time %.6f adj %.6f\n",
-                  ntp_node.ntp_time, now);
-#endif
-       ntp_node.ntp_time += now;
-       return (1);
-}
-
-/*
- * node_clock - update the clocks
- */
-int                            /* always succeeds */
-node_clock(
-       Node *n,                /* global node pointer */
-       double t                /* node time */
-       )
-{
-       double  dtemp;
-
-       /*
-        * Advance client clock (ntp_time). Advance server clock
-        * (clk_time) adjusted for systematic and random frequency
-        * errors. The random error is a random walk computed as the
-        * integral of samples from a Gaussian distribution.
-        */
-       dtemp = t - n->ntp_time;
-       n->time = t;
-       n->ntp_time += dtemp;
-       n->ferr += gauss(0, dtemp * n->fnse);
-       n->clk_time += dtemp * (1 + n->ferr);
-
-       /*
-        * Perform the adjtime() function. If the adjustment completed
-        * in the previous interval, amortize the entire amount; if not,
-        * carry the leftover to the next interval.
-        */
-       dtemp *= n->slew;
-       if (dtemp < fabs(n->adj)) {
-               if (n->adj < 0) {
-                       n->adj += dtemp;
-                       n->ntp_time -= dtemp;
-               } else {
-                       n->adj -= dtemp;
-                       n->ntp_time += dtemp;
-               }
-       } else {
-               n->ntp_time += n->adj;
-               n->adj = 0;
-       }
-        return (0);
-}
-
-/*
- * gauss() - returns samples from a gaussion distribution
- */
-double                         /* Gaussian sample */
-gauss(
-       double m,               /* sample mean */
-       double s                /* sample standard deviation (sigma) */
-       )
-{
-        double q1, q2;
-
-       /*
-        * Roll a sample from a Gaussian distribution with mean m and
-        * standard deviation s. For m = 0, s = 1, mean(y) = 0,
-        * std(y) = 1.
-        */
-       if (s == 0)
-               return (m);
-        while ((q1 = drand48()) == 0);
-        q2 = drand48();
-        return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
-}
 
-/*
- * poisson() - returns samples from a network delay distribution
+/* SK: 
+ * The code that used to be here has been moved to ntpsim.c,
+ * where, IMHO, it rightfully belonged.
  */
-double                         /* delay sample (s) */
-poisson(
-       double m,               /* fixed propagation delay (s) */
-       double s                /* exponential parameter (mu) */
-       )
-{
-        double q1;
 
-       /*
-        * Roll a sample from a composite distribution with propagation
-        * delay m and exponential distribution time with parameter s.
-        * For m = 0, s = 1, mean(y) = std(y) = 1.
-        */
-       if (s == 0)
-               return (m);
-        while ((q1 = drand48()) == 0);
-        return (m - s * log(q1 * s));
-}
 #endif /* SIM */
index c71167ec1bb6a69b34b03897b8dabf89d60fcab6..d01912299d78aab7be25ac61abd16189d496e6d6 100644 (file)
@@ -10,9 +10,7 @@
 #include "ntp_cmdargs.h"
 
 #ifdef SIM
-# include "ntpsim.h"
-# include "ntpdsim-opts.h"
-# define OPTSTRUCT     ntpdsimOptions
+/* SK: removed */
 #else
 # include "ntpd-opts.h"
 # define OPTSTRUCT     ntpdOptions
@@ -195,32 +193,11 @@ getCmdOpts(
                }
        }
 #ifdef SIM
-       if (HAVE_OPT( SIMBROADCASTDELAY ))
-               sscanf(OPT_ARG( SIMBROADCASTDELAY ), "%lf", &ntp_node.bdly);
 
-       if (HAVE_OPT( PHASENOISE ))
-               sscanf(OPT_ARG( PHASENOISE ), "%lf", &ntp_node.snse);
-
-       if (HAVE_OPT( SIMSLEW ))
-               sscanf(OPT_ARG( SIMSLEW ), "%lf", &ntp_node.slew);
-
-       if (HAVE_OPT( SERVERTIME ))
-               sscanf(OPT_ARG( SERVERTIME ), "%lf", &ntp_node.clk_time);
-
-       if (HAVE_OPT( ENDSIMTIME ))
-               sscanf(OPT_ARG( ENDSIMTIME ), "%lf", &ntp_node.sim_time);
-
-       if (HAVE_OPT( FREQERR ))
-               sscanf(OPT_ARG( FREQERR ), "%lf", &ntp_node.ferr);
-
-       if (HAVE_OPT( WALKNOISE ))
-               sscanf(OPT_ARG( WALKNOISE ), "%lf", &ntp_node.fnse);
-
-       if (HAVE_OPT( NDELAY ))
-               sscanf(OPT_ARG( NDELAY ), "%lf", &ntp_node.ndly);
-
-       if (HAVE_OPT( PDELAY ))
-               sscanf(OPT_ARG( PDELAY ), "%lf", &ntp_node.pdly);
+       /* SK:
+        * The simulator no longer takes any command line arguments. Hence,
+        * all the code that was here has been removed.
+        */
 
 #endif /* SIM */
 
index d9bbc34b349eb6f0a8977f0b420a3d5fe07275a5..d6e0617c5a6a989c0c7c20ca71b7eb93478584e4 100644 (file)
@@ -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
@@ -15,6 +23,7 @@
 #include "ntp_refclock.h"
 #include "ntp_filegen.h"
 #include "ntp_stdlib.h"
+#include "ntpsim.h"
 #include <ntp_random.h>
 #include <isc/net.h>
 #include <isc/result.h>
@@ -47,247 +56,10 @@ HANDLE ResolverThreadHandle = NULL;
 #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 },
-       { "codec",              CONF_CLOCK_CODEC },
-       { "",                   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 }
-};
+#include "ntp_data_structures.h"
 
-#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 */
+extern int priority_done;
 
-/*
- * 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
@@ -322,10 +94,7 @@ static struct masks logcfg_item[] = {
        { (char *)0,    0 }
 };
 
-/*
- * Limits on things
- */
-#define MAXTOKENS      20      /* 20 tokens on line */
+/* Limits */
 #define MAXLINE                1024    /* maximum length of line */
 #define MAXPHONE       10      /* maximum number of phone strings */
 #define MAXPPS         20      /* maximum length of PPS device string */
@@ -391,1523 +160,1855 @@ struct netinfo_config_state {
 };
 #endif
 
-/*
- * Function prototypes
- */
-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 *));
-#endif
-static int gettokens P((FILE *, char *, char **, int *));
-static int matchkey P((char *, struct keyword *, int));
+struct FILE_INFO *fp[MAXINCLUDELEVEL];
+int curr_include_level;      /* The current include level */
+struct config_tree my_config;/* Root of the configuration tree */
+struct FILE_INFO *ip_file;   /* Pointer to the configuration file stream */
+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 newline_is_special = 1; */ /* A boolean flag, which when set, implies that
+                                newlines are special characters that need to
+                                be returned as tokens */
+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
+                              */
+
+extern int sys_maxclock;
+
+/* FUNCTION PROTOTYPES */
+
+struct FILE_INFO *F_OPEN(const char *path, const char *mode);
+int FGETC(struct FILE_INFO *stream);
+int UNGETC(int ch, struct FILE_INFO *stream);
+int FCLOSE(struct FILE_INFO *stream);
+
+int get_next_char();
+void push_back_char(int ch);
+
+static struct state *create_states(char *keyword,int token,int expect_string, struct state *pre_state);
+//static struct state *create_keyword_scanner(struct key_tok *keyword_list);
+static void delete_keyword_scanner(struct state *key_scanner);
+void print_keyword_scanner(struct state *key_scanner, int pos);
+int yylex(void);
+
+void yyerror (char *msg);
+static int get_flags_from_list(queue *flag_list);
+static void init_auth_node(void);
+static void init_syntax_tree(void);
+queue *enqueue_in_new_queue(void *my_node);
+struct attr_val *create_attr_dval(int attr, double value);
+struct attr_val *create_attr_ival(int attr, int value);
+struct attr_val *create_attr_sval(int attr, char *s);
+struct attr_val *create_attr_pval(int attr, void *s);
+int *create_ival(int val);
+double *create_dval(double val);
+void **create_pval(void *val);
+struct address_node *create_address_node(char *addr, int type);
+struct peer_node *create_peer_node(int hmode, struct address_node *addr, queue *options);
+struct filegen_node *create_filegen_node(void **name, queue *options);
+struct restrict_node *create_restrict_node(struct address_node *addr,struct address_node *mask,queue *flags, int line_no);
+void destroy_restrict_node(struct restrict_node *my_node);
+struct setvar_node *create_setvar_node(char *var, char *val, u_short def);
+struct addr_opts_node *create_addr_opts_node(struct address_node *addr, queue *options);
+script_info *create_sim_script_info(double duration, queue *script_queue);
+static struct sockaddr_storage *get_next_address(struct address_node *addr);
+server_info *create_sim_server(struct address_node *addr, double server_offset, queue *script);
+struct sim_node *create_sim_node(queue *init_opts, queue *servers);
+
+static void config_other_modes(void);
+static void config_auth(void);
+static void config_tos(void);
+static void config_monitor(void);
+static void config_access(void);
+static void config_tinker(void);
+static void config_system_opts(void);
+static void config_logconfig(void);
+static void config_phone(void);
+static void config_setvar(void);
+static void config_ttl(void);
+static void config_trap(void);
+static void config_fudge(void);
+static void config_vars(void);
+static int is_sane_resolved_address(struct sockaddr_storage peeraddr, int hmode);
+static int get_correct_host_mode(int hmode);
+static void config_peers(void);
+static void config_sim(void);
+static void config_ntpd(void);
+static void config_ntpdsim(void);
+void getconfig(int argc,char *argv[]);
 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
- */
-static unsigned long
-get_pfxmatch(
-       char ** s,
-       struct masks *m
-       )
-{
-       while (m->name) {
-               if (strncmp(*s, m->name, strlen(m->name)) == 0) {
-                       *s += strlen(m->name);
-                       return m->mask;
-               } else {
-                       m++;
-               }
-       }
-       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++;
-               }
-       }
-       return 0;
-}
 
-/*
- * get_logmask - build bitmask for ntp_syslogmask
- */
-static unsigned long
-get_logmask(
-       char *s
-       )
-{
-       char *t;
-       unsigned long offset;
-       unsigned long mask;
+static unsigned long get_pfxmatch(char **s,struct masks *m);
+static unsigned long get_match(char *s,struct masks *m);
+static unsigned long get_logmask(char *s);
+static int getnetnum(const char *num,struct sockaddr_storage *addr,int complain,enum gnn_type a_type);
+static int get_multiple_netnums(const char *num, struct sockaddr_storage *addr, struct addrinfo **res, int complain, enum gnn_type a_type);
+static void save_resolve(char *name,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);
 
-       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);
-
-       return 0;
-}
 
 
-/*
- * getconfig - get command line options and read the configuration file
+/* INCLUSION OF CODE FOR THE DATA STRUCTURES
+ * -----------------------------------------
  */
-void
-getconfig(
-       int argc,
-       char *argv[]
-       )
-{
-       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;
-
-       /*
-        * Initialize, initialize
-        */
-       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;
-
-       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
-        */
-       (void) sprintf(line, "daemon_version=\"%s\"", Version);
-       set_sys_var(line, strlen(line)+1, RO);
+#include "ntp_data_structures.c"
 
-       /*
-        * 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);
-
-       /*
-        * Initialize the loop.
-        */
-       loop_config(LOOP_DRIFTINIT, 0.);
-
-       getCmdOpts(argc, argv);
-
-       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 */
-
-               if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
-
-                       /*
-                        * Broadcast clients can sometimes run without
-                        * a configuration file.
-                        */
-
-                       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;
-               }
-#else  /* not SYS_WINNT */
-               return;
-#endif /* not SYS_WINNT */
-       }
-
-       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 (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;
-
-                       if (ntokens < 2) {
-                               msyslog(LOG_ERR,
-                                       "No address for %s, line ignored",
-                                       tokens[0]);
-                               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++;
-                               break;
-                       case CONF_ADDR_IPV6:
-                               peeraddr.ss_family = AF_INET6;
-                               istart++;
-                               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));
-                                               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));
-                                               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;
-                                       }
-                               }
-                       }
-                       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:
-                                   peerflags |= FLAG_DYNAMIC;
-                                   break;
-
-#ifdef OPENSSL
-                               case CONF_MOD_SKEY:
-                                   peerflags |= FLAG_SKEY |
-                                       FLAG_AUTHENABLE;
-                                   break;
-#endif /* OPENSSL */
-
-                               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;
-
-                               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;
-                       }
-                       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);
-                       }
-                       break;
-
-                   case CONFIG_DRIFTFILE:
-                       if (ntokens >= 2)
-                           stats_config(STATS_FREQ_FILE, tokens[1]);
-                       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;
-                       }
-                       break;
-       
-                   case CONFIG_PIDFILE:
-                       if (ntokens >= 2)
-                           stats_config(STATS_PID_FILE, tokens[1]);
-                       else
-                           stats_config(STATS_PID_FILE, (char *)0);
-                       break;
-
-                   case CONFIG_END:
-                       for ( i = 0; i <= includelevel; i++ ) {
-                               fclose(fp[i]);
-                       }
-                       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;
-                       break;
-
-                   case CONFIG_LOGFILE:
-                       if (ntokens >= 2) {
-                               FILE *new_file;
-
-                               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);
+/* INCLUSION OF BISON GENERATED FILE
+ * ---------------------------------
+ */
+#include "ntp_config.tab.c"
 
-                                       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:
-                                       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]);
-#endif
-                       }
-                       break;
-
-                   case CONFIG_BROADCASTCLIENT:
-                       if (ntokens == 1) {
-                               proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
-                       } else {
-                               proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
-                       }
-                       break;
+/* FUNCTIONS FOR INITIALIZATION
+ * ----------------------------
+ */
 
-                   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;
-                       break;
+static int get_flags_from_list(queue *flag_list)
+{
+    int flags = 0;
+    struct attr_val *curr_flag;
+    
+    while (!empty(flag_list)) {
+        curr_flag = (struct attr_val *) dequeue(flag_list);
+        flags |= curr_flag->value.i;
+        free_node(curr_flag);
+    }
+    return flags;
+}
 
-                   case CONFIG_KEYS:
-                       if (ntokens >= 2) {
-                               getauthkeys(tokens[1]);
-                       }
-                       break;
+static void init_auth_node()
+{
+    my_config.auth.autokey = 0;
+    my_config.auth.control_key = 0;
+    my_config.auth.crypto_cmd_list = NULL;
+    my_config.auth.keys = NULL;
+    my_config.auth.keysdir = NULL;
+    my_config.auth.requested_key = 0;
+    my_config.auth.revoke = 0;
+    my_config.auth.trusted_key_list = NULL;
+}
 
-                   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]);
-                       break;
+static void init_syntax_tree()
+{
+    my_config.peers = create_queue();
+    my_config.orphan_cmds = create_queue();
+    
+    my_config.broadcastclient = 0;
+    my_config.manycastserver = create_queue();
+    my_config.multicastclient = create_queue();
+
+    my_config.stats_list = create_queue();
+    my_config.stats_dir = NULL;
+    my_config.filegen_opts = create_queue();
+
+    my_config.discard_opts = create_queue();
+    my_config.restrict_opts = create_queue();
+
+    my_config.enable_opts = create_queue();
+    my_config.disable_opts = create_queue();
+    my_config.tinker = create_queue();
+    my_config.fudge = create_queue();
+
+    my_config.logconfig = create_queue();
+    my_config.phone = create_queue();
+    my_config.setvar = create_queue();
+    my_config.ttl = create_queue();
+    my_config.trap = create_queue();
+    my_config.vars = create_queue();
+    my_config.sim_details = NULL;
+    init_auth_node();
+}
 
-                   case CONFIG_TINKER:
-                       for (i = 1; i < ntokens; i++) {
-                           int temp;
-                           double ftemp;
+/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 
+ * -----------------------------------------------
+ */
 
-                           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) {
+queue *enqueue_in_new_queue(void *my_node)
+{ 
+    queue *my_queue = create_queue();
+    enqueue(my_queue, my_node);
+    return my_queue;
+}
 
-                           case CONF_CLOCK_MAX:
-                                loop_config(LOOP_MAX, ftemp);
-                               break;
+struct attr_val *create_attr_dval(int attr, double value)
+{
+    struct attr_val *my_val;
+    my_val = (struct attr_val *)
+        get_node(sizeof(struct attr_val));
+    my_val->attr = attr;
+    my_val->value.d = value;
+    my_val->type = T_Double;
+    return my_val;
+}
 
-                           case CONF_CLOCK_PANIC:
-                               loop_config(LOOP_PANIC, ftemp);
-                               break;
+struct attr_val *create_attr_ival(int attr, int value)
+{
+    struct attr_val *my_val;
+    my_val = (struct attr_val *)
+        get_node(sizeof(struct attr_val));
+    my_val->attr = attr;
+    my_val->value.i = value;
+    my_val->type = T_Integer;
+    return my_val;
+}
 
-                           case CONF_CLOCK_PHI:
-                               loop_config(LOOP_PHI, ftemp);
-                               break;
+struct attr_val *create_attr_sval(int attr, char *s)
+{
+    struct attr_val *my_val;
+    my_val = (struct attr_val *)
+        get_node(sizeof(struct attr_val));
+    my_val->attr = attr;
+    my_val->value.s = s;
+    my_val->type = T_String;
+    return my_val;
+}
 
-                           case CONF_CLOCK_MINSTEP:
-                               loop_config(LOOP_MINSTEP, ftemp);
-                               break;
+struct attr_val *create_attr_pval(int attr, void *p)
+{
+    struct attr_val *my_val;
+    my_val = (struct attr_val *)
+        get_node(sizeof(struct attr_val));
+    my_val->attr = attr;
+    my_val->value.p = p;
+    my_val->type = T_Void;
+    return my_val;
+}
 
-                           case CONF_CLOCK_ALLAN:
-                               loop_config(LOOP_ALLAN, ftemp);
-                               break;
+int *create_ival(int val)
+{
+    int *p = (int *)get_node(sizeof(int));
+    *p = val;
+    return p;
+}
 
-                           case CONF_CLOCK_HUFFPUFF:
-                               loop_config(LOOP_HUFFPUFF, ftemp);
-                               break;
+double *create_dval(double val)
+{
+    double *p = (double *) get_node(sizeof(int));
+    *p = val;
+    return p;
+}
 
-                           case CONF_CLOCK_FREQ:
-                               loop_config(LOOP_FREQ, ftemp);
+void **create_pval(void *val)
+{
+    void **p = (void **) get_node(sizeof(void *));
+    *p = val;
+    return p;
+}
 
-                           case CONF_CLOCK_CODEC:
-                               loop_config(LOOP_CODEC, ftemp);
-                               break;  
-                           }
-                       }
-                       break;
+struct address_node *create_address_node(char *addr, int type)
+{
+    struct address_node *my_node = (struct address_node *) 
+        get_node(sizeof(struct address_node));
+    my_node->address = addr;
+    my_node->type = type;
+    return my_node;
+}
 
-                   case CONFIG_TOS:
-                       for (i = 1; i < ntokens; i++) {
-                           int temp;
-                           double ftemp;
+struct peer_node *create_peer_node(int hmode, struct address_node *addr, queue *options)
+{
+    struct peer_node* my_node;
+    int errflag = 0;
+
+    my_node = (struct peer_node *)
+        get_node(sizeof(struct peer_node));
+
+    /* Initialze node values to default */
+    my_node->minpoll = NTP_MINDPOLL;
+    my_node->maxpoll = NTP_MAXDPOLL;
+    my_node->ttl = 0;
+    my_node->peerversion = NTP_VERSION;
+    my_node->peerkey = 0;
+    my_node->peerflags = 0;
+
+    /* Now set the node to the read values */
+    my_node->host_mode = hmode;
+    my_node->addr = addr;
+    
+    while (options && !empty(options)) {
+        struct attr_val *my_val = dequeue(options);
+
+        /* Check the kind of option being set */
+        switch(my_val->attr) { 
+        case T_Minpoll:
+            if (my_val->value.i < NTP_MINPOLL) {
+                msyslog(LOG_INFO,
+                        "minpoll: provided value (%d) is below minimum (%d)",
+                        my_val->value.i, NTP_MINPOLL);
+                my_node->minpoll = NTP_MINPOLL;
+            }
+            else
+                my_node->minpoll = my_val->value.i;
+            break;
+        case T_Maxpoll:
+            if (my_val->value.i > NTP_MAXPOLL) {
+                msyslog(LOG_INFO,
+                        "maxpoll: provided value (%d) is above maximum (%d)",
+                         my_val->value.i, NTP_MAXPOLL);
+                my_node->maxpoll = NTP_MAXPOLL;
+            }
+            else
+                my_node->maxpoll = my_val->value.i;
+            break;
+        case T_Ttl:
+            if (my_node->ttl >= MAX_TTL) {
+                msyslog(LOG_ERR, "ttl: invalid argument");
+                errflag = 1;
+            } 
+            else
+                my_node->ttl = my_val->value.i;
+            break;
+        case T_Mode:
+            my_node->ttl = my_val->value.i;
+            break;
+        case T_Key:
+            my_node->peerkey = my_val->value.i;
+            my_node->peerflags |=  FLAG_AUTHENABLE;
+            break;
+        case T_Version:
+            my_node->peerversion = my_val->value.i;
+            break;
+        case T_Flag:
+            my_node->peerflags |= my_val->value.i;
+            break;
+        }
+        free_node(my_val);
+    }
+    if (options)
+        destroy_queue(options);
+    
+    /* Check if errors were reported. If yes, ignore the node */
+    if (errflag) {
+        free_node(my_node);
+        return NULL;
+    }
+    return my_node;
+}
 
-                           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) {
+struct filegen_node *create_filegen_node(
+    void **name, 
+    queue *options)
+{
+    struct filegen_node *my_node = (struct filegen_node *)
+        get_node(sizeof(struct filegen_node));
 
-                           case CONF_TOS_MINCLOCK:
-                               proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
-                               break;
+    my_node->name = (char *) *name;
+    free_node(name);
 
-                           case CONF_TOS_MAXCLOCK:
-                               proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
-                               break;
+    my_node->options = options;
+    return my_node;
+}
 
-                           case CONF_TOS_MINSANE:
-                               proto_config(PROTO_MINSANE, 0, ftemp, NULL);
-                               break;
 
-                           case CONF_TOS_FLOOR:
-                               proto_config(PROTO_FLOOR, 0, ftemp, NULL);
-                               break;
+struct restrict_node *create_restrict_node(
+    struct address_node *addr,
+    struct address_node *mask,
+    queue *flags,
+    int line_no)
+{
+    struct restrict_node *my_node = (struct restrict_node *)
+        get_node(sizeof(struct restrict_node));
+    my_node->addr = addr;
+    my_node->mask = mask;
+    my_node->flags = flags;
+    my_node->line_no = line_no;
+    return my_node;
+}
 
-                           case CONF_TOS_CEILING:
-                               proto_config(PROTO_CEILING, 0, ftemp, NULL);
-                               break;
+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)
+        free_node(my_node->addr);
+    if (my_node->mask)
+        free_node(my_node->mask);
+    if (my_node->flags)
+        destroy_queue(my_node->flags);
+    free_node(my_node);
+}
 
-                           case CONF_TOS_COHORT:
-                               proto_config(PROTO_COHORT, 0, ftemp, NULL);
-                               break;
 
-                           case CONF_TOS_MINDISP:
-                               proto_config(PROTO_MINDISP, 0, ftemp, NULL);
-                               break;
+struct setvar_node *create_setvar_node(char *var, char *val, u_short def)
+{
+    int len1 = strlen(var);
+    int len2 = strlen(val);
+    
+    char *s = (char *) emalloc(len1 + len2 + 2);
+    struct setvar_node *my_node;
+    
+    /* Copy the var = val to s */
+    strcpy(s, var);
+    s[len1] = '=';
+    strcpy(&s[len1 + 1], val);
+    s[len1+len2+1] = '\0';
+    
+    free(var);
+    free(val);
+
+    /* Now store the string and its length into a setvar_node */
+    my_node = (struct setvar_node *)
+        get_node(sizeof(struct setvar_node));
+    my_node->data = s;
+    my_node->len = len1 + len2 + 2;
+    my_node->def = def;
+    return my_node;
+}
 
-                           case CONF_TOS_MAXDIST:
-                               proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
-                               break;
+struct addr_opts_node *create_addr_opts_node(
+    struct address_node *addr, 
+    queue *options)
+{
+    struct addr_opts_node *my_node = (struct addr_opts_node *)
+        get_node(sizeof(struct addr_opts_node));
+    my_node->addr = addr;
+    my_node->options = options;
+    return my_node;
+}
 
-                           case CONF_TOS_MAXHOP:
-                               proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
-                               break;
+script_info *create_sim_script_info(double duration, queue *script_queue)
+{
+    script_info *my_info;
+    struct attr_val *my_attr_val;
+    my_info = (script_info *)get_node(sizeof(script_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 */
+    while (!empty(script_queue)) {
+        my_attr_val = (struct attr_val *) dequeue(script_queue);
+        
+        /* Set the desired value */
+        switch(my_attr_val->attr) {
+        case T_Freq_Offset:
+            my_info->freq_offset = my_attr_val->value.d;
+            break;
+        case T_Wander:
+            my_info->wander = my_attr_val->value.d;
+            break;
+        case T_Jitter:
+            my_info->jitter = my_attr_val->value.d;
+            break;
+        case T_Prop_Delay:
+            my_info->prop_delay = my_attr_val->value.d;
+            break;
+        case T_Proc_Delay:
+            my_info->proc_delay = my_attr_val->value.d;
+            break;
+        default:
+            yyerror("ERROR!! Invalid script info in file\n");
+            break;
+        }
+        free_node(my_attr_val);
+    }
+    destroy_queue(script_queue);
+    return (my_info);
+}
 
-                           case CONF_TOS_ORPHAN:
-                               proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
-                               break;
 
-                           case CONF_TOS_BEACON:
-                               proto_config(PROTO_BEACON, 0, ftemp, NULL);
-                               break;
-                           }
-                       }
-                       break;
+#define ADDR_LENGTH 16 + 1
 
-                   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;
-                       }
-                       break;
+static struct sockaddr_storage *get_next_address(struct address_node *addr)
+{
+    static char *addr_prefix = "192.168.0.";
+    static int curr_addr_no = 1;
+    char addr_string[ADDR_LENGTH];
+
+    struct sockaddr_storage *final_addr = (struct sockaddr_storage *) 
+        malloc(sizeof(struct sockaddr_storage));
+    struct addrinfo *ptr;
+    int retval;
+    
+    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 == 0) {
+        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;
+}
+    
 
-                   case CONFIG_DISCARD:
-                       for (i = 1; i < ntokens; i++) {
-                           int temp;
+server_info *create_sim_server(struct address_node *addr, double server_offset, queue *script)
+{
+    server_info *my_info;
+    my_info = (server_info *) get_node(sizeof(server_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;
+}
 
-                           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;
+struct sim_node *create_sim_node(queue *init_opts, queue *servers)
+{
+    struct sim_node *my_node = (struct sim_node *) 
+        get_node(sizeof(struct sim_node));
+    my_node->init_opts = init_opts;
+    my_node->servers = servers;
+    return my_node;
+}
 
-                           case CONF_DISCARD_MINIMUM:
-                               res_min_interval = atoi(tokens[i]);
-                               break;
 
-                           case CONF_DISCARD_MONITOR:
-                               mon_age = atoi(tokens[i]);
-                               break;
+/* INCLUSION OF SCANNER FILE 
+ * -------------------------
+ */
 
-                           default:
-                               msyslog(LOG_ERR,
-                                   "discard: unknown keyword");
-                               break;
-                           }
-                       }
-                       break;
+#include "ntp_scanner.c"
+
+struct key_tok keyword_list[] = {
+    { "automax",       T_Automax,         NO_ARG },
+    { "broadcast",     T_Broadcast,       SINGLE_ARG },
+    { "broadcastclient",T_Broadcastclient, NO_ARG },
+    { "broadcastdelay",        T_Broadcastdelay,  NO_ARG },
+    { "calldelay",     T_Calldelay,       NO_ARG },
+    { "disable",       T_Disable,         NO_ARG },
+    { "driftfile",     T_Driftfile,       SINGLE_ARG },
+    { "enable",                T_Enable,          NO_ARG },
+    { "end",           T_End,             NO_ARG },
+    { "filegen",       T_Filegen,         NO_ARG },
+    { "fudge",         T_Fudge,           SINGLE_ARG },
+    { "includefile",   T_Includefile,     SINGLE_ARG },
+    { "logconfig",     T_Logconfig,       SINGLE_ARG },
+    { "logfile",       T_Logfile,         SINGLE_ARG },
+    { "manycastclient",        T_Manycastclient,  SINGLE_ARG },
+    { "manycastserver", T_Manycastserver,  MULTIPLE_ARG },
+    { "multicastclient",T_Multicastclient, MULTIPLE_ARG },
+    { "peer",          T_Peer,            SINGLE_ARG },
+    { "phone",         T_Phone,           MULTIPLE_ARG },
+    { "pidfile",       T_Pidfile,         SINGLE_ARG },
+    { "pool",           T_Pool,            SINGLE_ARG },
+    { "discard",       T_Discard,         NO_ARG },
+    { "restrict",      T_Restrict,        NO_ARG },    
+    { "server",                T_Server,          SINGLE_ARG },
+    { "setvar",                T_Setvar,          NO_ARG },
+    { "statistics",    T_Statistics,      NO_ARG },
+    { "statsdir",      T_Statsdir,        SINGLE_ARG },
+    { "tick",          T_Tick,            NO_ARG },
+    { "tinker",                T_Tinker,          NO_ARG },
+    { "tos",           T_Tos,             NO_ARG },
+    { "trap",          T_Trap,            SINGLE_ARG },
+    { "default",        T_Default,         NO_ARG },
+
+/* authentication_command */
+    { "controlkey",    T_ControlKey,      NO_ARG },
+    { "crypto",                T_Crypto,          NO_ARG },
+    { "keys",          T_Keys,            SINGLE_ARG },
+    { "keysdir",       T_Keysdir,         SINGLE_ARG },
+    { "requestkey",    T_Requestkey,      NO_ARG },
+    { "revoke",                T_Revoke,          NO_ARG },
+    { "trustedkey",    T_Trustedkey,      NO_ARG },
+/* option */
+    { "autokey",        T_Autokey,         NO_ARG },
+    { "burst",         T_Burst,           NO_ARG },
+    { "iburst",                T_Iburst,          NO_ARG },
+    { "key",            T_Key,             NO_ARG },
+    { "maxpoll",       T_Maxpoll,         NO_ARG },
+    { "minpoll",       T_Minpoll,         NO_ARG },
+    { "mode",          T_Mode,            NO_ARG },     
+    { "noselect",      T_Noselect,        NO_ARG },
+    { "preempt",       T_Preempt,         NO_ARG },
+    { "true",          T_True,            NO_ARG },
+    { "prefer",                T_Prefer,          NO_ARG },
+    { "ttl",           T_Ttl,             NO_ARG },      
+    { "version",       T_Version,         NO_ARG },
+/* crypto_command */
+    { "cert",          T_Cert,            SINGLE_ARG },
+    { "gqpar",         T_Gqpar,           SINGLE_ARG },
+    { "host",          T_Host,            SINGLE_ARG },
+    { "ident",         T_Ident,           SINGLE_ARG },
+    { "iffpar",                T_Iffpar,          SINGLE_ARG },
+    { "leap",          T_Leap,            SINGLE_ARG },
+    { "mvpar",         T_Mvpar,           SINGLE_ARG },
+    { "pw",            T_Pw,              SINGLE_ARG },
+    { "randfile",      T_RandFile,        SINGLE_ARG },
+    { "sign",          T_Sign,            SINGLE_ARG },
+/*** MONITORING COMMANDS ***/
+/* stat */
+    { "clockstats",     T_Clockstats,      NO_ARG },
+    { "cryptostats",   T_Cryptostats,     NO_ARG },
+    { "loopstats",      T_Loopstats,       NO_ARG },
+    { "peerstats",      T_Peerstats,       NO_ARG },
+    { "rawstats",      T_Rawstats,        NO_ARG },
+    { "sysstats",      T_Sysstats,        NO_ARG },
+/* filegen_option */
+    { "disable",       T_Disable,         NO_ARG },
+    { "enable",                T_Enable,          NO_ARG },
+    { "file",          T_File,            SINGLE_ARG },
+    { "link",          T_Link,            NO_ARG },
+    { "nolink",                T_Nolink,          NO_ARG },
+    { "type",          T_Type,            NO_ARG },
+/* filegen_type */
+    { "age",           T_Age,             NO_ARG },
+    { "day",           T_Day,             NO_ARG },
+    { "month",         T_Month,           NO_ARG },
+    { "none",          T_None,            NO_ARG },
+    { "pid",           T_Pid,             NO_ARG },
+    { "week",          T_Week,            NO_ARG },
+    { "year",          T_Year,            NO_ARG },
+/*** ORPHAN MODE COMMANDS ***/
+/* tos_option */
+    { "minclock",      T_Minclock,        NO_ARG },
+    { "maxclock",      T_Maxclock,        NO_ARG },
+    { "minsane",       T_Minsane,         NO_ARG },
+    { "floor",         T_Floor,           NO_ARG },
+    { "ceiling",       T_Ceiling,         NO_ARG },
+    { "cohort",                T_Cohort,          NO_ARG },
+    { "mindist",       T_Mindist,         NO_ARG },
+    { "maxdist",       T_Maxdist,         NO_ARG },
+    { "maxhop",                T_Maxhop,          NO_ARG },
+    { "beacon",                T_Beacon,          NO_ARG },
+    { "orphan",                T_Orphan,          NO_ARG },
+/* access_control_flag */
+    { "ignore",                T_Ignore,          NO_ARG },
+    { "limited",       T_Limited,         NO_ARG },
+    { "kod",           T_Kod,             NO_ARG },
+    { "lowpriotrap",   T_Lowpriotrap,     NO_ARG },
+    { "mask",          T_Mask,            NO_ARG },
+    { "nomodify",      T_Nomodify,        NO_ARG },
+    { "nopeer",                T_Nopeer,          NO_ARG },
+    { "noquery",       T_Noquery,         NO_ARG },
+    { "noserve",       T_Noserve,         NO_ARG },
+    { "notrap",                T_Notrap,          NO_ARG },
+    { "notrust",       T_Notrust,         NO_ARG },
+    { "ntpport",       T_Ntpport,         NO_ARG },
+    { "version",       T_Version,         NO_ARG },
+/* discard_option */
+    { "average",       T_Average,         NO_ARG },
+    { "minimum",       T_Minimum,         NO_ARG },
+    { "monitor",       T_Monitor,         NO_ARG },
+/* fudge_factor */
+    { "flag1",         T_Flag1,           NO_ARG },
+    { "flag2",         T_Flag2,           NO_ARG },
+    { "flag3",         T_Flag3,           NO_ARG },
+    { "flag4",         T_Flag4,           NO_ARG },
+    { "refid",         T_Refid,           SINGLE_ARG },
+    { "stratum",       T_Stratum,         NO_ARG },
+    { "time1",         T_Time1,           NO_ARG },
+    { "time2",         T_Time2,           NO_ARG },
+/* system_option */
+    { "auth",          T_Auth,            NO_ARG },
+    { "bclient",       T_Bclient,         NO_ARG },
+    { "calibrate",     T_Calibrate,       NO_ARG },
+    { "kernel",                T_Kernel,          NO_ARG },
+    { "monitor",       T_Monitor,         NO_ARG },
+    { "ntp",           T_Ntp,             NO_ARG },
+    { "stats",         T_Stats,           NO_ARG },
+/* tinker_option */
+    { "step",          T_Step,            NO_ARG },
+    { "panic",         T_Panic,           NO_ARG },
+    { "dispersion",    T_Dispersion,      NO_ARG },
+    { "stepout",       T_Stepout,         NO_ARG },
+    { "allan",         T_Allan,           NO_ARG },
+    { "huffpuff",      T_Huffpuff,        NO_ARG },
+    { "freq",          T_Freq,            NO_ARG },
+/* miscellaneous_command */
+    { "port",          T_Port,            NO_ARG },
+    { "interface",     T_Interface,       SINGLE_ARG },
+/* simulator commands */
+    { "simulate",       T_Simulate,        NO_ARG },
+    { "simulation_duration", T_Sim_Duration, NO_ARG },
+    { "beep_delay",     T_Beep_Delay,      NO_ARG },
+    { "duration",       T_Duration,        NO_ARG },
+    { "server_offset",  T_Server_Offset,   NO_ARG },
+    { "freq_offset",    T_Freq_Offset,     NO_ARG },
+    { "wander",         T_Wander,          NO_ARG },
+    { "jitter",         T_Jitter,          NO_ARG },
+    { "prop_delay",     T_Prop_Delay,      NO_ARG },
+    { "proc_delay",     T_Proc_Delay,      NO_ARG }, 
+    { NULL, 0, 0}
+};
 
-#ifdef OPENSSL
-                   case CONFIG_REVOKE:
-                       if (ntokens >= 2)
-                           sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
-                       break;
 
-                   case CONFIG_AUTOMAX:
-                       if (ntokens >= 2)
-                           sys_automax = 1 << max(atoi(tokens[1]), 10);
-                       break;
+/* FUNCTIONS FOR PERFORMING THE CONFIGURATION
+ * ------------------------------------------
+ */
 
-                   case CONFIG_CRYPTO:
-                       if (ntokens == 1) {
-                               crypto_config(CRYPTO_CONF_NONE, NULL);
-                               break;
-                       }
-                       for (i = 1; i < ntokens; i++) {
-                           int temp;
-
-                           temp = matchkey(tokens[i++],
-                                crypto_keywords, 1);
-                           if (i > ntokens - 1) {
-                               msyslog(LOG_ERR,
-                                   "crypto: missing argument");
-                               errflg++;
-                               break;
-                           }
-                           switch(temp) {
+static void config_other_modes(void)
+{
 
-                           case CONF_CRYPTO_CERT:
-                               crypto_config(CRYPTO_CONF_CERT,
-                                   tokens[i]);
-                               break;
+    struct sockaddr_storage addr_sock;
+    struct address_node *addr_node;
 
-                           case CONF_CRYPTO_RSA:
-                               crypto_config(CRYPTO_CONF_PRIV,
-                                   tokens[i]);
-                               break;
+    if (my_config.broadcastclient) {
+        proto_config(PROTO_BROADCLIENT, my_config.broadcastclient, 0., NULL);
+        my_config.broadcastclient = 0;
+    }
+    
+    /* Configure the many-cast servers */
+    if (!empty(my_config.manycastserver)) {
+        while (!empty(my_config.manycastserver)) {
+            addr_node = (struct address_node *)
+                dequeue(my_config.manycastserver);
+            
+            memset((char *)&addr_sock, 0, sizeof(addr_sock));
+            addr_sock.ss_family = addr_node->type;
+
+            if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK)  == 1)
+                proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+            
+            free(addr_node->address);
+            free_node(addr_node);
+        }
+        sys_manycastserver = 1;
+    }
+    
+    /* Configure the multicast clients */
+    if (!empty(my_config.multicastclient)) {
+        while (!empty(my_config.multicastclient)) {
+            addr_node = (struct address_node *)
+                dequeue(my_config.multicastclient);
+            
+            memset((char *)&addr_sock, 0, sizeof(addr_sock));
+            addr_sock.ss_family = addr_node->type;
+
+            if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK)  == 1)
+                proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+            
+            
+            free(addr_node->address);
+            free_node(addr_node);
+        }
+        proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
+    }
+}
 
-                           case CONF_CRYPTO_IDENT:
-                               crypto_config(CRYPTO_CONF_IDENT,
-                                   tokens[i]);
-                               break;
 
-                           case CONF_CRYPTO_IFFPAR:
-                               crypto_config(CRYPTO_CONF_IFFPAR,
-                                   tokens[i]);
-                               break;
+static void config_auth(void)
+{
+    struct attr_val *my_val;
+    int *key_val;
+    
+    /* Crypto Command */
+    if (my_config.auth.crypto_cmd_list) {
+        while (!empty(my_config.auth.crypto_cmd_list)) {
+            my_val = (struct attr_val *) 
+                dequeue(my_config.auth.crypto_cmd_list);
+            crypto_config(my_val->attr, my_val->value.s);
+            
+            free(my_val->value.s);
+            free_node(my_val);
+        }
+        destroy_queue(my_config.auth.crypto_cmd_list);
+        my_config.auth.crypto_cmd_list = NULL;
+    }
+    
+    /* Keys Command */
+    if (my_config.auth.keys)
+        getauthkeys(my_config.auth.keys);
+    
+    /* Keysdir Command */
+    if (my_config.auth.keysdir)
+        keysdir = my_config.auth.keysdir;
+
+    /* Control Key Command */
+    if (my_config.auth.control_key != 0) 
+        ctl_auth_keyid = my_config.auth.control_key;
+
+    /* Requested Key Command */
+    if (my_config.auth.requested_key) {
+#ifdef DEBUG
+        if (debug > 3)
+            printf("set info_auth_key to %08lx\n",
+                   (long unsigned int) my_config.auth.requested_key);
+#endif
+        info_auth_keyid = (keyid_t) my_config.auth.requested_key;
+    }
 
-                           case CONF_CRYPTO_GQPAR:
-                               crypto_config(CRYPTO_CONF_GQPAR,
-                                   tokens[i]);
-                               break;
+    /* Trusted Key Command */
+    if (my_config.auth.trusted_key_list) {
+        while (!empty(my_config.auth.trusted_key_list)) {
+            key_val = (int *) dequeue(my_config.auth.trusted_key_list);
+            authtrust(*key_val, 1);
+            free_node(key_val);
+        }
+        destroy_queue(my_config.auth.trusted_key_list);
+        my_config.auth.trusted_key_list = NULL;
+    }
+    
+    /* Revoke Command */
+    if (my_config.auth.revoke) 
+        sys_revoke = (u_char) max(my_config.auth.revoke, KEY_REVOKE);
 
-                           case CONF_CRYPTO_MVPAR:
-                               crypto_config(CRYPTO_CONF_MVPAR,
-                                   tokens[i]);
-                               break;
+#if !defined(VMS) && !defined(SYS_VXWORKS)
+    /* find a keyid */
+    if (info_auth_keyid == 0)
+        req_keyid = 65535;
+    else
+        req_keyid = info_auth_keyid;
+
+    /* if doesn't exist, make up one at random */
+    if (!authhavekey(req_keyid)) {
+        char rankey[9];
+        int i, 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? */
+        }
+    }
 
-                           case CONF_CRYPTO_LEAP:
-                               crypto_config(CRYPTO_CONF_LEAP,
-                                   tokens[i]);
-                               break;
+    /* save keyid so we will accept config requests with it */
+    info_auth_keyid = req_keyid;
+#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
 
-                           case CONF_CRYPTO_PW:
-                               crypto_config(CRYPTO_CONF_PW,
-                                   tokens[i]);
-                               break;
+}
 
-                           case CONF_CRYPTO_RAND:
-                               crypto_config(CRYPTO_CONF_RAND,
-                                   tokens[i]);
-                               break;
+static void config_tos(void) {
+    struct attr_val *tos;
+    
+    while (!empty(my_config.orphan_cmds)) {
+        tos = (struct attr_val *) dequeue(my_config.orphan_cmds);
+        proto_config(tos->attr, 0, tos->value.d, NULL);
+        free_node(tos);
+    }
+}
 
-                           case CONF_CRYPTO_SIGN:
-                               crypto_config(CRYPTO_CONF_SIGN,
-                                   tokens[i]);
-                               break;
+static void config_monitor(void)
+{
+    char **filegen_string;
+    FILEGEN *filegen;
+    struct filegen_node *my_node;
+    struct attr_val *my_opts;
+
+    char *filegen_file;
+    int filegen_type;
+    int filegen_flag;
+    
+    /* Set the statistics directory */
+    if (my_config.stats_dir) {
+        stats_config(STATS_STATSDIR,my_config.stats_dir);
+        free(my_config.stats_dir);
+        my_config.stats_dir = NULL;
+    }
+    
+    /* 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 */
+    while (!empty(my_config.stats_list)) {
+        filegen_string = (char **) dequeue(my_config.stats_list);
+        filegen = filegen_get(*filegen_string);
 
-                           default:
-                               msyslog(LOG_ERR,
-                                   "crypto: unknown keyword");
-                               break;
-                           }
-                       }
-                       break;
-#endif /* OPENSSL */
+#ifdef DEBUG
+        if (debug > 3)
+            printf("enabling filegen for %s statistics \"%s%s\"\n",
+                   *filegen_string, filegen->prefix, filegen->basename);
+#endif
+        filegen->flag |= FGEN_FLAG_ENABLED;
+        free_node(filegen_string);
+    }
+    
+    /* Configure the statistics with the options */
+    while (!empty(my_config.filegen_opts)) {
+        my_node = (struct filegen_node *) dequeue(my_config.filegen_opts);
+        filegen = filegen_get(my_node->name);
+
+        /* Initilize the filegen variables to their pre-configurtion states */
+        filegen_flag = filegen->flag;
+        filegen_type = filegen->type;
+        filegen_file = my_node->name; 
+
+        while (!empty(my_node->options)) {
+            my_opts = (struct attr_val *) dequeue(my_node->options);
+            switch (my_opts->attr) {
+            case T_File:
+                filegen_file = (char *) my_opts->value.p;
+                break;
+            case T_Type:
+                filegen_type = my_opts->value.i;
+                break;
+            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;
+                }
+                break;
+            }
+            filegen_config(filegen, filegen_file, filegen_type, filegen_flag);
+            free_node(my_opts);
+        }
+        free_node(my_node);
+    }
+}
 
-                   case CONFIG_RESTRICT:
-                       if (ntokens < 2) {
-                               msyslog(LOG_ERR, "restrict requires an address");
-                               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++;
-                               break;
-                       case CONF_ADDR_IPV6:
-                               peeraddr.ss_family = AF_INET6;
-                               istart++;
-                               break;
-                       }
 
-                       /*
-                        * Assume default means an IPv4 address, except
-                        * if forced by a -4 or -6.
-                        */
-                       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;
+static void config_access(void) 
+{
+    struct attr_val *my_opt;
+    struct restrict_node *my_node;
+    
+    struct sockaddr_storage addr_sock;
+    struct sockaddr_storage addr_mask;
+
+    int flags;
+    int mflags;
+
+    /* Configure the discard options */
+    while (!empty(my_config.discard_opts)) {
+        my_opt = (struct attr_val *)
+            dequeue(my_config.discard_opts);
+        switch(my_opt->attr) {
+        case T_Average:
+            res_avg_interval = my_opt->value.i;
+            break;
+        case T_Minimum:
+            res_min_interval = my_opt->value.i;
+            break;
+        case T_Monitor:
+            mon_age = my_opt->value.i;
+            break;
+        }
+        free_node(my_opt);
+    }
 
-                       /*
-                        * Use peerversion as flags, peerkey as mflags.  Ick.
-                        */
-                       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;
-
-                                   case CONF_RES_IGNORE:
-                                       peerversion |= RES_IGNORE;
-                                       break;
-
-                                   case CONF_RES_NOSERVE:
-                                       peerversion |= RES_DONTSERVE;
-                                       break;
-
-                                   case CONF_RES_NOTRUST:
-                                       peerversion |= RES_DONTTRUST;
-                                       break;
-
-                                   case CONF_RES_NOQUERY:
-                                       peerversion |= RES_NOQUERY;
-                                       break;
-
-                                   case CONF_RES_NOMODIFY:
-                                       peerversion |= RES_NOMODIFY;
-                                       break;
-
-                                   case CONF_RES_NOPEER:
-                                       peerversion |= RES_NOPEER;
-                                       break;
-
-                                   case CONF_RES_NOTRAP:
-                                       peerversion |= RES_NOTRAP;
-                                       break;
-
-                                   case CONF_RES_LPTRAP:
-                                       peerversion |= RES_LPTRAP;
-                                       break;
-
-                                   case CONF_RES_NTPPORT:
-                                       peerkey |= RESM_NTPONLY;
-                                       break;
-
-                                   case CONF_RES_VERSION:
-                                       peerversion |= RES_VERSION;
-                                       break;
-
-                                   case CONF_RES_DEMOBILIZE:
-                                       peerversion |= RES_DEMOBILIZE;
-                                       break;
-
-                                   case CONF_RES_LIMITED:
-                                       peerversion |= RES_LIMITED;
-                                       break;
-
-                                   case CONFIG_UNKNOWN:
-                                       errflg++;
-                                       break;
-                               }
-                       }
-                       if (SOCKNUL(&peeraddr))
-                           ANYSOCK(&maskaddr);
-                       if (!errflg)
-                           hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
-                                         (int)peerkey, peerversion);
-                       break;
+    /* Configure the restrict options */
+    while (!empty(my_config.restrict_opts)) {
+        my_node = (struct restrict_node *)
+            dequeue(my_config.restrict_opts);
+
+        memset((char *)&addr_sock, 0, sizeof(addr_sock));
+        /* Check if the user specified a default rule */
+        if (my_node->addr) {
+            /* Resolve the specified address */
+            addr_sock.ss_family = my_node->addr->type;
+            
+            if (getnetnum(my_node->addr->address, 
+                          &addr_sock, 1,t_UNK) != 1) {
+                
+                /* Error in resolving name!!!
+                 * Free the node memory and move onto the next
+                 * Restrict flag 
+                 */
+                msyslog(LOG_INFO,
+                        "restrict: error in resolving name: %s on line %d. Ignoring...",
+                        my_node->addr->address, my_node->line_no);
+                destroy_restrict_node(my_node);
+                continue;
+            }
+            
+            SET_HOSTMASK(&addr_mask, addr_sock.ss_family);
+            
+            /* Resolve the mask */
+            if (my_node->mask) {
+                memset((char *)&addr_mask, 0, sizeof(addr_mask));
+                addr_mask.ss_family = my_node->mask->type;
+                if (getnetnum(my_node->mask->address, &addr_mask, 1, t_MSK) != 1) {
+                    /* Error in mask !!!
+                     * Free the node memory and move onto the next
+                     * Restrict flag 
+                     */
+                    msyslog(LOG_INFO,
+                            "restrict: error in resolving mask: %s on line %d. Ignoring...",
+                            my_node->mask->address, my_node->line_no);
+                    destroy_restrict_node(my_node);
+                    continue;
+                }
+            }
+        }
+        else { /* The user specified a default rule */
+            addr_sock.ss_family = default_ai_family;
+            ANYSOCK(&addr_mask);
+        }
+        
+        /* Parse the flags */
+        flags = 0;
+        mflags = 0;
+        
+        while (!empty(my_node->flags)) {
+            int *curr_flag = (int *) dequeue(my_node->flags);
+            if (*curr_flag == RESM_NTPONLY)
+                mflags |= *curr_flag;
+            else
+                flags |= *curr_flag;
+            free_node(curr_flag);
+        }   
+
+        /* Set the flags */        
+        hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
+                      mflags, flags);
+        destroy_restrict_node(my_node);
+    }
+}
 
-                   case CONFIG_BDELAY:
-                       if (ntokens >= 2) {
-                               double tmp;
 
-                               if (sscanf(tokens[1], "%lf", &tmp) != 1) {
-                                       msyslog(LOG_ERR,
-                                               "broadcastdelay value %s undecodable",
-                                               tokens[1]);
-                               } else {
-                                       proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
-                               }
-                       }
-                       break;
+static void config_tinker(void)
+{
+    struct attr_val *tinker;
+    
+    while (!empty(my_config.tinker)) {
+        tinker= (struct attr_val *) dequeue(my_config.tinker);
+        loop_config(tinker->attr, tinker->value.d);
+        free_node(tinker);
+    }
+}
 
-                   case CONFIG_CDELAY:
-                        if (ntokens >= 2) {
-                                u_long ui;
 
-                               if (sscanf(tokens[1], "%ld", &ui) != 1)
-                                       msyslog(LOG_ERR,
-                                           "illegal value - line ignored");
-                               else
-                                       proto_config(PROTO_CALLDELAY, ui, 0, NULL);
-                       }
-                       break;
+static void config_system_opts(void) 
+{
+    int enable_flags;
+    int disable_flags;
+
+    enable_flags = get_flags_from_list(my_config.enable_opts);
+    disable_flags = get_flags_from_list(my_config.disable_opts);
+    
+    if (enable_flags)
+        proto_config(enable_flags, 1, 0., NULL);
+    if (disable_flags)
+        proto_config(disable_flags, 0, 0., NULL);
+}
 
-                   case CONFIG_TRUSTEDKEY:
-                       for (i = 1; i < ntokens; i++) {
-                               keyid_t tkey;
-
-                               tkey = atol(tokens[i]);
-                               if (tkey == 0) {
-                                       msyslog(LOG_ERR,
-                                               "trusted key %s unlikely",
-                                               tokens[i]);
-                               } else {
-                                       authtrust(tkey, 1);
-                               }
-                       }
-                       break;
+static void config_logconfig(void)
+{
+    struct attr_val *my_logconfig;
+
+    while(!empty(my_config.logconfig)) {
+        my_logconfig = (struct attr_val *)
+            dequeue(my_config.logconfig);
+        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;
+        }
+        free(my_logconfig->value.s);
+        free_node(my_logconfig);
+    }
+}
 
-                   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);
-#endif
-                                       info_auth_keyid = (keyid_t)ul;
-                               }
-                       }
-                       break;
+static void config_phone(void)
+{
+    int i = 0;
+    char **s;
+    
+    while (!empty(my_config.phone)) {
+        s = (char **) dequeue(my_config.phone);
+        if (i < MAXPHONE)
+            sys_phone[i++] = *s;
+        else {
+            msyslog(LOG_INFO,
+                    "phone: Number of phone entries exceeds %d. Ignoring phone %s...",
+                    MAXPHONE, *s);
+            free(*s);
+        }
+        free_node(s);
+    }
+    sys_phone[i] = NULL;
+}
 
-                   case CONFIG_CONTROLKEY:
-                       if (ntokens >= 2) {
-                               keyid_t ckey;
-
-                               ckey = atol(tokens[1]);
-                               if (ckey == 0) {
-                                       msyslog(LOG_ERR,
-                                               "%s makes a poor control keyid",
-                                               tokens[1]);
-                               } else {
-                                       ctl_auth_keyid = ckey;
-                               }
-                       }
-                       break;
+static void config_setvar(void)
+{
+    struct setvar_node *my_node;
 
-                   case CONFIG_TRAP:
-                       if (ntokens < 2) {
-                               msyslog(LOG_ERR,
-                                       "no address for trap command, line ignored");
-                               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++;
-                               break;
-                       case CONF_ADDR_IPV6:
-                               peeraddr.ss_family = AF_INET6;
-                               istart++;
-                               break;
-                       }
+    while (!empty(my_config.setvar)) {
+        my_node = (struct setvar_node *) dequeue(my_config.setvar);
+        set_sys_var(my_node->data, my_node->len, my_node->def);
+        free_node(my_node);
+    }
+}
 
-                       if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
-                           break;
+static void config_ttl(void)
+{
+    int i = 0;
+    int *curr_ttl;
+    
+    while (!empty(my_config.ttl)) {
+        curr_ttl = (int *) dequeue(my_config.ttl);
+        if (i < MAX_TTL)
+            sys_ttl[i++] = *curr_ttl;
+        else 
+            msyslog(LOG_INFO,
+                    "ttl: Number of TTL entries exceeds %d. Ignoring TTL %d...",
+                    MAX_TTL, *curr_ttl);
+     
+        free_node(curr_ttl);
+    }
+    sys_ttlmax = i - 1;
+}
 
-                       /*
-                        * 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));
-                       }
-                       break;
+static void config_trap(void)
+{
+    
+    struct addr_opts_node *curr_trap;
+    struct attr_val *curr_opt;
+    struct sockaddr_storage addr_sock;
+    struct sockaddr_storage peeraddr;
+    struct address_node *addr_node;
+    struct interface *localaddr;
+    int port_no;
+    int err_flag;
+    
+    port_no = 0;
+    localaddr = 0;
+
+    
+    while (!empty(my_config.trap)) {
+        err_flag = 0;
+        curr_trap = (struct addr_opts_node *) dequeue(my_config.trap);
+        
+        while (!empty(curr_trap->options)) {
+            curr_opt = (struct attr_val *) dequeue(curr_trap->options);
+            if (curr_opt->attr == T_Port) {
+                port_no = curr_opt->value.i;
+                if (port_no <= 0 || port_no > 32767) {
+                    msyslog(LOG_ERR, "invalid port number %d, trap ignored", port_no);
+                    err_flag = 1;
+                }
+            }
+            else if (curr_opt->attr == T_Interface) {
+                addr_node = (struct address_node *) curr_opt->value.p;
+
+                /* Resolve the interface address */
+                memset((char *)&addr_sock, 0, sizeof(addr_sock));
+                addr_sock.ss_family = addr_node->type;
+                
+                if (getnetnum(addr_node->address,
+                              &addr_sock, 1, t_UNK) != 1) {
+                    err_flag = 1;
+                    break;
+                }
+                
+                localaddr = findinterface(&addr_sock);
+                
+                if (localaddr == NULL) {
+                    msyslog(LOG_ERR,
+                            "can't find interface with address %s",
+                            stoa(&addr_sock));
+                    err_flag = 1;
+                }
+                
+                free(addr_node->address);
+                free_node(addr_node);
+            }
+            free_node(curr_opt);
+        }
+        
+        /* Now process the trap for the specified interface
+         * and port number 
+         */
+        if (!err_flag) {
+            memset((char *)&peeraddr, 0, sizeof(peeraddr));
+            if (port_no != 0)
+                ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons((u_short) port_no);
+            else
+                ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
+
+            if (localaddr == NULL) {
+                peeraddr.ss_family = default_ai_family;
+                localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
+            }
+            else
+                peeraddr.ss_family = addr_sock.ss_family;
+            
+            if (!ctlsettrap(&peeraddr, localaddr, 0,
+                            NTP_VERSION))
+                msyslog(LOG_ERR,
+                        "can't set trap for %s, no resources",
+                        stoa(&peeraddr));
+        }
+        destroy_queue(curr_trap->options);
+        free_node(curr_trap);
+    }    
+}
 
-                   case CONFIG_FUDGE:
-                       if (ntokens < 2) {
-                               msyslog(LOG_ERR,
-                                       "no address for fudge command, line ignored");
-                               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));
-                               break;
-                       }
+static void config_fudge(void)
+{
+    struct addr_opts_node *curr_fudge;
+    struct attr_val *curr_opt;
+    struct sockaddr_storage addr_sock;
+    struct address_node *addr_node;
+    struct refclockstat clock_stat;
+    int err_flag;
+    
+    
+    while (!empty(my_config.fudge)) {
+        curr_fudge = (struct addr_opts_node *) dequeue(my_config.fudge);
+        err_flag = 0;
+        
+        /* Get the reference clock address and
+         * ensure that it is sane
+         */
+        addr_node = curr_fudge->addr;
+        memset((char *)&addr_sock, 0, sizeof(addr_sock));
+        if (getnetnum(addr_node->address, &addr_sock, 1, t_REF) != 1)
+            err_flag = 1;
+        
+        if (!ISREFCLOCKADR(&addr_sock)) {
+            msyslog(LOG_ERR,
+                    "%s is inappropriate address for the fudge command, line ignored",
+                    stoa(&addr_sock));
+            err_flag = 1;
+        }
+
+        /* Parse all the options to the fudge command */
+        memset((void *)&clock_stat, 0, sizeof clock_stat);
+        while (!empty(curr_fudge->options)) {
+            curr_opt = (struct attr_val *) dequeue(curr_fudge->options);
+            
+            /* The attribute field is used to store the flag. 
+             * Set haveflags with it
+             */
+            clock_stat.haveflags |= curr_opt->attr;
+            switch (curr_opt->attr) {
+            case CLK_HAVETIME1:
+                clock_stat.fudgetime1 = curr_opt->value.d;
+                break;
+            case CLK_HAVETIME2:
+                clock_stat.fudgetime2 = curr_opt->value.d;
+                break;
+            case CLK_HAVEVAL1:
+                clock_stat.fudgeval1 = curr_opt->value.i;
+                break;
+            case CLK_HAVEVAL2:
+                memcpy(&clock_stat.fudgeval2,
+                       curr_opt->value.s, 
+                       min(strlen(curr_opt->value.s), 4));
+                free(curr_opt->value.s);
+                break;
+            case CLK_HAVEFLAG1:
+                if (curr_opt->value.i)
+                    clock_stat.flags |= CLK_FLAG1;
+                else
+                    clock_stat.flags &= ~CLK_FLAG1;
+                break;
+            case CLK_HAVEFLAG2:
+                if (curr_opt->value.i)
+                    clock_stat.flags |= CLK_FLAG2;
+                else
+                    clock_stat.flags &= ~CLK_FLAG2;
+                break;
+            case CLK_HAVEFLAG3:
+                if (curr_opt->value.i)
+                    clock_stat.flags |= CLK_FLAG3;
+                else
+                    clock_stat.flags &= ~CLK_FLAG3;
+                break;
+            case CLK_HAVEFLAG4:
+                if (curr_opt->value.i)
+                    clock_stat.flags |= CLK_FLAG4;
+                else
+                    clock_stat.flags &= ~CLK_FLAG4;
+                break;
+            }
+            
+            free_node(curr_opt);
+        }
+        if (!err_flag)
+            refclock_control(&addr_sock, &clock_stat,
+                             (struct refclockstat *)0);
+        destroy_queue(curr_fudge->options);
+        free_node(curr_fudge);
+    }
+}
 
-                       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 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 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 CONF_FDG_REFID:
-                                       i++;
-                                       memcpy(&clock_stat.fudgeval2,
-                                           tokens[i], min(strlen(tokens[i]),
-                                           4));
-                                       clock_stat.haveflags |= CLK_HAVEVAL2;
-                                       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 CONFIG_UNKNOWN:
-                                       errflg = -1;
-                                       break;
-                               }
-                       }
+static void config_vars(void)
+{
+    struct attr_val *curr_var;
+    FILE *new_file;
+    
+    while (!empty(my_config.vars)) {
+        curr_var = (struct attr_val *) dequeue(my_config.vars);
+        /* 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:
+            stats_config(STATS_FREQ_FILE, curr_var->value.s);
+            free(curr_var->value.s);
+            break;
+        case T_Pidfile:
+            stats_config(STATS_PID_FILE, curr_var->value.s);
+            free(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,
+                        "Cannot open log file %s",
+                        curr_var->value.s);
+            free(curr_var->value.s);
+            break;
+        case T_Automax:
+            sys_automax = 1 << max(curr_var->value.i, 10);
+            break;
+        }
+        free_node(curr_var);
+    }
+}
 
+/* Define a function to check if a resolved address is sane.
+ * If yes, return 1, else return 0;
+ */
+static int is_sane_resolved_address(struct sockaddr_storage peeraddr, int hmode)
+{
+    if (
 #ifdef REFCLOCK
-                       /*
-                        * If reference clock support isn't defined the
-                        * fudge line will still be accepted and syntax
-                        * checked, but will essentially do nothing.
-                        */
-                       if (!errflg) {
-                               refclock_control(&peeraddr, &clock_stat,
-                                   (struct refclockstat *)0);
-                       }
+        !ISREFCLOCKADR(&peeraddr) &&
 #endif
-                       break;
+        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!
+     */
+    /* Check for IPv4 */
+    if (peeraddr.ss_family == AF_INET) {
+        if (((hmode == T_Server) || (hmode == T_Peer) || (hmode == T_Pool)) &&
+#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));
+            return 0;
+        }
+        if ((hmode == T_Manycastclient) &&
+            !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
+            msyslog(LOG_ERR,
+                    "attempt to configure invalid address %s",
+                    stoa(&peeraddr));
+            return 0;
+        }
+         
+    }
+    /* Check for IPv6 */
+    else if(peeraddr.ss_family == AF_INET6) {
+        if (((hmode == T_Server) || (hmode == T_Peer) || (hmode == T_Pool)) &&
+#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));
+            return 0;
+        }
+        if ((hmode == T_Manycastclient) &&
+            !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
+            msyslog(LOG_ERR,
+                    "attempt to configure in valid address %s",
+                    stoa(&peeraddr));
+            return 0;
+        }
+    }
+    
+    if (peeraddr.ss_family == AF_INET6 &&
+        isc_net_probeipv6() != ISC_R_SUCCESS)
+        return 0;
 
-                   case CONFIG_STATSDIR:
-                       if (ntokens >= 2)
-                               stats_config(STATS_STATSDIR,tokens[1]);
-                       break;
+    /* Ok, all tests succeeded, now we can return 1 */
+    return 1;
+}
 
-                   case CONFIG_STATISTICS:
-                       for (i = 1; i < ntokens; i++) {
-                               filegen = filegen_get(tokens[i]);
+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:
+        fprintf(stderr, "Fatal error in client_type in ntp_config.y");
+        exit(1);
+        break;
+    }
+}
 
-                               if (filegen == NULL) {
-                                       msyslog(LOG_ERR,
-                                               "no statistics named %s available",
-                                               tokens[i]);
-                                       continue;
-                               }
+static void config_peers()
+{
+    struct addrinfo *res, res_bak;
+    struct sockaddr_storage peeraddr;
+    struct peer_node *curr_peer;
+    int hmode;
+    int status;
+    int no_needed;
+    int i;
+    
+    while (!empty(my_config.peers)) {
+        curr_peer = (struct peer_node *) dequeue(my_config.peers);
+        
+        /* Find the number of associations needed.
+         * If a pool coomand is specified, then sys_maxclock needed
+         * else, only one is needed
+         */
+        no_needed = (curr_peer->host_mode == T_Pool) ? sys_maxclock : 1;
+
+        /* Find the correct host-mode */
+        hmode = get_correct_host_mode(curr_peer->host_mode);
+        
+        /* Attempt to resolve the address */
+        memset((char *)&peeraddr, 0, sizeof(peeraddr));
+        peeraddr.ss_family = curr_peer->addr->type;
+        
+        status = get_multiple_netnums(curr_peer->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, apparantly 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) {
+            save_resolve(curr_peer->addr->address,
+                         hmode,
+                         curr_peer->peerversion,
+                         curr_peer->minpoll,
+                         curr_peer->maxpoll, 
+                         curr_peer->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;
+            /* Loop to configure the desired number of associations 
+             */
+            for (i = 0; (i < no_needed) && res; res = res->ai_next) {
+                ++i;
+                memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
 #ifdef DEBUG
-                               if (debug > 3)
-                                   printf("enabling filegen for %s statistics \"%s%s\"\n",
-                                          tokens[i], filegen->prefix, filegen->basename);
+                if (debug > 1)
+                    printf("configuring host %s with address %s\n",
+                           curr_peer->addr->address, stoa(&peeraddr));
 #endif
-                               filegen->flag |= FGEN_FLAG_ENABLED;
-                       }
-                       break;
+                if (is_sane_resolved_address(peeraddr, curr_peer->host_mode)) {
+                    if (peer_config(&peeraddr,
+                                    ANY_INTERFACE_CHOOSE(&peeraddr), 
+                                    hmode,
+                                    curr_peer->peerversion, 
+                                    curr_peer->minpoll, 
+                                    curr_peer->maxpoll, 
+                                    curr_peer->peerflags,
+                                    curr_peer->ttl, 
+                                    curr_peer->peerkey, 
+                                    (u_char *)"*") == 0) {
+                        msyslog(LOG_ERR,
+                                "configuration of %s failed",
+                                stoa(&peeraddr));
+                    }
+                }
+            }
+            freeaddrinfo(res_bak);
+        }
+
+        /* Ok, everything done. Free up peer node memory */
+        free(curr_peer->addr->address);
+        free_node(curr_peer->addr);
+        free_node(curr_peer);
+    }
+}
 
-                   case CONFIG_FILEGEN:
-                       if (ntokens < 2) {
-                               msyslog(LOG_ERR,
-                                       "no id for filegen command, line ignored");
-                               break;
-                       }
+#ifdef SIM
+static void config_sim()
+{
+    int i;
+    server_info *serv_info;
+    struct attr_val *init_stmt;
+    
+    /* Check if a simulate block was found in the configuration code.
+     * If not, return an error and exit
+     */
+    if (my_config.sim_details == NULL) {
+        fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
+        fprintf(stderr, "\tCheck your configuration file.\n");
+        exit(1);
+    }
 
-                       filegen = filegen_get(tokens[1]);
-                       if (filegen == NULL) {
-                               msyslog(LOG_ERR,
-                                       "unknown filegen \"%s\" ignored",
-                                       tokens[1]);
-                               break;
-                       }
-                       /*
-                        * peerversion is (ab)used for filegen file (index)
-                        * peerkey         is (ab)used for filegen type
-                        * peerflags   is (ab)used for filegen flags
-                        */
-                       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;
-
-                                   case CONF_FGEN_FLAG_LINK:
-                                       peerflags |= FGEN_FLAG_LINK;
-                                       break;
-
-                                   case CONF_FGEN_FLAG_NOLINK:
-                                       peerflags &= ~FGEN_FLAG_LINK;
-                                       break;
-
-                                   case CONF_FGEN_FLAG_ENABLE:
-                                       peerflags |= FGEN_FLAG_ENABLED;
-                                       break;
-
-                                   case CONF_FGEN_FLAG_DISABLE:
-                                       peerflags &= ~FGEN_FLAG_ENABLED;
-                                       break;
-                               }
-                       }
-                       if (!errflg)
-                               filegen_config(filegen, tokens[peerversion],
-                                  (u_char)peerkey, (u_char)peerflags);
-                       break;
+    /* Process the initialization statements 
+     * -------------------------------------
+     */
+    while(!empty(my_config.sim_details->init_opts)) {
+        init_stmt = (struct attr_val *) 
+            dequeue(my_config.sim_details->init_opts);
+        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:
+            yyerror("Internal Error in parser...\n"
+                    "Invalid init statement in simulator block");
+            break;
+        }
+        free_node(init_stmt);
+    }
+    destroy_queue(my_config.sim_details->init_opts);
+
+
+    /* Process the server list 
+     * -----------------------
+     */
+    simulation.num_of_servers = get_no_of_elements(my_config.sim_details->servers);
+    simulation.servers = (server_info *) malloc(simulation.num_of_servers *
+                                                sizeof(server_info));
+
+    for (i = 0;i < simulation.num_of_servers;++i) {
+        serv_info = (server_info *) 
+            dequeue(my_config.sim_details->servers);
+        if (!serv_info) 
+            yyerror("Internal Error in parser...\n"
+                    "Tried to initialize server list but no server returned\n");
+        memcpy(&simulation.servers[i], serv_info, sizeof(server_info));
+        free_node(serv_info);
+    }
+    destroy_queue(my_config.sim_details->servers);
+    
+    /* Free the sim_node memory and set the sim_details as NULL */
+    free_node(my_config.sim_details);
+    my_config.sim_details = NULL;
+    
+    /* Create server associations */
+    printf("Creating server associations\n");
+    create_server_associations();
+    fprintf(stderr,"\tServer associations successfully created!!\n");
+}
+#endif /* SIM */
 
-                   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)));
-                       }
-                       break;
+/* 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 
+ */
 
-                   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;
+static void config_ntpd() 
+{
+    config_auth();
+    config_tos();
+    config_monitor();
+    config_access();
+    config_tinker();
+    config_system_opts();
+    config_logconfig();
+    config_phone();
+    config_setvar();
+    config_ttl();
+    config_trap();
+    config_fudge();
+    config_vars();
+    config_other_modes();
+    config_peers();
+}
 
-                   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_ntpdsim()
+{
+    printf("Configuring Simulator...\n");
+    printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
+
+    config_tos();
+    config_monitor();
+    config_tinker();
+    config_system_opts();
+    config_logconfig();
+    config_vars();
+    config_sim();
+}
+#endif /* SIM */
 
-                   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;
+void config_remotely() 
+{
+    input_from_file = 0;
+//    init_syntax_tree();
+    yyparse();
+    if (debug > 1) 
+        printf("Finished Parsing!!\n");
+
+    config_ntpd();
+    
+    input_from_file = 1;
+}
+    
 
-                   case CONFIG_ADJ: {
-                           double ftemp;
+/* ACTUAL getconfig code */
 
-                           sscanf(tokens[1], "%lf", &ftemp);
-                           proto_config(PROTO_ADJ, 0, ftemp, NULL);
-                       }
-                       break;
+void getconfig(int argc,char *argv[])
+{
+    char line[MAXLINE];
 
-               }
-       }
-       if (fp[0])
-               (void)fclose(fp[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;
+    
+    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 */
+    progname = argv[0];
+    res_fp = NULL;
+    ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+
+    /*
+     * install a non default variable with this daemon version
+     */
+    (void) sprintf(line, "daemon_version=\"%s\"", Version);
+    set_sys_var(line, strlen(line)+1, RO);
+    
+    /*
+     * 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);
+
+    /*
+     * Initialize the loop.
+     */
+    loop_config(LOOP_DRIFTINIT, 0.);
+    
+    getCmdOpts(argc, argv);
+
+    curr_include_level = 0;
+    if (
+        (fp[curr_include_level] = F_OPEN(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 */
+        
+        if ((fp[curr_include_level] = F_OPEN(FindConfig(alt_config_file), "r")) == NULL) {
+
+            /*
+             * Broadcast clients can sometimes run without
+             * a configuration file.
+             */
+            
+            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;
+        }
+#else  /* not SYS_WINNT */
+        return;
+#endif /* not SYS_WINNT */
+    }
+
+    /*** BULK OF THE PARSER ***/
+    ip_file = fp[curr_include_level];
+    key_scanner = create_keyword_scanner(keyword_list);
+    init_syntax_tree();
+    yyparse();
+    if (debug > 1) 
+        printf("Finished Parsing!!\n");
+
+    /* 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();
+#else
+    config_ntpdsim();
+#endif
 
+    while (curr_include_level != -1) {
+        FCLOSE(fp[curr_include_level--]);
+    }
+    
+    
 #ifdef HAVE_NETINFO
-       if (config_netinfo)
-               free_netinfo_config(config_netinfo);
+    if (config_netinfo)
+        free_netinfo_config(config_netinfo);
 #endif /* HAVE_NETINFO */
+        
+    if (res_fp != NULL) {
+        if (call_resolver) {
+            /*
+             * Need name resolution
+             */
+            do_resolve_internal();
+        }
+    }
+}
 
-#if !defined(VMS) && !defined(SYS_VXWORKS)
-       /* find a keyid */
-       if (info_auth_keyid == 0)
-               req_keyid = 65535;
-       else
-               req_keyid = info_auth_keyid;
 
-       /* 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? */
+/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
+ * --------------------------------------------
+ */
+
+
+/*
+ * get_pfxmatch - find value for prefixmatch
+ * and update char * accordingly
+ */
+static unsigned long
+get_pfxmatch(
+       char ** s,
+       struct masks *m
+       )
+{
+       while (m->name) {
+               if (strncmp(*s, m->name, strlen(m->name)) == 0) {
+                       *s += strlen(m->name);
+                       return m->mask;
+               } else {
+                       m++;
                }
        }
+       return 0;
+}
 
-       /* save keyid so we will accept config requests with it */
-       info_auth_keyid = req_keyid;
-#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
-
-       if (res_fp != NULL) {
-               if (call_resolver) {
-                       /*
-                        * Need name resolution
-                        */
-                       do_resolve_internal();
+/*
+ * 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++;
                }
        }
+       return 0;
+}
+
+/*
+ * get_logmask - build bitmask for ntp_syslogmask
+ */
+static unsigned long
+get_logmask(
+       char *s
+       )
+{
+       char *t;
+       unsigned long offset;
+       unsigned long mask;
+
+       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);
+
+       return 0;
 }
 
 
@@ -2079,217 +2180,102 @@ gettokens_netinfo (
 
 #endif /* HAVE_NETINFO */
 
-
 /*
- * gettokens - read a line and return tokens
+ * getnetnum - return a net number (this is crude, but careful)
  */
+
 static int
-gettokens (
-       FILE *fp,
-       char *line,
-       char **tokenlist,
-       int *ntokens
-       )
+getnetnum(
+    const char *num,
+    struct sockaddr_storage *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++ == '"');
+    int retval;
+    struct addrinfo *res;
 
-               if (ISEOL(*cp)) {
-                       *cp = '\0';
-                       break;
-               } else {                /* must be space */
-                       *cp++ = '\0';
-                       while (ISSPACE(*cp))
-                               cp++;
-                       if (ISEOL(*cp))
-                               break;
-               }
-       }
+    /* Get all the addresses that resolve to this name */
+    retval = get_multiple_netnums(num, addr, &res, complain, a_type);
 
-     /* 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';
-                       }
-                                                       
+    if (retval != 1) {
+        /* Name resolution failed */
+        return retval;
     }
 
-       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;
-       }
-
-       return ntok;
-}
-
-
-
-/*
- * 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++;
-       }
+    memcpy(addr, res->ai_addr, res->ai_addrlen);
+#ifdef DEBUG
+    if (debug > 1)
+        printf("getnetnum given %s, got %s \n",
+               num, stoa(addr));
+#endif
+    freeaddrinfo(res);
+    return 1;
 }
 
-
-/*
- * getnetnum - return a net number (this is crude, but careful)
- */
 static int
-getnetnum(
-       const char *num,
-       struct sockaddr_storage *addr,
-       int complain,
-       enum gnn_type a_type
-       )
+get_multiple_netnums(
+    const char *num,
+    struct sockaddr_storage *addr,
+    struct addrinfo **res,
+    int complain,
+    enum gnn_type a_type
+    )
 {
-       struct addrinfo hints;
-       struct addrinfo *ptr;
-       int retval;
-
-#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;
-
-       hints.ai_socktype = SOCK_DGRAM;
-
-       if (a_type != t_UNK) {
-               hints.ai_flags = AI_NUMERICHOST;
-       }
-
+    struct addrinfo hints;
+    struct addrinfo *ptr;
+
+    int retval;
+
+    /* 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;
+
+    hints.ai_socktype = SOCK_DGRAM;
 #ifdef DEBUG
-       if (debug > 3)
-               printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
+    if (debug > 3)
+        printf("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 (complain)
-                       msyslog(LOG_ERR,
-                               "getaddrinfo: \"%s\" invalid host address, ignored",
-                               num);
+    retval = getaddrinfo(num, "ntp", &hints, &ptr);
+    if (retval != 0 ||
+        (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
+        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"
-                               : "");
+        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) 
-               {
-                       return -1;
-               }
-               else {
-                       return 0;
-               }
-       }
+        if (retval == 0 && 
+            ptr->ai_family == AF_INET6 && 
+            isc_net_probeipv6() != ISC_R_SUCCESS) 
+        {
+            return -1;
+        }
+        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;
+    return 1;
 }
 
 
+
 #if !defined(VMS) && !defined(SYS_WINNT)
 /*
  * catchchild - receive the resolver's exit status
index 64603d37f527c74c2154ec718fa320a7f08e5b39..89fe992787c57794c22a957be85d2630b6f53514 100644 (file)
@@ -11,6 +11,7 @@
 #include "ntp_control.h"
 #include "ntp_unixtime.h"
 #include "ntp_stdlib.h"
+#include "ntp_config.h"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -76,9 +77,11 @@ static       void    read_clock_status P((struct recvbuf *, int));
 static void    write_clock_status P((struct recvbuf *, int));
 static void    set_trap        P((struct recvbuf *, int));
 static void    unset_trap      P((struct recvbuf *, int));
+static void    configure       P((struct recvbuf *, int));
 static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
                                    struct interface *));
 
+
 static struct ctl_proc control_codes[] = {
        { CTL_OP_UNSPEC,        NOAUTH, control_unspec },
        { CTL_OP_READSTAT,      NOAUTH, read_status },
@@ -88,6 +91,7 @@ static        struct ctl_proc control_codes[] = {
        { CTL_OP_WRITECLOCK,    NOAUTH, write_clock_status },
        { CTL_OP_SETTRAP,       NOAUTH, set_trap },
        { CTL_OP_UNSETTRAP,     NOAUTH, unset_trap },
+        { CTL_OP_CONFIGURE,     AUTH, configure },
        { NO_REQUEST,           0 }
 };
 
@@ -2306,6 +2310,56 @@ write_variables(
        ctl_flushpkt(0);
 }
 
+/* SK:
+ * configure: remotely configure an NTP daemon
+ */
+static void configure(struct recvbuf *rbufp,int restrict_mask)
+{
+    int data_count;
+    int retval;
+
+    /* I haven't yet implemented changes to an existing association.
+     * Hence check if the association id is 0
+     */
+    if (res_associd != 0) {
+        ctl_error(CERR_BADVALUE);
+        return;
+    }
+    
+    /* Initialize the remote config buffer */
+    data_count = reqend - reqpt;
+    memcpy(remote_config.buffer, reqpt, data_count);
+    remote_config.buffer[data_count++] = '\n';
+    remote_config.buffer[data_count] = '\0';
+    remote_config.pos = 0;
+    remote_config.err_pos = 0;
+    remote_config.no_errors = 0;
+
+    if (debug > 0)
+        printf("Got Remote Configuration Command: %s\n\n", remote_config.buffer);
+    config_remotely();
+
+    /* Check if errors were reported. If not, output 'Config Succeeded'
+     * Else output the error message
+     */
+    printf("No_Errors %d\n", remote_config.no_errors);
+    if (remote_config.no_errors == 0) {
+        retval = snprintf(remote_config.err_msg, MAXLINE, "Config Succeeded");
+        if (retval > 0) 
+            remote_config.err_pos += retval;
+    }
+    ctl_putdata(remote_config.err_msg, remote_config.err_pos, 0);
+
+//    datapt = remote_config.err_msg;
+//    dataend = remote_config.err_msg + remote_config.err_pos;
+//    datalinelen = remote_config.err_pos;
+//    datanotbinflag = 1;
+    
+//    printf("Reply: %s\n\nReply_len: %d\n\n", datapt, datalinelen);
+    
+    ctl_flushpkt(0);
+}
+
 
 /*
  * read_clock_status - return clock radio status
index fad74c7a2223243acea80bfd9eb79ca05735aa90..85e65104c47e6a41a0ab91e031d87ba4abafc8b7 100644 (file)
@@ -2572,7 +2572,7 @@ sendpkt(
        if (err != ERROR_SUCCESS)
 #else
 #ifdef SIM
-        cc = srvr_rply(&ntp_node,  dest, inter, pkt);
+       cc = simulate_server(dest, inter, pkt);
 #else /* SIM */
        cc = sendto(inter->fd, (char *)pkt, (unsigned int)len, 0, (struct sockaddr *)dest,
                    SOCKLEN(dest));
index d5ed587d562e63dee4f174c569c4fd6ea59ffc75..af626f819c5198bfa35ac479536c14050078e2db 100644 (file)
-/*
- * NTP simulator engine - Harish Nair
- * University of Delaware, 2001
+/* ntpdsim.c
+ *
+ * The source code for the ntp discrete event simulator. 
+ *
+ * Written By: Sachin Kamboj
+ *             University of Delaware
+ *             Newark, DE 19711
+ * Copyright (c) 2006
+ * (Some code shamelessly based on the original NTP discrete event simulator)
  */
+
 #include "ntpd.h"
 #include "ntpsim.h"
-#include "ntpdsim-opts.h"
-
-/*
- * Defines...
+#include "ntp_data_structures.h"
+
+/* Include the C source file for the data structures used by the simulator.
+ * Since these data structures are only used by the simulator, we will
+ * directly include the source file here instead of exporting the public
+ * interface of the data structures and "corrupting" the global namespace.
+ *
+ * SK: Update: The configuration code now makes use of these data structures.
+ * So I will include this file in the ntp_config.c instead of here.
+ * Once the autoconfigure code is updated, we can get rid of this messiness.
  */
-#define SIM_TIME 86400         /* end simulation time */
-#define NET_DLY .001            /* network delay */
-#define PROC_DLY .001          /* processing delay */
-#define BEEP_DLY 3600           /* beep interval (s) */
-#define        SLEW    500e-6          /* correction rate (PPM) */
+//#include "data_structures.c"
 
-/*
- * Function pointers
+
+/* Global Variable Definitions */
+
+sim_info simulation;         /* Simulation Control Variables */
+local_clock_info simclock;   /* Local Clock Variables */
+queue *event_queue;          /* Event Queue */
+queue *recv_queue;           /* Receive Queue */
+static double sys_residual = 0;     /* adjustment residue (s) */
+
+void (*event_ptr[]) (Event *) = {
+    sim_event_beep, sim_update_clocks, sim_event_timer, sim_event_recv_packet
+};                        /* Function pointer to the events */
+
+
+/* Define a function to compare two events to determine which one occurs first
  */
-void (*funcPtr[]) (Node *, Event) = {
-       &ndbeep, &ndeclk, &ntptmr, &netpkt
-};
 
+int determine_event_ordering(Event *e1, Event *e2)
+{
+    return (e1->time - e2->time);
+}
 
-/*
- * ntpsim - initialize global variables and event queue and start
+/* Define a function to compare two received packets to determine which one
+ * is received first
  */
-int
-ntpsim(
-       int     argc,
-       char    *argv[]
-       )
+int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2)
 {
-       Event   e;
-       double  maxtime;
-       struct timeval seed;
-
-       /*
-        * Initialize the global node
-        */
-       ntp_node.time = 0;              /* simulation time */
-       ntp_node.sim_time = SIM_TIME;   /* end simulation time (-S) */
-       ntp_node.ntp_time = 0;          /* client disciplined time */
-       ntp_node.adj = 0;               /* remaining time correction */
-       ntp_node.slew = SLEW;           /* correction rate (-H) */
-
-       ntp_node.clk_time = 0;          /* server time (-O) */
-       ntp_node.ferr = 0;              /* frequency error (-T) */
-       ntp_node.fnse = 0;              /* random walk noise (-W) */
-       ntp_node.ndly = NET_DLY;        /* network delay (-Y) */
-       ntp_node.snse = 0;              /* phase noise (-C) */
-       ntp_node.pdly = PROC_DLY;       /* processing delay (-Z) */
-       ntp_node.bdly = BEEP_DLY;       /* beep interval (-B) */
-
-       ntp_node.events = NULL;
-       ntp_node.rbuflist = NULL;
-
-       /*
-        * Initialize ntp variables
-        */
-       initializing = 1;
-        init_auth();
-        init_util();
-        init_restrict();
-        init_mon();
-        init_timer();
-        init_lib();
-        init_request();
-        init_control();
-        init_peer();
-        init_proto();
-        init_io();
-        init_loopfilter();
-        mon_start(MON_OFF);
-
-       {
-               int optct = optionProcess(&ntpdsimOptions, argc, argv);
-               argc -= optct;
-               argv += optct;
-       }
-
-       getconfig(argc, argv);
-
-        initializing = 0;
-       loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
-
-       /*
-        * Watch out here, we want the real time, not the silly stuff.
-        */
-       gettimeofday(&seed, NULL);
-       ntp_srandom(seed.tv_usec);
-
-       /*
-        * Push a beep and timer interrupt on the queue
-        */
-       push(event(0, BEEP), &ntp_node.events);
-       push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
-
-       /*
-        * Pop the queue until nothing is left or time is exceeded
-        */
-       maxtime = ntp_node.time + ntp_node.sim_time;
-       while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
-               e = pop(&ntp_node.events);
-               ndeclk(&ntp_node, e);
-               funcPtr[e.function](&ntp_node, e);
-       }
-       return (0);
+    double recv_time1, recv_time2;
+
+    /* Simply convert the time received to double and subtract */
+    LFPTOD(&b1->recv_time, recv_time1);
+    LFPTOD(&b2->recv_time, recv_time2);
+    return ((int)(recv_time1 - recv_time2));
 }
 
+/* Define a function to create the server associations */
+void create_server_associations()
+{
+    int i;
+    for (i = 0;i < simulation.num_of_servers;++i) {
+        printf("%s\n", stoa(simulation.servers[i].addr));
+        if (peer_config(simulation.servers[i].addr,
+                        ANY_INTERFACE_CHOOSE(simulation.servers[i].addr),
+                        MODE_CLIENT,
+                        NTP_VERSION,
+                        NTP_MINDPOLL,
+                        NTP_MAXDPOLL,
+                        0, /* peerflags */
+                        0, /* ttl */
+                        0, /* peerkey */
+                        (u_char *)"*" /* peerkeystr */) == 0) {
+            fprintf(stderr, "ERROR!! Could not create association for: %s",
+                    stoa(simulation.servers[i].addr));
+        }
+    }
+}
 
-/*
- * Return an event
- */
-Event
-event(
-       double t,
-       funcTkn f
-       )
+
+/* Main Simulator Code */
+int
+ntpsim(int argc, char *argv[])
 {
-       Event e;
+    Event *curr_event;
+    struct timeval seed;
+    
+    /* Initialize the local Clock 
+     */
+    simclock.local_time = 0;
+    simclock.adj = 0;
+    simclock.slew = 0;
+
+    /* Initialize the simulation 
+     */
+    simulation.num_of_servers = 0;
+    simulation.beep_delay = BEEP_DLY;
+    simulation.sim_time = 0;
+    simulation.end_time = SIM_TIME;
+
+    /* Parse the configuration file  
+     */
+/*     if (argc != 2) { */
+/*         fprintf(stderr, "USAGE: %s <ntpsim configuration file>\n", argv[0]); */
+/*         exit(1); */
+/*     } */
+/*     ip_file = fopen(argv[1], "r"); */
+/*     if (ip_file == NULL) { */
+/*         fprintf(stderr, "ERROR!!, Could not open file: %s\n", argv[1]); */
+/*         exit(1); */
+/*     } */
+/*     key_scanner = create_keyword_scanner(keyword_list); */
+/*     print_keyword_scanner(key_scanner, 0); */
+        
+/*     debug=1; */
+/*     yyparse(); */
+
+    /*
+     * Initialize ntp variables
+     */
+    initializing = 1;
+    init_auth();
+    init_util();
+    init_restrict();
+    init_mon();
+    init_timer();
+    init_lib();
+    init_request();
+    init_control();
+    init_peer();
+    init_proto();
+    init_io();
+    init_loopfilter();
+    mon_start(MON_OFF);    
+    /* Call getconfig to parse the configuration file */
+    getconfig(argc, argv);
+    initializing = 0;
+    loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
+    
+    /*
+     * Watch out here, we want the real time, not the silly stuff.
+     */
+    gettimeofday(&seed, NULL);
+    ntp_srandom(seed.tv_usec);
+        
+
+    /* Initialize the event queue */
+    event_queue = create_priority_queue((int(*)(void *, void*)) 
+                                        determine_event_ordering);
+
+    /* Initialize the receive queue */
+    recv_queue = create_priority_queue((int(*)(void *, void*))
+                                       determine_recv_buf_ordering);
+
+    /* Push a beep and a timer on the event queue */
+    enqueue(event_queue, event(0, BEEP));
+    enqueue(event_queue, event(simulation.sim_time + 1.0, TIMER));
+    /* 
+     * Pop the queue until nothing is left or time is exceeded
+     */
+    /* maxtime = simulation.sim_time + simulation.end_time;*/
+    while (simulation.sim_time <= simulation.end_time &&
+           (!empty(event_queue))) {
+        curr_event = dequeue(event_queue);
+        /* Update all the clocks to the time on the event */
+        sim_update_clocks(curr_event);
+        
+        /* Execute the function associated with the event */
+        event_ptr[curr_event->function](curr_event);
+        free_node(curr_event);
+    }
+    return (0);
+}
+
+
 
-       e.time = t;
-       e.function = f;
-       return (e);
+/* Define a function to create an return an Event  */
+
+Event *event(double t, funcTkn f)
+{
+    Event *e;
+    
+    if ((e = (Event *)get_node(sizeof(Event))) == NULL)
+        abortsim("get_node failed in event");
+    e->time = t;
+    e->function = f;
+    return (e);
 }
 
-/*
- * Create an event queue
+/* NTP SIMULATION FUNCTIONS */
+
+/* Define a function for processing a timer interrupt.
+ * On every timer interrupt, call the NTP timer to send packets and process
+ * the clock and then call the receive function to receive packets.
  */
-Queue
-queue(
-       Event e,
-       Queue q
-       )
+void sim_event_timer(Event *e)
 {
-       Queue ret;
+    struct recvbuf *rbuf;
+    
+    /* Call the NTP timer.
+     * This will be responsible for actually "sending the packets."
+     * Since this is a simulation, the packets sent over the network
+     * will be processed by the simulate_server routine below.
+     */
+    timer();
+    
+    /* Process received buffers */
+    while (!empty(recv_queue)) {
+        rbuf = (struct recvbuf *)dequeue(recv_queue);
+        (rbuf->receiver)(rbuf);
+        free_node(rbuf);
+    }
+    
+    /* Arm the next timer interrupt. */
+    enqueue(event_queue, 
+            event(simulation.sim_time + (1 << EVENT_TIMEOUT), TIMER));
+}
+
+
 
-       if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
-                abortsim("queue-malloc");
-       ret->event = e;
-       ret->next = q;
-       return (ret);
+/* Define a function to simulate a server.
+ * This function processes the sent packet according to the server script,
+ * creates a reply packet and pushes the reply packet onto the event queue
+ */
+int simulate_server(
+    struct sockaddr_storage *serv_addr, /* Address of the server */
+    struct interface *inter,            /* Interface on which the reply should
+                                           be inserted */
+    struct pkt *rpkt                    /* Packet sent to the server that
+                                           needs to be processed. */
+)
+{
+    struct pkt xpkt;           /* Packet to be transmitted back
+                                  to the client */
+    struct recvbuf rbuf;       /* Buffer for the received packet */
+    Event *e;                  /* Packet receive event */
+    server_info *server;       /* Pointer to the server being simulated */
+    script_info *curr_script;  /* Current script being processed */
+    int i;
+    double d1, d2, d3;         /* Delays while the packet is enroute */
+    double t1, t2, t3, t4;     /* The four timestamps in the packet */
+
+    /* Search for the server with the desired address */
+    server = NULL;
+    for (i = 0; i < simulation.num_of_servers; ++i) {
+        fprintf(stderr,"Checking address: %s\n", stoa(simulation.servers[i].addr));
+        if (memcmp(simulation.servers[i].addr, serv_addr, 
+                   sizeof(struct sockaddr_storage)) == 0) { 
+            server = &simulation.servers[i];
+            break;
+        }
+    }
+    
+    fprintf(stderr, "Received packet for: %s\n", stoa(serv_addr));
+    if (server == NULL)
+        abortsim("Server with specified address not found!!!");
+    
+    /* Get the current script for the server */
+    curr_script = server->curr_script;
+
+    /* Create a server reply packet. 
+     * Masquerade the reply as a stratum-1 server with a GPS clock
+     */
+    xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
+                                     MODE_SERVER);
+    xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
+    memcpy(&xpkt.refid, "GPS", 4);
+    xpkt.ppoll = rpkt->ppoll;
+    xpkt.precision = rpkt->precision;
+    xpkt.rootdelay = 0;
+    xpkt.rootdispersion = 0;
+    
+    /* TIMESTAMP CALCULATIONS
+            t1                           t4
+             \                          /
+          d1  \                        / d3
+               \                      /
+               t2 ----------------- t3
+                         d2
+    */
+    /* Compute the delays */
+    d1 = poisson(curr_script->prop_delay, curr_script->jitter);
+    d2 = poisson(curr_script->proc_delay, 0);
+    d3 = poisson(curr_script->prop_delay, curr_script->jitter);
+    
+    /* Note: In the transmitted packet: 
+     * 1. t1 and t4 are times in the client according to the local clock.
+     * 2. t2 and t3 are server times according to the simulated server.
+     * Compute t1, t2, t3 and t4
+     * Note: This function is called at time t1. 
+     */
+    
+    LFPTOD(&rpkt->xmt, t1);
+    t2 = server->server_time + d1;
+    t3 = server->server_time + d1 + d2;
+    t4 = t1 + d1 + d2 + d3;
+    
+    /* Save the timestamps */
+    xpkt.org = rpkt->xmt;     
+    DTOLFP(t2, &xpkt.rec);
+    DTOLFP(t3, &xpkt.xmt);
+    xpkt.reftime = xpkt.xmt;
+
+
+
+    /* Ok, we are done with the packet. Now initialize the receive buffer for
+     * the packet.
+     */
+    rbuf.receiver = receive;   /* Function to call to process the packet */
+    rbuf.recv_length = LEN_PKT_NOMAC;
+    rbuf.recv_pkt = xpkt;
+    
+    memcpy(&rbuf.srcadr, serv_addr, sizeof(struct sockaddr_storage));
+    memcpy(&rbuf.recv_srcadr, serv_addr, sizeof(struct sockaddr_storage));
+    if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
+        abortsim("malloc failed in simulate_server");
+    memcpy(rbuf.dstadr, inter, sizeof(struct interface));
+    /* rbuf.link = NULL; */
+
+    /* Create a packet event and insert it onto the event_queue at the 
+     * arrival time (t4) of the packet at the client 
+     */
+    e = event(t4, PACKET);
+    e->rcv_buf = rbuf;
+    enqueue(event_queue, e);
+    
+
+    /* Check if the time of the script has expired. If yes, delete the script.
+     * If not, re-enqueue the script onto the server script queue 
+     */
+    if (curr_script->duration > simulation.sim_time && 
+        !empty(server->script)) {
+        printf("Hello\n");
+        /* 
+         * For some reason freeing up the curr_script memory kills the
+         * simulation. Further debugging is needed to determine why.
+         * free_node(curr_script);
+         */
+        curr_script = dequeue(server->script);
+    }
+
+    return (0);
 }
 
 
-/*
- * Push an event into the event queue
+/* Define a function to update all the clocks 
+ * Most of the code is modified from the systime.c file by Prof. Mills
  */
-void push(
-       Event e,
-       Queue *qp
-       )
+
+void sim_update_clocks (Event *e)
 {
-       Queue *tmp = qp;
+    double time_gap;
+    double adj;
+    int i;
+        
+    /* Compute the time between the last update event and this update */
+    time_gap = e->time - simulation.sim_time;
+    
+    /* Advance the client clock */
+    simclock.local_time = e->time + time_gap;
+
+    /* Advance the simulation time */
+    simulation.sim_time = e->time;
+
+    /* Advance the server clocks adjusted for systematic and random frequency
+     * errors. The random error is a random walk computed as the
+     * integral of samples from a Gaussian distribution.
+     */
+    for (i = 0;i < simulation.num_of_servers; ++i) {
+        simulation.servers[i].curr_script->freq_offset +=
+            gauss(0, time_gap * simulation.servers[i].curr_script->wander);
+
+        simulation.servers[i].server_time += time_gap * 
+            (1 + simulation.servers[i].curr_script->freq_offset);
+    }
+    
+    
+    /* Perform the adjtime() function. If the adjustment completed
+     * in the previous interval, amortize the entire amount; if not,
+     * carry the leftover to the next interval.
+     */
+    
+    adj = time_gap * simclock.slew;
+    if (adj < fabs(simclock.adj)) {
+        if (simclock.adj < 0) {
+            simclock.adj += adj;
+            simclock.local_time -= adj;
+        } 
+        else {
+            simclock.adj -= adj;
+            simclock.local_time += adj;
+        }    
+    } 
+    else {
+        simclock.local_time += simclock.adj;
+        simclock.adj = 0;
+    }
+}
+
 
-       while (*tmp != NULL && ((*tmp)->event.time < e.time))
-               tmp = &((*tmp)->next);
-       *tmp = queue(e, (*tmp));
+/* Define a function that processes a receive packet event. 
+ * This function simply inserts the packet received onto the receive queue
+ */   
+
+void sim_event_recv_packet(Event *e)
+{
+    struct recvbuf *rbuf;
+    
+    /* Allocate a receive buffer and copy the packet to it */
+    if ((rbuf = (struct recvbuf *) get_node(sizeof(struct recvbuf))) == NULL)
+        abortsim("get_node failed in sim_event_recv_packet");
+    memcpy(rbuf, &e->rcv_buf, sizeof(struct recvbuf));
+    
+    /* Store the local time in the received packet */
+    DTOLFP(simclock.local_time, &rbuf->recv_time);
+    
+    /* Insert the packet received onto the receive queue */
+    enqueue(recv_queue, rbuf);
 }
 
 
-/*
- * Pop the first event from the event queue
+
+/* Define a function to output simulation statistics on a beep event
  */
-Event
-pop(
-       Queue *qp
-       )
+
+/*** TODO: Need to decide on how to output for multiple servers ***/
+void sim_event_beep(Event *e)
 {
-       Event ret;
-       Queue tmp;
-
-       tmp = *qp;
-       if (tmp == NULL)
-           abortsim("pop - empty queue");
-       ret = tmp->event;
-       *qp = tmp->next;
-       free(tmp);
-       return (ret);
+    static int first_time = 1;
+    char *dash = "-----------------";
+    fprintf(stderr, "BEEP!!!\n");
+    enqueue(event_queue, event(e->time + simulation.beep_delay, BEEP));
+/*
+    if(simulation.beep_delay > 0) {
+        if (first_time) {
+            printf("\t%4c    T    %4c\t%4c  T+ERR  %3c\t%5cT+ERR+NTP\n", 
+                   ' ', ' ', ' ', ' ',' ');
+            printf("\t%s\t%s\t%s\n", dash, dash, dash);
+            first_time = 0;
+            
+            printf("\t%16.6f\t%16.6f\t%16.6f\n",
+                   n->time, n->clk_time, n->ntp_time);
+            return;
+        }
+        printf("\t%16.6f\t%16.6f\t%16.6f\n",
+               simclock.local_time, 
+               
+               n->time, n->clk_time, n->ntp_time);
+*/
+        /* Enqueue the next beep onto the event queue */
+/*
+
+    }
+*/
+
 }
 
 
-/*
- * Update clocks
+/* Define a function to abort the simulation on an error and spit out an
+ * error message
  */
-void
-ndeclk(
-       Node *n,
-       Event e
-       )
+
+void abortsim(char *errmsg)
 {
-       node_clock(n, e.time);
+    perror(errmsg);
+    exit(1);
 }
 
 
+/* CODE ORIGINALLY IN libntp/systime.c 
+ * -----------------------------------
+ * This code was a part of the original NTP simulator and originally 
+ * had its home in the libntp/systime.c file. 
+ *
+ * It has been shamelessly moved to here and has been modified for the
+ * purposes of the current simulator.
+ */
+
+
 /*
- * Timer interrupt. Eventually, this results in calling the
- * srvr_rplyi() routine below.
+ * get_systime - return the system time in NTP timestamp format 
  */
 void
-ntptmr(
-       Node *n,
-       Event e
-       )
+get_systime(
+    l_fp *now          /* current system time in l_fp */        )
 {
-       struct recvbuf *rbuf;
-
-       timer();
-
-       /*
-        * Process buffers received. They had better be in order by
-        * receive timestamp. Note that there are no additional buffers
-        * in the current implementation of ntpsim.
-        */
-       while (n->rbuflist != NULL) {
-               rbuf = n->rbuflist;
-               n->rbuflist = NULL;
-               (rbuf->receiver)(rbuf);
-               free(rbuf);
-       }
-
-       /*
-        * Arm the next timer interrupt.
-        */
-       push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
+    /*
+     * To fool the code that determines the local clock precision,
+     * we advance the clock a minimum of 200 nanoseconds on every
+     * clock read. This is appropriate for a typical modern machine
+     * with nanosecond clocks. Note we make no attempt here to
+     * simulate reading error, since the error is so small. This may
+     * change when the need comes to implement picosecond clocks.
+     */
+    if (simclock.local_time == simclock.last_read_time)
+        simclock.local_time += 200e-9;
+
+    simclock.last_read_time = simclock.local_time;
+    DTOLFP(simclock.local_time, now);
+/* OLD Code
+   if (ntp_node.ntp_time == ntp_node.last_time)
+   ntp_node.ntp_time += 200e-9;
+   ntp_node.last_time = ntp_node.ntp_time;
+   DTOLFP(ntp_node.ntp_time, now);
+*/
 }
-
-
 /*
- * srvr_rply() - send packet
+ * adj_systime - advance or retard the system clock exactly like the
+ * real thng.
  */
-int srvr_rply(
-       Node *n,
-       struct sockaddr_storage *dest,
-       struct interface *inter, struct pkt *rpkt
-       )
+int                            /* always succeeds */
+adj_systime(
+    double now         /* time adjustment (s) */
+    )
 {
-       struct pkt xpkt;
-       struct recvbuf rbuf;
-       Event   xvnt;
-       double  dtemp, etemp;
-
-       /*
-        * Insert packet header values. We make this look like a
-        * stratum-1 server with a GPS clock, but nobody will ever
-        * notice that.
-        */
-       xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
-           MODE_SERVER);
-       xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
-       memcpy(&xpkt.refid, "GPS", 4);
-       xpkt.ppoll = rpkt->ppoll;
-        xpkt.precision = rpkt->precision;
-        xpkt.rootdelay = 0;
-        xpkt.rootdispersion = 0;
-
-       /*
-        * Insert the timestamps.
-        */
-        xpkt.org = rpkt->xmt;
-       dtemp = poisson(n->ndly, n->snse); /* client->server delay */
-       DTOLFP(dtemp + n->clk_time, &xpkt.rec);
-       dtemp += poisson(n->pdly, 0);   /* server delay */
-       DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
-       xpkt.reftime = xpkt.xmt;
-       dtemp += poisson(n->ndly, n->snse); /* server->client delay */
-
-       /*
-        * Insert the I/O stuff.
-        */
-       rbuf.receiver = receive;
-        get_systime(&rbuf.recv_time);
-        rbuf.recv_length = LEN_PKT_NOMAC;
-        rbuf.recv_pkt = xpkt;
-        memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
-        memcpy(&rbuf.recv_srcadr, dest,
-           sizeof(struct sockaddr_storage));
-        if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
-               abortsim("server-malloc");
-        memcpy(rbuf.dstadr, inter, sizeof(struct interface));
-
-       /*
-        * Very carefully predict the time of arrival for the received
-        * packet. 
-        */ 
-       LFPTOD(&xpkt.org, etemp);
-       etemp += dtemp;
-       xvnt = event(etemp, PACKET);
-       xvnt.rcv_buf = rbuf;
-       push(xvnt, &n->events);
-       return (0);
+    struct timeval adjtv;      /* new adjustment */
+    double     dtemp;
+    long       ticks;
+    int        isneg = 0;
+
+    /*
+     * Most Unix adjtime() implementations adjust the system clock
+     * in microsecond quanta, but some adjust in 10-ms quanta. We
+     * carefully round the adjustment to the nearest quantum, then
+     * adjust in quanta and keep the residue for later.
+     */
+    dtemp = now + sys_residual;
+    if (dtemp < 0) {
+        isneg = 1;
+        dtemp = -dtemp;
+    }
+    adjtv.tv_sec = (long)dtemp;
+    dtemp -= adjtv.tv_sec;
+    ticks = (long)(dtemp / sys_tick + .5);
+    adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
+    dtemp -= adjtv.tv_usec / 1e6;
+    sys_residual = dtemp;
+
+    /*
+     * Convert to signed seconds and microseconds for the Unix
+     * adjtime() system call. Note we purposely lose the adjtime()
+     * leftover.
+     */
+    if (isneg) {
+        adjtv.tv_sec = -adjtv.tv_sec;
+        adjtv.tv_usec = -adjtv.tv_usec;
+        sys_residual = -sys_residual;
+    }
+    simclock.adj = now;
+/*     ntp_node.adj = now; */
+    return (1);
 }
-
-
 /*
- * netpkt() - receive packet
+ * step_systime - step the system clock. We are religious here.
  */
-void
-netpkt(
-       Node *n,
-       Event e
-       )
+int                            /* always succeeds */
+step_systime(
+    double now         /* step adjustment (s) */
+    )
 {
-       struct recvbuf *rbuf;
-       struct recvbuf *obuf;
-
-       /*
-        * Insert the packet on the receive queue and record the arrival
-        * time.
-        */
-       if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
-               abortsim("ntprcv-malloc");
-       memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
-       rbuf->receiver = receive;
-       DTOLFP(n->ntp_time, &rbuf->recv_time);
-       obuf = n->rbuflist;
-
-       /*
-        * In the present incarnation, no more than one buffer can be on
-        * the queue; 
-        */
-       if (obuf == NULL) {
-               n->rbuflist = rbuf;
-       }
+#ifdef DEBUG
+    if (debug)
+        printf("step_systime: time %.6f adj %.6f\n",
+               simclock.local_time, now);
+#endif
+    simclock.local_time += now;
+    return (1);
 }
-
-
 /*
- * ndbeep() - progress indicator
+ * gauss() - returns samples from a gaussion distribution
  */
-void
-ndbeep(
-       Node *n,
-       Event e
-       )
+double                         /* Gaussian sample */
+gauss(
+    double m,          /* sample mean */
+    double s           /* sample standard deviation (sigma) */
+    )
 {
-       static int first_time = 1;
-       char *dash = "-----------------";
-
-       if(n->bdly > 0) {
-               if (first_time) {
-                       printf(
-                           "\t%4c    T    %4c\t%4c  T+ERR  %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
-                       printf("\t%s\t%s\t%s\n", dash, dash, dash);
-                       first_time = 0;
-                       push(event(n->bdly, BEEP), &n->events);  
-                       push(event(n->sim_time, BEEP), &n->events);
-                       printf("\t%16.6f\t%16.6f\t%16.6f\n",
-                            n->time, n->clk_time, n->ntp_time);
-                       return;
-               }
-               printf("\t%16.6f\t%16.6f\t%16.6f\n",
-                   n->time, n->clk_time, n->ntp_time);
-               push(event(e.time + n->bdly, BEEP), &n->events);
-       }
+    double q1, q2;
+
+    /*
+     * Roll a sample from a Gaussian distribution with mean m and
+     * standard deviation s. For m = 0, s = 1, mean(y) = 0,
+     * std(y) = 1.
+     */
+    if (s == 0)
+        return (m);
+    while ((q1 = drand48()) == 0);
+    q2 = drand48();
+    return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
 }
 
-
 /*
- * Abort simulation
+ * poisson() - returns samples from a network delay distribution
  */
-void
-abortsim(
-       char *errmsg
-       )
+double                         /* delay sample (s) */
+poisson(
+    double m,          /* fixed propagation delay (s) */
+    double s           /* exponential parameter (mu) */
+    )
 {
-        perror(errmsg);
-        exit(1);
+    double q1;
+
+    /*
+     * Roll a sample from a composite distribution with propagation
+     * delay m and exponential distribution time with parameter s.
+     * For m = 0, s = 1, mean(y) = std(y) = 1.
+     */
+    if (s == 0)
+        return (m);
+    while ((q1 = drand48()) == 0);
+    return (m - s * log(q1 * s));
 }
index 93551bd72b0ae1b681e8d3a056d2904390ad4ad7..879c208d44ae90a363ae8c21df4298fe16f794c6 100644 (file)
@@ -63,6 +63,8 @@ static        void    lpeers          P((struct parse *, FILE *));
 static void    doopeers        P((int, FILE *, int));
 static void    opeers          P((struct parse *, FILE *));
 static void    lopeers         P((struct parse *, FILE *));
+static  void    config          P((struct parse *, FILE *));
+static  void    config_from_file P((struct parse *, FILE *));
 
 
 /*
@@ -150,6 +152,12 @@ struct xcmd opcmds[] = {
        { "lopeers", lopeers,   { OPT|IP_VERSION, NO, NO, NO },
          { "-4|-6", "", "", "" },
          "obtain and print a list of all peers and clients showing dstadr [IP version]" },
+       { "config", config,   { NTP_STR, NO, NO, NO },
+         { "<configuration command>", "", "", "" },
+         "send a remote configuration command to ntpd" },
+        { "config-from-file", config_from_file, { NTP_STR, NO, NO, NO },
+          { "<configuration filename>", "", "", "" },
+          "configure ntpd using the configuration filename" },
        { 0,            0,              { NO, NO, NO, NO },
          { "-4|-6", "", "", "" }, "" }
 };
@@ -158,6 +166,7 @@ struct xcmd opcmds[] = {
 /*
  * Variable list data space
  */
+#define MAXLINE     512  /* maximum length of a line */
 #define MAXLIST        64      /* maximum number of variables in list */
 #define LENHOSTNAME 256 /* host name is 256 characters long */
 /*
@@ -1766,3 +1775,84 @@ lopeers(
        }
        doopeers(1, fp, af);
 }
+
+
+/* 
+ * config - send a configuration command to a remote host
+ */
+static void 
+config (
+       struct parse *pcmd,
+       FILE *fp
+       )
+{
+    u_short rstatus;
+    int rsize;
+    char *rdata;
+    int res;
+
+    if (debug > 2) {
+        printf("In Config\n");
+        printf("Keyword = %s\n", pcmd->keyword);
+        printf("Command = %s\n", pcmd->argval[0].string);
+    }
+    
+    res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(pcmd->argval[0].string),
+                  pcmd->argval[0].string, &rstatus,
+                  &rsize, &rdata);
+    rdata[rsize] = '\0';
+    printf("%s\n", rdata);
+
+}
+
+/* 
+ * config_from_file - remotely configure an ntpd daemon using the
+ * specified configuration file
+ * SK: This function is a kludge at best and is full of bad design
+ * bugs:
+ * 1. ntpq uses UDP, which means that there is no guarantee of in-order,
+ *    error-free delivery. 
+ * 2. The maximum length of a packet is constrained, and as a result, the
+ *    maximum length of a line in a configuration file is constrained. 
+ *    Longer lines will lead to unpredictable results.
+ * 3. Since this function is sending a line at a time, we can't update
+ *    the control key through the configuration file (YUCK!!)
+ */
+static void 
+config_from_file (
+       struct parse *pcmd,
+       FILE *fp
+       )
+{
+    u_short rstatus;
+    int rsize;
+    char *rdata;
+    int res;
+    FILE *config_fd;
+    char config_cmd[MAXLINE];
+
+    if (debug > 2) {
+        printf("In Config\n");
+        printf("Keyword = %s\n", pcmd->keyword);
+        printf("Filename = %s\n", pcmd->argval[0].string);
+    }
+
+    if ((config_fd = fopen(pcmd->argval[0].string, "r")) == NULL) {
+        printf("ERROR!! Couldn't open file: %s\n", pcmd->argval[0].string);
+    } 
+    else {
+        int i = 0;
+        printf("Sending configuration file, one line at a time.\n");
+        while (fgets(config_cmd, MAXLINE, config_fd) != NULL) {
+            ++i;
+            res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(config_cmd),
+                          config_cmd, &rstatus,
+                          &rsize, &rdata);
+            printf("Line No: %d ", i);
+            rdata[rsize] = '\0';
+            printf(rdata);
+        }
+        printf("Done sending file\n");
+        fclose(config_fd);
+    }
+}
index 91379408ff7c96b6bf8176b8782aa1706014ad4b..462724d9be50674d54a36107eb3755c7f412dbc0 100644 (file)
@@ -1528,6 +1528,12 @@ docmd(
 /*
  * tokenize - turn a command line into tokens
  */
+
+
+/* SK:
+ * Modified to allow a quoted string 
+ */
+
 static void
 tokenize(
        const char *line,
@@ -1547,16 +1553,27 @@ tokenize(
                    cp++;
                if (ISEOL(*cp))
                    break;
-               do {
+
+                /* Check if the next token begins with a double quote.
+                 * If yes, continue reading till the next double quote
+                 */
+                if (*cp == '\"') {
+                    ++cp;
+                    do {
+                        *sp++ = *cp++;
+                    } while ((*cp != '\"') && !ISEOL(*cp));
+                }
+                else {
+                    do {
                        *sp++ = *cp++;
-               } while (!ISSPACE(*cp) && !ISEOL(*cp));
+                    } while ((*cp != '\"') && !ISSPACE(*cp) && !ISEOL(*cp));
+                }
 
                *sp++ = '\0';
        }
 }
 
 
-
 /*
  * findcmd - find a command in a command description table
  */