From: Harlan Stenn Date: Wed, 15 Aug 2007 07:04:56 +0000 (-0400) Subject: Merge pogo.udel.edu:/pogo/users/kardel/main-line/ntp-stable X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a24951e731e65c1b7f5fd72aa25fdf56a1cf103;p=thirdparty%2Fntp.git Merge pogo.udel.edu:/pogo/users/kardel/main-line/ntp-stable into pogo.udel.edu:/pogo/users/stenn/ntp-dev bk: 46c2a598JcKvc4YfzfFg6E2xbRVopg --- 8a24951e731e65c1b7f5fd72aa25fdf56a1cf103 diff --cc ChangeLog index 00a560dc33,11e1dde1c8..d50d203f9e --- a/ChangeLog +++ b/ChangeLog @@@ -101,12 -17,13 +101,20 @@@ * [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/ntp_config.c index 065fe194f8,05af3ffc20..b47e18bfc3 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@@ -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 1e1401d0bb,ae0208ae18..8544a1ec12 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@@ -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;