]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Merge pogo.udel.edu:/pogo/users/kardel/main-line/ntp-stable
authorHarlan Stenn <stenn@ntp.org>
Wed, 15 Aug 2007 07:04:56 +0000 (03:04 -0400)
committerHarlan Stenn <stenn@ntp.org>
Wed, 15 Aug 2007 07:04:56 +0000 (03:04 -0400)
into  pogo.udel.edu:/pogo/users/stenn/ntp-dev

bk: 46c2a598JcKvc4YfzfFg6E2xbRVopg

1  2 
ChangeLog
ntpd/cmd_args.c
ntpd/ntp_config.c
ntpd/ntp_io.c
ntpd/refclock_parse.c

diff --cc ChangeLog
index 00a560dc3385c918dd54a2e36ce1e00fd556d5c2,11e1dde1c8bbc8fa16bbdf3e9831dc69b2c877d7..d50d203f9e94bd18bead00897ea8634be8a328fb
+++ b/ChangeLog
  
  * [Bug 854] Broadcast address was not correctly set for interface addresses
  * [Bug 829] reduce syslog noise, while there fix Enabled/Disable logging
 -          to reflect the actual configuration.
 +  to reflect the actual configuration.
  * [Bug 795] Moved declaration of variable to top of function.
  * [Bug 789] Fix multicast client crypto authentication and make sure arriving
 -          multicast packets do not disturb the autokey dance.
 +  multicast packets do not disturb the autokey dance.
  * [Bug 785] improve handling of multicast interfaces
 -          (multicast routers still need to run a multicast routing
 -          software/daemon)
 +  (multicast routers still need to run a multicast routing software/daemon)
++* ntpd/refclock_parse.c: cleanup shutdown while the file descriptor is still
++  open.
++* [Bug 885] use emalloc() to get a message at the end of the memory
++  unsigned types cannot be less than 0
++  default_ai_family is a short
++  lose trailing , from enum list
++* [Bug 884] don't access recv buffers after having them passed to the free list.
++* [Bug 882] allow loopback interfaces to share addresses with other interfaces.
  * [Bug 527] Don't write from source address length to wrong location
  * Upgraded autogen and libopts.
  * [Bug 811] ntpd should not read a .ntprc file.
