ntp_config.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 1996, 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ntp_config.c - read and apply configuration information
*/
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#if !defined(VMS)
#endif /* VMS */
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_filegen.h"
#include "ntp_stdlib.h"
#ifdef SYS_WINNT
#include <io.h>
#endif /* SYS_WINNT */
/*
* These routines are used to read the configuration file at
* startup time. An entry in the file must fit on a single line.
* Entries are processed as multiple tokens separated by white space
* Lines are considered terminated when a '#' is encountered. Blank
* lines are ignored.
*/
/*
* Configuration file name
*/
#ifndef CONFIG_FILE
# ifndef SYS_WINNT
# ifdef SYS_SOLARIS
# define CONFIG_FILE "/etc/inet/ntp.conf"
# else
# define CONFIG_FILE "/etc/ntp.conf"
# endif
# else /* SYS_WINNT */
# define CONFIG_FILE "%windir%\\ntp.conf"
# define ALT_CONFIG_FILE "%windir%\\ntp.ini"
# endif /* SYS_WINNT */
#endif /* not CONFIG_FILE */
/*
* We understand the following configuration entries and defaults.
*
* peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
* server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
* precision -7
* broadcast [ addr ] [ version 3 ] [ key 0 ] [ ttl 1 ]
* broadcastclient
* multicastclient [224.0.1.1]
* broadcastdelay 0.0102
* restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
* driftfile file_name
* keys file_name
* filegen peerstats [ file peerstats ] [ type day ] [ link ]
* clientlimit [ n ]
* clientperiod [ 3600 ]
* trustedkey [ key ]
* requestkey [ key]
* controlkey [ key ]
* trap [ addr ]
* fudge [ addr ] [ stratum ] [ refid ] ...
* pidfile [ ]
* setvar [ ]
* logfile logfile
* logconfig [+|-|=][{sync|sys|peer|clock}{{,all}{info|statistics|events|status}}]...
* enable auth|bclient|pll|pps|monitor|stats
* disable auth|bclient|pll|pps|monitor|stats
* phone ...
* tick unsigned_value
* tickadj unsigned_value
* slewalways yes|no
*/
/*
* Types of entries we understand.
*/
#define CONFIG_UNKNOWN 0
#define CONFIG_PEER 1
#define CONFIG_SERVER 2
#define CONFIG_DRIFTFILE 4
#define CONFIG_BROADCAST 5
#define CONFIG_BROADCASTCLIENT 6
#define CONFIG_AUTHENTICATE 7
#define CONFIG_KEYS 8
#define CONFIG_RESTRICT 11
#define CONFIG_BDELAY 12
#define CONFIG_TRUSTEDKEY 13
#define CONFIG_REQUESTKEY 14
#define CONFIG_CONTROLKEY 15
#define CONFIG_TRAP 16
#define CONFIG_FUDGE 17
#define CONFIG_STATSDIR 19
#define CONFIG_FILEGEN 20
#define CONFIG_STATISTICS 21
#define CONFIG_PIDFILE 22
#define CONFIG_SETVAR 23
#define CONFIG_CLIENTLIMIT 24
#define CONFIG_CLIENTPERIOD 25
#define CONFIG_MULTICASTCLIENT 26
#define CONFIG_ENABLE 27
#define CONFIG_DISABLE 28
#define CONFIG_PHONE 29
#define CONFIG_LOGFILE 30
#define CONFIG_LOGCONFIG 31
#define CONFIG_TICK 32
#define CONFIG_TICKADJ 33
#define CONFIG_SLEWALWAYS 34
#define CONF_MOD_VERSION 1
#define CONF_MOD_KEY 2
#define CONF_MOD_MINPOLL 3
#define CONF_MOD_MAXPOLL 4
#define CONF_MOD_PREFER 5
#define CONF_MOD_TTL 6
#define CONF_MOD_MODE 7
#define CONF_RES_MASK 1
#define CONF_RES_IGNORE 2
#define CONF_RES_NOSERVE 3
#define CONF_RES_NOTRUST 4
#define CONF_RES_NOQUERY 5
#define CONF_RES_NOMODIFY 6
#define CONF_RES_NOPEER 7
#define CONF_RES_NOTRAP 8
#define CONF_RES_LPTRAP 9
#define CONF_RES_NTPPORT 10
#define CONF_RES_LIMITED 11
#define CONF_TRAP_PORT 1
#define CONF_TRAP_INTERFACE 2
#define CONF_FDG_TIME1 1
#define CONF_FDG_TIME2 2
#define CONF_FDG_STRATUM 3
#define CONF_FDG_REFID 4
#define CONF_FDG_FLAG1 5
#define CONF_FDG_FLAG2 6
#define CONF_FDG_FLAG3 7
#define CONF_FDG_FLAG4 8
#define CONF_FGEN_FILE 1
#define CONF_FGEN_TYPE 2
#define CONF_FGEN_FLAG_LINK 3
#define CONF_FGEN_FLAG_NOLINK 4
#define CONF_FGEN_FLAG_ENABLE 5
#define CONF_FGEN_FLAG_DISABLE 6
/*
* Translation table - keywords to function index
*/
struct keyword {
const char *text;
int keytype;
};
/*
* Command keywords
*/
{ "peer", CONFIG_PEER },
{ "server", CONFIG_SERVER },
{ "driftfile", CONFIG_DRIFTFILE },
{ "broadcast", CONFIG_BROADCAST },
{ "broadcastclient", CONFIG_BROADCASTCLIENT },
{ "multicastclient", CONFIG_MULTICASTCLIENT },
{ "authenticate", CONFIG_AUTHENTICATE },
{ "keys", CONFIG_KEYS },
{ "restrict", CONFIG_RESTRICT },
{ "broadcastdelay", CONFIG_BDELAY },
{ "trustedkey", CONFIG_TRUSTEDKEY },
{ "requestkey", CONFIG_REQUESTKEY },
{ "controlkey", CONFIG_CONTROLKEY },
{ "trap", CONFIG_TRAP },
{ "fudge", CONFIG_FUDGE },
{ "statsdir", CONFIG_STATSDIR },
{ "filegen", CONFIG_FILEGEN },
{ "statistics", CONFIG_STATISTICS },
{ "pidfile", CONFIG_PIDFILE },
{ "setvar", CONFIG_SETVAR },
{ "clientlimit", CONFIG_CLIENTLIMIT },
{ "clientperiod", CONFIG_CLIENTPERIOD },
{ "enable", CONFIG_ENABLE },
{ "disable", CONFIG_DISABLE },
{ "phone", CONFIG_PHONE },
{ "logfile", CONFIG_LOGFILE },
{ "logconfig", CONFIG_LOGCONFIG },
{ "tick", CONFIG_TICK },
{ "tickadj", CONFIG_TICKADJ },
{ "slewalways", CONFIG_SLEWALWAYS },
{ "", CONFIG_UNKNOWN }
};
/*
* "peer", "server", "broadcast" modifier keywords
*/
static struct keyword mod_keywords[] = {
{ "version", CONF_MOD_VERSION },
{ "key", CONF_MOD_KEY },
{ "minpoll", CONF_MOD_MINPOLL },
{ "maxpoll", CONF_MOD_MAXPOLL },
{ "prefer", CONF_MOD_PREFER },
{ "", CONFIG_UNKNOWN }
};
/*
* "restrict" modifier keywords
*/
static struct keyword res_keywords[] = {
{ "mask", CONF_RES_MASK },
{ "ignore", CONF_RES_IGNORE },
{ "noserve", CONF_RES_NOSERVE },
{ "notrust", CONF_RES_NOTRUST },
{ "noquery", CONF_RES_NOQUERY },
{ "nomodify", CONF_RES_NOMODIFY },
{ "nopeer", CONF_RES_NOPEER },
{ "notrap", CONF_RES_NOTRAP },
{ "lowpriotrap", CONF_RES_LPTRAP },
{ "ntpport", CONF_RES_NTPPORT },
{ "limited", CONF_RES_LIMITED },
{ "", CONFIG_UNKNOWN }
};
/*
* "trap" modifier keywords
*/
static struct keyword trap_keywords[] = {
{ "port", CONF_TRAP_PORT },
{ "interface", CONF_TRAP_INTERFACE },
{ "", CONFIG_UNKNOWN }
};
/*
* "fudge" modifier keywords
*/
static struct keyword fudge_keywords[] = {
{ "time1", CONF_FDG_TIME1 },
{ "time2", CONF_FDG_TIME2 },
{ "stratum", CONF_FDG_STRATUM },
{ "refid", CONF_FDG_REFID },
{ "flag1", CONF_FDG_FLAG1 },
{ "flag2", CONF_FDG_FLAG2 },
{ "flag3", CONF_FDG_FLAG3 },
{ "flag4", CONF_FDG_FLAG4 },
{ "", CONFIG_UNKNOWN }
};
/*
* "filegen" modifier keywords
*/
static struct keyword filegen_keywords[] = {
{ "file", CONF_FGEN_FILE },
{ "type", CONF_FGEN_TYPE },
{ "link", CONF_FGEN_FLAG_LINK },
{ "nolink", CONF_FGEN_FLAG_NOLINK },
{ "enable", CONF_FGEN_FLAG_ENABLE },
{ "disable", CONF_FGEN_FLAG_DISABLE },
{ "", CONFIG_UNKNOWN }
};
/*
* "type" modifier keywords
*/
static struct keyword fgen_types[] = {
{ "none", FILEGEN_NONE },
{ "pid", FILEGEN_PID },
{ "day", FILEGEN_DAY },
{ "week", FILEGEN_WEEK },
{ "month", FILEGEN_MONTH },
{ "year", FILEGEN_YEAR },
{ "age", FILEGEN_AGE },
{ "", CONFIG_UNKNOWN}
};
/*
* "enable", "disable" modifier keywords
*/
static struct keyword flags_keywords[] = {
{ "auth", PROTO_AUTHENTICATE },
{ "bclient", PROTO_BROADCLIENT },
{ "pll", PROTO_PLL },
{ "pps", PROTO_PPS },
{ "monitor", PROTO_MONITOR },
{ "stats", PROTO_FILEGEN },
{ "", CONFIG_UNKNOWN }
};
/*
* "logconfig" building blocks
*/
struct masks {
const char *name;
unsigned long mask;
};
static struct masks logcfg_class[] = {
{ "sys", NLOG_OSYS },
{ "peer", NLOG_OPEER },
{ "clock", NLOG_OCLOCK },
{ "sync", NLOG_OSYNC },
{ (char *)0, 0 }
};
static struct masks logcfg_item[] = {
{ "info", NLOG_INFO },
{ "events", NLOG_EVENT },
{ "status", NLOG_STATUS },
{ "statistics", NLOG_STATIST },
{ (char *)0, 0 }
};
/*
* Limits on things
*/
/*
* Miscellaneous macros
*/
/*
* File descriptor used by the resolver save routines, and temporary file
* name.
*/
#ifndef SYS_WINNT
#define RES_TEMPFILE "/tmp/xntpXXXXXX"
#else
#endif /* SYS_WINNT */
/*
* Definitions of things either imported from or exported to outside
*/
#ifdef DEBUG
extern int debug;
#endif
char *progname;
static const char *xntp_options = "aAbc:dD:f:gk:l:mp:r:s:t:v:V:x";
#ifdef SYS_WINNT
extern HANDLE ResolverThreadHandle;
#endif
extern int slewalways;
extern int pll_enable;
/*
* Function prototypes
*/
static unsigned long get_pfxmatch P((char **, struct masks *));
static unsigned long get_logmask P((char *));
static int getnetnum P((char *, struct sockaddr_in *, int));
static void save_resolve P((char *, int, int, int, int, int, int, u_int32));
static void do_resolve_internal P((void));
static void abort_resolve P((void));
#if !defined(VMS)
static RETSIGTYPE catchchild P((int));
#endif /* VMS */
/*
* get_pfxmatch - find value for prefixmatch
* and update char * accordingly
*/
static unsigned long
get_pfxmatch(s, m)
char ** s;
struct masks *m;
{
while (m->name) {
return m->mask;
} else {
m++;
}
}
return 0;
}
/*
* get_match - find logmask value
*/
static unsigned long
get_match(s, m)
char *s;
struct masks *m;
{
while (m->name) {
return m->mask;
} else {
m++;
}
}
return 0;
}
/*
* get_logmask - build bitmask for ntp_syslogmask
*/
static unsigned long
get_logmask(s)
char *s;
{
char *t;
unsigned long offset;
unsigned long mask;
t = s;
if (mask)
else
return 0;
}
/*
* getstartup - search through the options looking for a debugging flag
*/
void
int argc;
char *argv[];
{
int errflg;
int c;
extern int ntp_optind;
extern char *ntp_optarg;
#ifdef DEBUG
debug = 0; /* no debugging by default */
#endif
/*
* This is a big hack. We don't really want to read command line
* configuration until everything else is initialized, since
* the ability to configure the system may depend on storage
* and the like having been initialized. Except that we also
* don't want to initialize anything until after detaching from
* the terminal, but we won't know to do that until we've
* parsed the command line. Do that now, crudely, and do it
* again later. Our ntp_getopt() is explicitly reusable, by the
* way. Your own mileage may vary.
*
* This hack is even called twice (to allow complete logging to file)
*/
errflg = 0;
/*
* Decode argument list
*/
switch (c) {
#ifdef DEBUG
case 'd':
++debug;
break;
case 'D':
break;
#else
case 'd':
case 'D':
++errflg;
break;
#endif
case '?':
++errflg;
break;
case 'l':
{
extern int syslogit;
extern FILE *syslog_file;
if (syslog_file != NULL &&
(void)fclose(syslog_file);
syslogit = 0;
}
else
"Cannot open log file %s",
}
break;
default:
break;
}
exit(2);
}
ntp_optind = 0; /* reset ntp_optind to restart ntp_getopt */
#ifdef DEBUG
if (debug) {
#ifdef HAVE_SETVBUF
#else
#endif
}
#endif
}
/*
* getconfig - get command line options and read the configuration file
*/
void
int argc;
char *argv[];
{
register int i;
int c;
int errflg;
int peerversion;
int minpoll;
int maxpoll;
int ttl;
int peerflags;
int hmode;
struct sockaddr_in peeraddr;
struct sockaddr_in maskaddr;
int ntokens;
int tok;
char *config_file;
#ifdef SYS_WINNT
char *alt_config_file;
char config_file_storage[MAX_PATH];
char alt_config_file_storage[MAX_PATH];
#endif /* SYS_WINNT */
struct refclockstat clock;
extern int ntp_optind;
extern char *ntp_optarg;
extern char *Version;
extern char *set_tod_using;
extern u_int32 info_auth_keyid;
extern int allow_set_backward;
extern int correct_any;
/*
* Initialize, initialize
*/
errflg = 0;
#ifdef DEBUG
debug = 0;
#endif /* DEBUG */
#ifndef SYS_WINNT
#else
temp = CONFIG_FILE;
if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
exit(1);
}
if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
exit(1);
}
#endif /* SYS_WINNT */
correct_any = FALSE;
/*
* install a non default variable with this daemon version
*/
/*
* Say how we're setting the time of day
*/
/*
* Initialize the loop.
*/
L_CLR(&zero_drift);
/*
* Decode argument list
*/
switch (c) {
case 'a':
break;
case 'A':
break;
case 'b':
break;
case 'c':
break;
case 'd':
#ifdef DEBUG
debug++;
#else
errflg++;
#endif /* DEBUG */
break;
case 'D':
#ifdef DEBUG
#else
errflg++;
#endif /* DEBUG */
break;
case 'f':
break;
case 'g':
correct_any = TRUE;
break;
case 'k':
break;
case 'l': /* already done at pre-scan */
break;
case 'm':
break;
case 'p':
break;
case 'r':
do {
"command line broadcast delay value %s undecodable",
"command line broadcast delay value %s is unlikely",
} else {
}
} while (0);
break;
case 's':
break;
case 't':
do {
"command line trusted key %s is unlikely",
} else {
}
} while (0);
break;
case 'v':
case 'V':
break;
case 'x':
break;
default:
errflg++;
break;
}
}
exit(2);
}
{
#ifdef SYS_WINNT
/* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
/*
* Broadcast clients can sometimes run without
* a configuration file.
*/
return;
}
#else /* not SYS_WINNT */
return;
#endif /* not SYS_WINNT */
}
!= CONFIG_UNKNOWN) {
switch(tok) {
case CONFIG_PEER:
case CONFIG_SERVER:
case CONFIG_BROADCAST:
if (tok == CONFIG_PEER)
hmode = MODE_ACTIVE;
else if (tok == CONFIG_SERVER)
hmode = MODE_CLIENT;
else
if (ntokens < 2) {
"No address for %s, line ignored",
tokens[0]);
break;
}
errflg = -1;
} else {
errflg = 0;
if (
#ifdef REFCLOCK
!ISREFCLOCKADR(&peeraddr) &&
#endif
"attempt to configure invalid address %s",
break;
}
}
peerkey = 0;
peerflags = 0;
ttl = 0;
for (i = 2; i < ntokens; i++)
case CONF_MOD_VERSION:
if (i >= ntokens-1) {
errflg = 1;
break;
}
"inappropriate version number %s, line ignored",
tokens[i]);
errflg = 1;
}
break;
case CONF_MOD_KEY:
if (i >= ntokens-1) {
"key: argument required");
errflg = 1;
break;
}
break;
case CONF_MOD_MINPOLL:
if (i >= ntokens-1) {
"minpoll: argument required");
errflg = 1;
break;
}
if (minpoll < NTP_MINPOLL)
break;
case CONF_MOD_MAXPOLL:
if (i >= ntokens-1) {
"maxpoll: argument required");
errflg = 1;
break;
}
if (maxpoll > NTP_MAXPOLL)
break;
case CONF_MOD_PREFER:
peerflags |= FLAG_PREFER;
break;
case CONF_MOD_TTL:
if (i >= ntokens-1) {
"ttl: argument required");
errflg = 1;
break;
}
break;
case CONF_MOD_MODE:
if (i >= ntokens-1) {
"mode: argument required");
errflg = 1;
break;
}
break;
case CONFIG_UNKNOWN:
errflg = 1;
break;
}
errflg = 1;
}
if (errflg == 0) {
if (peer_config(&peeraddr,
== 0) {
"configuration of %s failed",
}
} else if (errflg == -1) {
}
break;
case CONFIG_DRIFTFILE:
if (ntokens >= 2)
else
stats_config(STATS_FREQ_FILE, (char *)0);
break;
case CONFIG_PIDFILE:
if (ntokens >= 2)
else
stats_config(STATS_PID_FILE, (char *)0);
break;
case CONFIG_LOGFILE: {
extern int syslogit;
extern FILE *syslog_file;
if (ntokens >= 2) {
if (syslog_file != NULL &&
(void)fclose(syslog_file);
syslogit = 0;
}
else
"Cannot open log file %s",
tokens[1]);
}
else
}
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)
#endif
}
}
break;
case CONFIG_BROADCASTCLIENT:
break;
case CONFIG_MULTICASTCLIENT:
if (ntokens > 1) {
for (i = 1; i < ntokens; i++) {
}
} else
break;
case CONFIG_AUTHENTICATE:
errflg = 0;
if (ntokens >= 2) {
else
errflg++;
} else {
errflg++;
}
if (errflg)
"should be `authenticate yes|no'");
break;
case CONFIG_KEYS:
if (ntokens >= 2) {
}
break;
case CONFIG_RESTRICT:
if (ntokens < 2) {
break;
}
break;
/*
* Use peerversion as flags, peerkey as mflags. Ick.
*/
peerversion = 0;
peerkey = 0;
errflg = 0;
for (i = 2; i < ntokens; i++) {
case CONF_RES_MASK:
if (i >= ntokens-1) {
"mask keyword needs argument");
errflg++;
break;
}
i++;
errflg++;
break;
case CONF_RES_IGNORE:
break;
case CONF_RES_NOSERVE:
break;
case CONF_RES_NOTRUST:
break;
case CONF_RES_NOQUERY:
break;
case CONF_RES_NOMODIFY:
break;
case CONF_RES_NOPEER:
break;
case CONF_RES_NOTRAP:
break;
case CONF_RES_LPTRAP:
break;
case CONF_RES_NTPPORT:
peerkey |= RESM_NTPONLY;
break;
case CONF_RES_LIMITED:
break;
case CONFIG_UNKNOWN:
errflg++;
break;
}
}
if (!errflg)
(int)peerkey, peerversion);
break;
case CONFIG_BDELAY:
if (ntokens >= 2) {
"broadcastdelay value %s undecodable",
tokens[1]);
"broadcastdelay value %s is unlikely",
tokens[1]);
} else {
}
}
break;
case CONFIG_TRUSTEDKEY:
for (i = 1; i < ntokens; i++) {
if (tkey == 0) {
"trusted key %s unlikely",
tokens[i]);
} else {
}
}
break;
case CONFIG_REQUESTKEY:
if (ntokens >= 2) {
"%s is undecodable as request key",
tokens[1]);
} else if (rkey == 0) {
"%s makes a poor request keyid",
tokens[1]);
} else {
#ifdef DEBUG
if (debug > 3)
"set info_auth_key to %lu\n", rkey);
#endif
}
}
break;
case CONFIG_CONTROLKEY:
if (ntokens >= 2) {
extern u_int32 ctl_auth_keyid;
if (ckey == 0) {
"%s makes a poor control keyid",
tokens[1]);
} else {
}
}
break;
case CONFIG_TRAP:
if (ntokens < 2) {
"no address for trap command, line ignored");
break;
}
break;
/*
* Use peerversion for port number. Barf.
*/
errflg = 0;
peerversion = 0;
localaddr = 0;
case CONF_TRAP_PORT:
if (i >= ntokens-1) {
"trap port requires an argument");
errflg = 1;
break;
}
if (peerversion <= 0
|| peerversion > 32767) {
"invalid port number %s, trap ignored",
tokens[i]);
errflg = 1;
}
break;
case CONF_TRAP_INTERFACE:
if (i >= ntokens-1) {
"trap interface requires an argument");
errflg = 1;
break;
}
&maskaddr, 1)) {
errflg = 1;
break;
}
"can't find interface with address %s",
errflg = 1;
}
break;
case CONFIG_UNKNOWN:
errflg++;
break;
}
if (!errflg) {
extern struct interface *any_interface;
if (peerversion != 0)
else
"can't set trap for %s, no resources",
}
break;
case CONFIG_FUDGE:
if (ntokens < 2) {
"no address for fudge command, line ignored");
break;
}
break;
if (!ISREFCLOCKADR(&peeraddr)) {
"%s is inappropriate address for the fudge command, line ignored",
break;
}
errflg = 0;
fudge_keywords)) {
case CONF_FDG_TIME1:
&clock.fudgetime1)) {
"fudge %s time1 value in error",
errflg = i;
break;
}
break;
case CONF_FDG_TIME2:
&clock.fudgetime2)) {
"fudge %s time2 value in error",
errflg = i;
break;
}
break;
case CONF_FDG_STRATUM:
"fudge %s stratum value in error",
errflg = i;
break;
}
break;
case CONF_FDG_REFID:
tokens[++i], 4);
break;
case CONF_FDG_FLAG1:
case CONF_FDG_FLAG2:
case CONF_FDG_FLAG3:
case CONF_FDG_FLAG4:
|| lpeerkey > 1) {
"fudge %s flag value in error",
errflg = i;
break;
}
switch(c) {
case CONF_FDG_FLAG1:
c = CLK_FLAG1;
break;
case CONF_FDG_FLAG2:
c = CLK_FLAG2;
break;
case CONF_FDG_FLAG3:
c = CLK_FLAG3;
break;
case CONF_FDG_FLAG4:
c = CLK_FLAG4;
break;
}
if (peerkey == 0)
else
break;
case CONFIG_UNKNOWN:
errflg = -1;
break;
}
}
#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) {
(struct refclockstat *)0);
}
#endif
break;
case CONFIG_STATSDIR:
if (ntokens >= 2) {
}
break;
case CONFIG_STATISTICS:
for (i = 1; i < ntokens; i++) {
"no statistics named %s available",
tokens[i]);
continue;
}
#ifdef DEBUG
if (debug > 3)
printf("enabling filegen for %s statistics \"%s%s\"\n",
#endif
}
break;
case CONFIG_FILEGEN:
if (ntokens < 2) {
"no id for filegen command, line ignored");
break;
}
"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;
errflg = 0;
for (i = 2; i < ntokens; i++) {
case CONF_FGEN_FILE:
if (i >= ntokens - 1) {
"filegen %s file requires argument",
tokens[1]);
errflg = i;
break;
}
peerversion = ++i;
break;
case CONF_FGEN_TYPE:
if (i >= ntokens -1) {
"filegen %s type requires argument",
tokens[1]);
errflg = i;
break;
}
if (peerkey == CONFIG_UNKNOWN) {
"filegen %s unknown type \"%s\"",
errflg = i;
break;
}
break;
case CONF_FGEN_FLAG_LINK:
break;
case CONF_FGEN_FLAG_NOLINK:
peerflags &= ~FGEN_FLAG_LINK;
break;
case CONF_FGEN_FLAG_ENABLE:
break;
case CONF_FGEN_FLAG_DISABLE:
break;
}
}
if (!errflg) {
}
break;
case CONFIG_SETVAR:
if (ntokens < 2) {
"no value for setvar command - line ignored");
} else {
"default"))) ? DEF : 0));
}
break;
case CONFIG_CLIENTLIMIT:
if (ntokens < 2) {
"no value for clientlimit command - line ignored");
} else {
u_long i;
"illegal value for clientlimit command - line ignored");
} else {
extern u_long client_limit;
char bp[80];
#ifdef DEBUG
if (debug)
#endif
client_limit = i;
}
}
break;
case CONFIG_CLIENTPERIOD:
if (ntokens < 2) {
"no value for clientperiod command - line ignored");
} else {
u_long i;
"illegal value for clientperiod command - line ignored");
} else {
extern u_long client_limit_period;
char bp[80];
client_limit_period = i;
}
}
break;
case CONFIG_TICK:
if (ntokens < 2) {
"no value for tick command - line ignored");
} else {
u_long i;
|| i < 900 || i > 11000
)
{
"illegal value for tick command (expected 900-11000) - line ignored");
}
else
{
extern u_long default_tick;
char bp[80];
default_tick = i;
}
}
break;
case CONFIG_TICKADJ:
if (ntokens < 2) {
"no value for tickadj command - line ignored");
} else {
u_long i;
|| i < 1 || i > 50
)
{
"illegal value for tickadj command (expected 1-50) - line ignored");
}
else
{
extern u_long default_tickadj;
char bp[80];
default_tickadj = i;
}
}
break;
case CONFIG_ENABLE:
for (i = 1; i < ntokens; i++) {
int flag;
if (flag == CONFIG_UNKNOWN) {
"enable unknown flag %s",
tokens[i]);
errflg = 1;
break;
}
}
break;
case CONFIG_DISABLE:
for (i = 1; i < ntokens; i++) {
int flag;
if (flag == CONFIG_UNKNOWN) {
"disable unknown flag %s",
tokens[i]);
errflg = 1;
break;
}
proto_config(flag, 0L);
}
break;
case CONFIG_PHONE:
}
break;
/*
* CONFIG_SLEWALWAYS was added to allow users to select
* SLEWALWAYS via the ntp.conf file.
*/
case CONFIG_SLEWALWAYS:
errflg = 0;
if (ntokens >= 2) {
slewalways = 1;
slewalways = 0;
else
errflg++;
} else {
errflg++;
}
if (errflg)
"should be `slewalways yes|no'");
break;
}
}
/*
* At this point we have processed all the configuration data,
* and we know if "disable pll" is in effect. If so, disable use
* of the drift file, because the recorded value may be harmful.
*/
if (pll_enable == 0) {
}
/*
* Need name resolution
*/
}
}
/*
* gettokens - read a line and return tokens
*/
static int
char *line;
char **tokenlist;
int *ntokens;
{
register char *cp;
register int eol;
register int ntok;
register int quoted = 0;
/*
* Find start of first token
*/
cp++;
break;
}
*ntokens = 0;
return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
}
/*
* Now separate out the tokens
*/
eol = 0;
ntok = 0;
while (!eol) {
*cp = '\0';
eol = 1;
} else { /* must be space */
*cp++ = '\0';
cp++;
eol = 1;
}
eol = 1;
}
/*
* Return the match
*/
if (ntok == CONFIG_UNKNOWN)
goto again;
return ntok;
}
/*
* matchkey - match a keyword to a list
*/
static int
register char *word;
{
for (;;) {
"configure: keyword \"%s\" unknown, line ignored",
word);
return CONFIG_UNKNOWN;
}
keys++;
}
}
/*
* getnetnum - return a net number (this is crude, but careful)
*/
static int
char *num;
struct sockaddr_in *addr;
int complain;
{
register char *cp;
register char *bp;
register int i;
register int temp;
/* XXX ELIMINATE replace with decodenetnum */
netnum = 0;
for (i = 0; i < 4; i++) {
break;
if (i < 3) {
if (*cp++ != '.')
break;
} else if (*cp != '\0')
break;
*bp = '\0';
if (temp > 255)
break;
netnum <<= 8;
#ifdef DEBUG
if (debug > 3)
printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
#endif
}
if (i < 4) {
if (complain)
"getnetnum: \"%s\" invalid host number, line ignored",
num);
#ifdef DEBUG
if (debug > 3)
"getnetnum: \"%s\" invalid host number, line ignored\n",
num);
#endif
return 0;
}
/*
* make up socket address. Clear it out for neatness.
*/
#ifdef DEBUG
if (debug > 1)
printf("getnetnum given %s, got %s (%lx)\n",
#endif
return 1;
}
#if !defined(VMS)
/*
* catchchild - receive the resolver's exit status
*/
static RETSIGTYPE
int sig;
{
/*
* We only start up one child, and if we're here
* it should have already exited. Hence the following
* shouldn't hang. If it does, please tell me.
*/
#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
(void) wait(0);
#endif /* SYS_WINNT && VXWORKS*/
}
#endif /* VMS */
/*
* save_resolve - save configuration info into a file for later name resolution
*/
static void
char *name;
int mode;
int version;
int minpoll;
int maxpoll;
int flags;
int ttl;
{
#ifndef SYS_VXWORKS
#ifndef SYS_WINNT
#else
/* no /tmp directory under NT */
{
return;
}
}
#endif /* SYS_WINNT */
#ifdef HAVE_MKSTEMP
{
int fd;
}
#else
#endif
return;
}
}
#ifdef DEBUG
if (debug) {
}
#endif
/* we don't open resolve file Casey */
#else /* SYS_VXWORKS */
/* save resolve info to a struct */
#endif /* SYS_VXWORKS */
}
/*
* abort_resolve - terminate the resolver stuff and delete the file
*/
static void
{
/*
* In an ideal world we would might reread the file and
* log the hosts which aren't getting configured. Since
* this is too much work, however, just close and delete
* the temp file.
*/
#ifndef SYS_VXWORKS /* we don't open the file to begin with */
#if !defined(VMS)
#else
#endif /* VMS */
#endif /* SYS_VXWORKS */
}
#define KEY_TYPE_MD5 4
/*
* do_resolve_internal - start up the resolver function (not program)
*/
/*
* On VMS, this routine will simply refuse to resolve anything.
*
* Possible implementation: keep `res_file' in memory, do async
* name resolution via QIO, update from within completion AST.
* I'm unlikely to find the time for doing this, though. -wjm
*/
static void
{
int i;
#if !defined(VMS)
extern char *req_file; /* name of the file with config info */
#endif
extern u_int32 info_auth_keyid;
/* belch */
"internal error in do_resolve_internal: res_fp == NULL");
exit(1);
}
/* we are done with this now */
#if !defined(VMS) && !defined (SYS_VXWORKS)
/* find a keyid */
if (info_auth_keyid == 0)
req_keyid = 65535;
else
/* if doesn't exist, make up one at random */
if (!authhavekey(req_keyid)) {
char rankey[9];
#ifdef HAVE_GETCLOCK
#endif
/* generate random key */
#ifdef HAVE_GETCLOCK
#else /* not HAVE_GETCLOCK */
#endif /* not HAVE_GETCLOCK */
for (i = 0; i < 8; i++)
rankey[8] = 0;
}
/* save keyid so we will accept config requests with it */
#ifndef SYS_WINNT
#ifndef SYS_VXWORKS
i = fork();
if (i == 0) {
/*
* this used to close everything
* I don't think this is necessary
*/
/*
* To the unknown commenter above:
* Well, I think it's better to clean up
* after oneself. I have had problems with
* refclock-io when intres was running - things
* where fine again when xntpintres was gone.
* So some systems react erratic at least.
*
* Frank Kardel
*
* 94-11-16:
* Further debugging has proven that the above is
* absolutely harmful. The internal resolver
* is still in the SIGIO process group and the lingering
* async io information causes it to process requests from
* all file decriptor causing a race between the NTP daemon
* and the resolver. which then eats data when it wins 8-(.
* It is absolutly necessary to kill ane io associations
* shared with the NTP daemon. I currently don't want
*
* we also block SIGIO (currently no portes means to
* disable the signal handle for IO).
*
* Thanks to wgstuken@informatik.uni-erlangen.de to notice
* that it is the xntp-resolver child running into trouble.
*
* THUS:
*/
closelog();
kill_asyncio();
ntp_intres();
/*
* If we got here, the intres code screwed up.
* Print something so we don't die without complaint
*/
exit(1);
}
#else
/* vxWorks spawns a thread... -casey */
i = sp (ntp_intres);
/*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
#endif
if (i == -1) {
}
#else /* SYS_WINNT */
{
/* NT's equivalent of fork() is _spawn(), but the start point
* of the new process is an executable filename rather than
* a function name as desired here.
*/
if (!(ResolverThreadHandle = CreateThread(
NULL, /* no security attributes */
0, /* use default stack size */
NULL, /* argument to thread function */
0, /* use default creation flags */
&dwThreadId))) { /* returns the thread identifier */
}
}
#endif /* SYS_WINNT */
#else /* VMS VXWORKS*/
"Name resolution not implemented for VMS - use numeric addresses");
#endif /* VMS VXWORKS*/
}