diff --cc ntpd/cmd_args.c
Simple merge
index 065fe194f88f8c97b73685dbfe9fad2fc196b653,05af3ffc2074d549e903e694405c32aec7f90ee1..b47e18bfc3eeb27238e866f7d0e8835db150dc1d
@@@ -221,1826 -406,1461 +221,1826 @@@ void getconfig(int argc,char *argv[])
  enum gnn_type {
        t_UNK,          /* Unknown */
        t_REF,          /* Refclock */
-       t_MSK,          /* Network Mask */
+       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);
 +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);
 +
 +
 +/* FUNCTIONS FOR INITIALIZATION
 + * ----------------------------
   */
 -static unsigned long
 -get_pfxmatch(
 -      char ** s,
 -      struct masks *m
 +
 +static int
 +get_flags_from_list(
 +      queue *flag_list
        )
  {
 -      while (m->name) {
 -              if (strncmp(*s, m->name, strlen(m->name)) == 0) {
 -                      *s += strlen(m->name);
 -                      return m->mask;
 -              } else {
 -                      m++;
 -              }
 +      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 0;
 +      return flags;
  }
  
 -/*
 - * get_match - find logmask value
 - */
 -static unsigned long
 -get_match(
 -      char *s,
 -      struct masks *m
 -      )
 +static void
 +init_auth_node(void)
  {
 -      while (m->name) {
 -              if (strcmp(s, m->name) == 0) {
 -                      return m->mask;
 -              } else {
 -                      m++;
 -              }
 -      }
 -      return 0;
 +      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;
  }
  
 -/*
 - * get_logmask - build bitmask for ntp_syslogmask
 - */
 -static unsigned long
 -get_logmask(
 -      char *s
 -      )
 +static void
 +init_syntax_tree(void)
  {
 -      char *t;
 -      unsigned long offset;
 -      unsigned long mask;
 +      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();
 +}
  
 -      t = s;
 -      offset = get_pfxmatch(&t, logcfg_class);
 -      mask   = get_match(t, logcfg_item);
 +/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE 
 + * -----------------------------------------------
 + */
  
 -      if (mask)
 -              return mask << offset;
 -      else
 -              msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
 +queue *
 +enqueue_in_new_queue(
 +      void *my_node
 +      )
 +{ 
 +      queue *my_queue = create_queue();
  
 -      return 0;
 +      enqueue(my_queue, my_node);
 +      return my_queue;
  }
  
 -
 -/*
 - * getconfig - get command line options and read the configuration file
 - */
 -void
 -getconfig(
 -      int argc,
 -      char *argv[]
 +struct attr_val *
 +create_attr_dval(
 +      int attr,
 +      double value
        )
  {
 -      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;
 +      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;
 +}
  
 -      /*
 -       * 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;
 +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;
 +}
  
 -      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;
 +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;
 +      if (s == NULL) 
 +              s = "\0";       /* free() and strdup() glow on NULL */
 +      my_val->value.s = strdup(s);
 +      my_val->type = T_String;
 +      return my_val;
 +}
  
 -#endif /* SYS_WINNT */
 -      res_fp = NULL;
 -      ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
 +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;
 +}
  
 -      /*
 -       * install a non default variable with this daemon version
 -       */
 -      (void) sprintf(line, "daemon_version=\"%s\"", Version);
 -      set_sys_var(line, strlen(line)+1, RO);
 +int *
 +create_ival(
 +      int val
 +      )
 +{
 +      int *p = (int *)get_node(sizeof(int));
  
 -      /*
 -       * 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);
 +      *p = val;
 +      return p;
 +}
  
 -      /*
 -       * Initialize the loop.
 -       */
 -      loop_config(LOOP_DRIFTINIT, 0.);
 +double *
 +create_dval(
 +      double val
 +      )
 +{
 +      double *p = (double *) get_node(sizeof(int));
  
 -      getCmdOpts(argc, argv);
 +      *p = val;
 +      return p;
 +}
  
 -      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 */
 +void **
 +create_pval(
 +      void *val
 +      )
 +{
 +      void **p = (void **) get_node(sizeof(void *));
  
 -              if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
 +      *p = val;
 +      return p;
 +}
  
 -                      /*
 -                       * Broadcast clients can sometimes run without
 -                       * a configuration file.
 -                       */
 +struct address_node *
 +create_address_node(
 +      char *addr,
 +      int type
 +      )
 +{
 +      struct address_node *my_node = (struct address_node *) 
 +          get_node(sizeof(struct address_node));
  
 -                      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 */
 -      }
 +      my_node->address = addr;
 +      my_node->type = type;
 +      return my_node;
 +}
  
 -      for (;;) {
 -              if (tok == CONFIG_END) 
 +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;
 -              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 {
 +                  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;
 +}
  
 -              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;
 +struct filegen_node *
 +create_filegen_node(
 +      void **name, 
 +      queue *options
 +      )
 +{
 +      struct filegen_node *my_node = (struct filegen_node *)
 +          get_node(sizeof(struct filegen_node));
  
 -                      if (ntokens < 2) {
 -                              msyslog(LOG_ERR,
 -                                      "No address for %s, line ignored",
 -                                      tokens[0]);
 -                              break;
 -                      }
 +      my_node->name = (char *) *name;
 +      free_node(name);
  
 -                      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;
 -                      }
 +      my_node->options = options;
 +      return my_node;
 +}
  
 -                      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;
 +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;
 +}
  
 -                      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;
 +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);
 +}
  
 -#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;
 +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_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;
 +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));
  
 -                  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;
 +      my_node->addr = addr;
 +      my_node->options = options;
 +      return my_node;
 +}
  
 -                  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;
 +script_info *
 +create_sim_script_info(
 +      double duration,
 +      queue *script_queue
 +      )
 +{
 +#ifdef SIM
 +      return NULL;
 +#else
 +      script_info *my_info;
 +      struct attr_val *my_attr_val;
 +      my_info = (script_info *)get_node(sizeof(script_info));
 +      /* XXX: check the return value... */
 +
 +      /* 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 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);
 -
 -                                      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");
 +                  case T_Wander:
 +                      my_info->wander = my_attr_val->value.d;
                        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
 -                      }
 +                  case T_Jitter:
 +                      my_info->jitter = my_attr_val->value.d;
                        break;
 -
 -                  case CONFIG_BROADCASTCLIENT:
 -                      if (ntokens == 1) {
 -                              proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
 -                      } else {
 -                              proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
 -                      }
 +                  case T_Prop_Delay:
 +                      my_info->prop_delay = my_attr_val->value.d;
                        break;
 -
 -                  case CONFIG_MULTICASTCLIENT:
 -                  case CONFIG_MANYCASTSERVER:
 -                      if (ntokens > 1) {
 -                              istart = 1;
 -                              memset((char *)&peeraddr, 0, sizeof(peeraddr));
 -                              peeraddr.ss_family = default_ai_family;
 -                              switch (matchkey(tokens[istart],
 -                                  addr_type, 0)) {
 -                              case CONF_ADDR_IPV4:
 -                                      peeraddr.ss_family = AF_INET;
 -                                      istart++;
 -                                      break;
 -                              case CONF_ADDR_IPV6:
 -                                      peeraddr.ss_family = AF_INET6;
 -                                      istart++;
 -                                      break;
 -                              }
 -                              /*
 -                               * Abuse maskaddr to store the prefered ip
 -                               * version.
 -                               */
 -                              memset((char *)&maskaddr, 0, sizeof(maskaddr));
 -                              maskaddr.ss_family = peeraddr.ss_family;
 -
 -                              for (i = istart; i < ntokens; i++) {
 -                                      memset((char *)&peeraddr, 0,
 -                                          sizeof(peeraddr));
 -                                      peeraddr.ss_family = maskaddr.ss_family;
 -                                      if (getnetnum(tokens[i], &peeraddr, 1,
 -                                                    t_UNK)  == 1)
 -                                          proto_config(PROTO_MULTICAST_ADD,
 -                                                       0, 0., &peeraddr);
 -                              }
 -                      } else
 -                          proto_config(PROTO_MULTICAST_ADD,
 -                                       0, 0., NULL);
 -                      if (tok == CONFIG_MULTICASTCLIENT)
 -                              proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
 -                      else if (tok == CONFIG_MANYCASTSERVER)
 -                              sys_manycastserver = 1;
 +                  case T_Proc_Delay:
 +                      my_info->proc_delay = my_attr_val->value.d;
                        break;
 -
 -                  case CONFIG_KEYS:
 -                      if (ntokens >= 2) {
 -                              getauthkeys(tokens[1]);
 -                      }
 +                  default:
 +                      yyerror("ERROR!! Invalid script info in file\n");
                        break;
 +              }
 +              free_node(my_attr_val);
 +      }
 +      destroy_queue(script_queue);
 +      return (my_info);
 +#endif
 +}
  
 -                  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;
  
 -                  case CONFIG_TINKER:
 -                      for (i = 1; i < ntokens; i++) {
 -                          int temp;
 -                          double ftemp;
 +#define ADDR_LENGTH 16 + 1
  
 -                          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) {
 +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];
  
 -                          case CONF_CLOCK_MAX:
 -                                loop_config(LOOP_MAX, ftemp);
 -                              break;
 +      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 CONF_CLOCK_PANIC:
 -                              loop_config(LOOP_PANIC, ftemp);
 -                              break;
 +server_info *
 +create_sim_server(
 +      struct address_node *addr,
 +      double server_offset,
 +      queue *script
 +      )
 +{
 +#ifdef SIM
 +      return NULL;
 +#else
 +      server_info *my_info;
 +      my_info = (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;
 +#endif /* SIM */
 +}
  
 -                          case CONF_CLOCK_PHI:
 -                              loop_config(LOOP_PHI, ftemp);
 -                              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));
  
 -                          case CONF_CLOCK_MINSTEP:
 -                              loop_config(LOOP_MINSTEP, ftemp);
 -                              break;
 +      my_node->init_opts = init_opts;
 +      my_node->servers = servers;
 +      return my_node;
 +}
  
 -                          case CONF_CLOCK_ALLAN:
 -                              loop_config(LOOP_ALLAN, ftemp);
 -                              break;
  
 -                          case CONF_CLOCK_HUFFPUFF:
 -                              loop_config(LOOP_HUFFPUFF, ftemp);
 -                              break;
 +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 },
 +      { "leapfile",           T_Leapfile,        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}
 +};
  
 -                          case CONF_CLOCK_FREQ:
 -                              loop_config(LOOP_FREQ, ftemp);
 -                              break;  
 -                          }
 -                      }
 -                      break;
  
 -                  case CONFIG_TOS:
 -                      for (i = 1; i < ntokens; i++) {
 -                          int temp;
 -                          double ftemp;
 +/* FUNCTIONS FOR PERFORMING THE CONFIGURATION
 + * ------------------------------------------
 + */
  
 -                          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) {
 +static void
 +config_other_modes(void)
 +{
  
 -                          case CONF_TOS_MINCLOCK:
 -                              proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
 -                              break;
 +      struct sockaddr_storage addr_sock;
 +      struct address_node *addr_node;
  
 -                          case CONF_TOS_MAXCLOCK:
 -                              proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
 -                              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_TOS_MINSANE:
 -                              proto_config(PROTO_MINSANE, 0, ftemp, NULL);
 -                              break;
  
 -                          case CONF_TOS_FLOOR:
 -                              proto_config(PROTO_FLOOR, 0, ftemp, NULL);
 -                              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);
 +#ifdef OPENSSL
 +                      crypto_config(my_val->attr, my_val->value.s);
 +#else
 +                      printf("Warning: Code not built with OpenSSL libraries!\n"
 +                             "Crypto commands are ignored\n");
 +                      msyslog(LOG_ERR, "config_auth: Crypto commands are ignored\n");
 +#endif
 +            
 +                      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_TOS_CEILING:
 -                              proto_config(PROTO_CEILING, 0, ftemp, NULL);
 -                              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;
 +      }
 +    
 +#ifdef OPENSSL
 +      /* Revoke Command */
 +      if (my_config.auth.revoke) 
 +              sys_revoke = my_config.auth.revoke;
 +#endif /* OPENSSL */
  
 -                          case CONF_TOS_COHORT:
 -                              proto_config(PROTO_COHORT, 0, ftemp, NULL);
 -                              break;
 +#if !defined(VMS) && !defined(SYS_VXWORKS)
 +      /* find a keyid */
 +      if (info_auth_keyid == 0)
 +              req_keyid = 65535;
 +      else
 +              req_keyid = info_auth_keyid;
  
 -                          case CONF_TOS_MINDISP:
 -                              proto_config(PROTO_MINDISP, 0, ftemp, NULL);
 -                              break;
 +      /* 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;
  
 -                          case CONF_TOS_MAXDIST:
 -                              proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
 -                              break;
 +              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_TOS_MAXHOP:
 -                              proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
 -                              break;
 +      /* save keyid so we will accept config requests with it */
 +      info_auth_keyid = req_keyid;
 +#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
  
 -                          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;
 +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 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 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.
 +       */
  
 -                  case CONFIG_DISCARD:
 -                      for (i = 1; i < ntokens; i++) {
 -                          int temp;
 +      /* Turn on the specified statistics */
 +      while (!empty(my_config.stats_list)) {
 +              filegen_string = (char **) dequeue(my_config.stats_list);
 +              filegen = filegen_get(*filegen_string);
  
 -                          temp = matchkey(tokens[i++],
 -                              discard_keywords, 1);
 -                          if (i > ntokens - 1) {
 -                              msyslog(LOG_ERR,
 -                                  "discard: missing argument");
 -                              errflg++;
 +#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;
 -                          }
 -                          switch(temp) {
 -                          case CONF_DISCARD_AVERAGE:
 -                              res_avg_interval = atoi(tokens[i]);
 +                          case T_Type:
 +                              filegen_type = my_opts->value.i;
                                break;
 -
 -                          case CONF_DISCARD_MINIMUM:
 -                              res_min_interval = atoi(tokens[i]);
 +                          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 CONF_DISCARD_MONITOR:
 -                              mon_age = atoi(tokens[i]);
 -                              break;
  
 -                          default:
 -                              msyslog(LOG_ERR,
 -                                  "discard: unknown keyword");
 -                              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;
 -
 -#ifdef OPENSSL
 -                  case CONFIG_REVOKE:
 -                      if (ntokens >= 2)
 -                          sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
 +                  case T_Minimum:
 +                      res_min_interval = my_opt->value.i;
                        break;
 -
 -                  case CONFIG_AUTOMAX:
 -                      if (ntokens >= 2)
 -                          sys_automax = 1 << max(atoi(tokens[1]), 10);
 +                  case T_Monitor:
 +                      mon_age = my_opt->value.i;
                        break;
 +              }
 +              free_node(my_opt);
 +      }
  
 -                  case CONFIG_CRYPTO:
 -                      if (ntokens == 1) {
 -                              crypto_config(CRYPTO_CONF_NONE, NULL);
 -                              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;
                        }
 -                      for (i = 1; i < ntokens; i++) {
 -                          int temp;
 +            
 +                      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);
 +      }
 +}
  
 -                          temp = matchkey(tokens[i++],
 -                               crypto_keywords, 1);
 -                          if (i > ntokens - 1) {
 -                              msyslog(LOG_ERR,
 -                                  "crypto: missing argument");
 -                              errflg++;
 -                              break;
 -                          }
 -                          switch(temp) {
  
 -                          case CONF_CRYPTO_CERT:
 -                              crypto_config(CRYPTO_CONF_CERT,
 -                                  tokens[i]);
 -                              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 CONF_CRYPTO_RSA:
 -                              crypto_config(CRYPTO_CONF_PRIV,
 -                                  tokens[i]);
 -                              break;
  
 -                          case CONF_CRYPTO_IDENT:
 -                              crypto_config(CRYPTO_CONF_IDENT,
 -                                  tokens[i]);
 -                              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 CONF_CRYPTO_IFFPAR:
 -                              crypto_config(CRYPTO_CONF_IFFPAR,
 -                                  tokens[i]);
 -                              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 CONF_CRYPTO_GQPAR:
 -                              crypto_config(CRYPTO_CONF_GQPAR,
 -                                  tokens[i]);
 -                              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);
 +      }
 +      if (i)
 +              sys_phone[i] = NULL;
 +}
  
 -                          case CONF_CRYPTO_MVPAR:
 -                              crypto_config(CRYPTO_CONF_MVPAR,
 -                                  tokens[i]);
 -                              break;
 -
 -                          case CONF_CRYPTO_LEAP:
 -                              crypto_config(CRYPTO_CONF_LEAP,
 -                                  tokens[i]);
 -                              break;
 -
 -                          case CONF_CRYPTO_PW:
 -                              crypto_config(CRYPTO_CONF_PW,
 -                                  tokens[i]);
 -                              break;
 -
 -                          case CONF_CRYPTO_RAND:
 -                              crypto_config(CRYPTO_CONF_RAND,
 -                                  tokens[i]);
 -                              break;
 -
 -                          case CONF_CRYPTO_SIGN:
 -                              crypto_config(CRYPTO_CONF_SIGN,
 -                                  tokens[i]);
 -                              break;
 -
 -                          default:
 -                              msyslog(LOG_ERR,
 -                                  "crypto: unknown keyword");
 -                              break;
 -                          }
 -                      }
 -                      break;
 -#endif /* OPENSSL */
 -
 -                  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;
 -
 -                      /*
 -                       * 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;
 +static void
 +config_setvar(void)
 +{
 +      struct setvar_node *my_node;
  
 -                                  case CONF_RES_DEMOBILIZE:
 -                                      peerversion |= RES_DEMOBILIZE;
 -                                      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);
 +      }
 +}
  
 -                                  case CONF_RES_LIMITED:
 -                                      peerversion |= RES_LIMITED;
 -                                      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;
 +}
  
 -                                  case CONFIG_UNKNOWN:
 -                                      errflg++;
 -                                      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;
                                }
                        }
 -                      if (SOCKNUL(&peeraddr))
 -                          ANYSOCK(&maskaddr);
 -                      if (!errflg)
 -                          hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
 -                                        (int)peerkey, peerversion);
 -                      break;
 -
 -                  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);
 +                      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;
                                }
 -                      }
 -                      break;
 -
 -                  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;
 -
 -                  case CONFIG_TRUSTEDKEY:
 -                      for (i = 1; i < ntokens; i++) {
 -                              keyid_t tkey;
 -
 -                              tkey = atol(tokens[i]);
 -                              if (tkey == 0) {
 +                
 +                              localaddr = findinterface(&addr_sock);
 +                
 +                              if (localaddr == NULL) {
                                        msyslog(LOG_ERR,
 -                                              "trusted key %s unlikely",
 -                                              tokens[i]);
 -                              } else {
 -                                      authtrust(tkey, 1);
 +                                              "can't find interface with address %s",
 +                                              stoa(&addr_sock));
 +                                      err_flag = 1;
                                }
 +                
 +                              free(addr_node->address);
 +                              free_node(addr_node);
                        }
 -                      break;
 +                      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);
  
 -                  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;
 -                              }
 +                      if (localaddr == NULL) {
 +                              peeraddr.ss_family = default_ai_family;
 +                              localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
                        }
 -                      break;
 -
 -                  case CONFIG_CONTROLKEY:
 -                      if (ntokens >= 2) {
 -                              keyid_t ckey;
 +                      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);
 +      }    
 +}
  
 -                              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_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;
 +              }
  
 -                  case CONFIG_TRAP:
 -                      if (ntokens < 2) {
 -                              msyslog(LOG_ERR,
 -                                      "no address for trap command, line ignored");
 +              /* 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;
 -                      }
 -                      istart = 1;
 -                      memset((char *)&peeraddr, 0, sizeof(peeraddr));
 -                      peeraddr.ss_family = default_ai_family;
 -                      switch (matchkey(tokens[istart], addr_type, 0)) {
 -                      case CONF_ADDR_IPV4:
 -                              peeraddr.ss_family = AF_INET;
 -                              istart++;
 +                          case 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 CONF_ADDR_IPV6:
 -                              peeraddr.ss_family = AF_INET6;
 -                              istart++;
 +                          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);
 +              }
 +
 +#ifdef REFCLOCK
 +              if (!err_flag)
 +                      refclock_control(&addr_sock, &clock_stat,
 +                                       (struct refclockstat *)0);
 +#endif
  
 -                      if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
 -                          break;
 +              destroy_queue(curr_fudge->options);
 +              free_node(curr_fudge);
 +      }
 +}
  
 -                      /*
 -                       * 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));
 +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:
 +                      if (!strcmp(curr_var->value.s, "\0")) { 
 +                              stats_drift_file = 0;
 +                              msyslog(LOG_INFO, "config: driftfile disabled\n");
 +                      } else { 
 +                              stats_config(STATS_FREQ_FILE, curr_var->value.s);
 +                              free(curr_var->value.s);
                        }
                        break;
 -
 -                  case CONFIG_FUDGE:
 -                      if (ntokens < 2) {
 -                              msyslog(LOG_ERR,
 -                                      "no address for fudge command, line ignored");
 -                              break;
 +                  case T_WanderThreshold:
 +                      wander_threshold = curr_var->value.d;
 +                      break;
 +                  case T_Leapfile:
 +                      stats_config(STATS_LEAP_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;
                        }
 -                      memset((char *)&peeraddr, 0, sizeof(peeraddr));
 -                      if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
 -                          break;
 -
 -                      if (!ISREFCLOCKADR(&peeraddr)) {
 +                      else
                                msyslog(LOG_ERR,
 -                                      "%s is inappropriate address for the fudge command, line ignored",
 -                                      stoa(&peeraddr));
 -                              break;
 -                      }
 -
 -                      memset((void *)&clock_stat, 0, sizeof clock_stat);
 -                      fudgeflag = 0;
 -                      errflg = 0;
 -                      for (i = 2; i < ntokens-1; i++) {
 -                              switch (c = matchkey(tokens[i],
 -                                  fudge_keywords, 1)) {
 -                                  case CONF_FDG_TIME1:
 -                                      if (sscanf(tokens[++i], "%lf",
 -                                                 &clock_stat.fudgetime1) != 1) {
 -                                              msyslog(LOG_ERR,
 -                                                      "fudge %s time1 value in error",
 -                                                      stoa(&peeraddr));
 -                                              errflg = i;
 -                                              break;
 -                                      }
 -                                      clock_stat.haveflags |= CLK_HAVETIME1;
 -                                      break;
 -
 -                                  case 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;
 +                                      "Cannot open log file %s",
 +                                      curr_var->value.s);
 +                      free(curr_var->value.s);
 +                      break;
 +#ifdef OPENSSL
 +                  case T_Automax:
 +                      sys_automax = curr_var->value.i;
 +                      break;
 +#endif
 +              }
 +              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
 +              !ISREFCLOCKADR(&peeraddr) &&
 +#endif
 +              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 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;
 +      /* Ok, all tests succeeded, now we can return 1 */
 +      return 1;
 +}
  
 -                                  case CONF_FDG_REFID:
 -                                      i++;
 -                                      memcpy(&clock_stat.fudgeval2,
 -                                          tokens[i], min(strlen(tokens[i]),
 -                                          4));
 -                                      clock_stat.haveflags |= CLK_HAVEVAL2;
 -                                      break;
 +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;
 +      }
 +}
  
 -                                  case CONF_FDG_FLAG1:
 -                                  case CONF_FDG_FLAG2:
 -                                  case CONF_FDG_FLAG3:
 -                                  case CONF_FDG_FLAG4:
 -                                      if (!atouint(tokens[++i], &fudgeflag)
 -                                          || fudgeflag > 1) {
 +static void
 +config_peers(void)
 +{
 +      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 > 1)
 +                                      printf("configuring host %s with address %s\n",
 +                                             curr_peer->addr->address, stoa(&peeraddr));
 +#endif
 +                              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,
 -                                                      "fudge %s flag value in error",
 +                                                      "configuration of %s failed",
                                                        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;
                                }
                        }
 +                      freeaddrinfo(res_bak);
 +              }
  
 -#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);
 -                      }
 -#endif
 -                      break;
 +              /* Ok, everything done. Free up peer node memory */
 +              free(curr_peer->addr->address);
 +              free_node(curr_peer->addr);
 +              free_node(curr_peer);
 +      }
 +}
 +
 +#ifdef SIM
 +static void
 +config_sim(void)
 +{
 +      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);
 +      }
  
 -                  case CONFIG_STATSDIR:
 -                      if (ntokens >= 2)
 -                              stats_config(STATS_STATSDIR,tokens[1]);
 +      /* 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);
  
 -                  case CONFIG_STATISTICS:
 -                      for (i = 1; i < ntokens; i++) {
 -                              filegen = filegen_get(tokens[i]);
  
 -                              if (filegen == NULL) {
 -                                      msyslog(LOG_ERR,
 -                                              "no statistics named %s available",
 -                                              tokens[i]);
 -                                      continue;
 -                              }
 -#ifdef DEBUG
 -                              if (debug > 3)
 -                                  printf("enabling filegen for %s statistics \"%s%s\"\n",
 -                                         tokens[i], filegen->prefix, filegen->basename);
 -#endif
 -                              filegen->flag |= FGEN_FLAG_ENABLED;
 -                      }
 -                      break;
 +      /* 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_FILEGEN:
 -                      if (ntokens < 2) {
 -                              msyslog(LOG_ERR,
 -                                      "no id for filegen command, line ignored");
 -                              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 
 + */
  
 -                      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;
 +static void
 +config_ntpd(void)
 +{
 +      config_auth();
 +      config_tos();
 +      config_monitor();
 +      config_access();
 +      config_tinker();
 +      config_system_opts();
 +      config_logconfig();
 +      config_phone();
 +      config_setvar();
 +      config_ttl();
 +      config_trap();
 +      config_vars();
 +      config_other_modes();
 +      config_peers();
 +      config_fudge();
 +}
 +
 +#ifdef SIM
 +static void
 +config_ntpdsim(void)
 +{
 +      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 */
 +
 +void
 +config_remotely(void)
 +{
 +      input_from_file = 0;
 +#if 0
 +      init_syntax_tree();
 +#endif
 +      yyparse();
 +#ifdef DEBUG
 +      if (debug > 1) 
 +              printf("Finished Parsing!!\n");
 +#endif
  
 -                                  case CONF_FGEN_FLAG_LINK:
 -                                      peerflags |= FGEN_FLAG_LINK;
 -                                      break;
 +      config_ntpd();
 +    
 +      input_from_file = 1;
 +}
 +    
  
 -                                  case CONF_FGEN_FLAG_NOLINK:
 -                                      peerflags &= ~FGEN_FLAG_LINK;
 -                                      break;
 +/* ACTUAL getconfig code */
  
 -                                  case CONF_FGEN_FLAG_ENABLE:
 -                                      peerflags |= FGEN_FLAG_ENABLED;
 -                                      break;
 +void
 +getconfig(
 +      int argc,
 +      char *argv[]
 +      )
 +{
 +      char line[MAXLINE];
  
 -                                  case CONF_FGEN_FLAG_DISABLE:
 -                                      peerflags &= ~FGEN_FLAG_ENABLED;
 -                                      break;
 -                              }
 -                      }
 -                      if (!errflg)
 -                              filegen_config(filegen, tokens[peerversion],
 -                                 (u_char)peerkey, (u_char)peerflags);
 -                      break;
 +#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;
  
 -                  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;
 +#endif /* SYS_WINNT */
 +      res_fp = NULL;
 +      ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
  
 -                  case CONFIG_ENABLE:
 -                      for (i = 1; i < ntokens; i++) {
 -                              int flag;
 +      /*
 +       * 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);
  
 -                              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;
 +      /*
 +       * Initialize the loop.
 +       */
 +      loop_config(LOOP_DRIFTINIT, 0.);
 +    
 +      getCmdOpts(argc, argv);
  
 -                  case CONFIG_DISABLE:
 -                      for (i = 1; i < ntokens; i++) {
 -                              int flag;
 +      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) {
  
 -                              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;
 +                      /*
 +                       * 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 */
 +      }
  
 -                  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;
 +      /*** BULK OF THE PARSER ***/
 +      ip_file = fp[curr_include_level];
 +      key_scanner = create_keyword_scanner(keyword_list);
 +      init_syntax_tree();
 +      yyparse();
 +#ifdef DEBUG
 +      if (debug > 1) 
 +              printf("Finished Parsing!!\n");
 +#endif
  
 -                  case CONFIG_ADJ: {
 -                          double ftemp;
 +      /* 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.
 +       */
  
 -                          sscanf(tokens[1], "%lf", &ftemp);
 -                          proto_config(PROTO_ADJ, 0, ftemp, NULL);
 -                      }
 -                      break;
 +#ifndef SIM
 +      config_ntpd();
 +#else
 +      config_ntpdsim();
 +#endif
  
 -              }
 +      while (curr_include_level != -1) {
 +              FCLOSE(fp[curr_include_level--]);
        }
 -      if (fp[0])
 -              (void)fclose(fp[0]);
 -
 +    
 +    
  #ifdef HAVE_NETINFO
        if (config_netinfo)
                free_netinfo_config(config_netinfo);
diff --cc ntpd/ntp_io.c
index 1e1401d0bb5de49e8bcf2361549e80d3e3233ecc,ae0208ae1806576f374cbbcab7a9e4ca4726ea35..8544a1ec12fb338a27376eaf80b22c9f9aed2e6a
@@@ -3616,9 -3591,7 +3618,8 @@@ kill_asyncio(int startfd
   */
  static void
  add_fd_to_list(SOCKET fd, enum desc_type type) {
-       vsock_t *lsock = (vsock_t *)malloc(sizeof(vsock_t));
+       vsock_t *lsock = (vsock_t *)emalloc(sizeof(vsock_t));
 +
-       NTP_INSIST(lsock != NULL);
        lsock->fd = fd;
        lsock->type = type;
  
Simple merge