home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
x
/
xntp3.zip
/
gizmo
/
gizmo_config.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-19
|
13KB
|
683 lines
/*
* gizmo_config.c - read and apply configuration information
*/
#include <stdio.h>
#include "gizmo_syslog.h"
#include <strings.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "ntp_fp.h"
#include "ntp.h"
#include "ntp_refclock.h"
#include "gizmo.h"
/*
* These routines are used decode and apply configuration information
* at run time. The configuration is compiled in.
*/
/*
* Definitions of things either imported from or exported to outside
*/
#ifdef DEBUG
extern int debug;
#endif
extern u_long ctl_auth_keyid;
extern u_long info_auth_keyid;
/*
* Configuration array. This is initialized at compile time.
*/
extern u_char gizmo_config_data[];
/*
* Used by the configuration data reading routines
*/
static u_char *config_pt;
static u_long config_csum;
/*
* getstartup - search through the options looking for a debug level
* and host to log to.
*/
void
getstartup(argc, argv)
int argc;
char *argv[];
{
void doconfig();
doconfig(0);
}
/*
* getconfig - get command line options and read the configuration file
*/
void
getconfig(argc, argv)
int argc;
char *argv[];
{
void doconfig();
doconfig(1);
}
/*
* doconfig - do the gross work of configuration
*/
void
doconfig(applyit)
int applyit;
{
register int i;
int errflg;
int peerversion;
u_long peerkey;
int peerflags;
int hmode;
struct sockaddr_in peeraddr;
struct sockaddr_in maskaddr;
l_fp ts;
int tok;
struct interface *localaddr;
struct refclockstat clock;
u_long data_csum;
int cgettoken();
int cgetuchar();
int cgetchar();
int cgetushort();
u_long cgetulong();
void cgetts();
void cgetnetnum();
void check_size();
extern void proto_config();
extern void authtrust();
extern struct peer *peer_config();
extern void stats_config();
extern void mon_start(), mon_stop();
extern void loop_config();
extern int atolfp();
extern int authreadkeys();
extern struct interface *findinterface();
extern char *ntoa();
extern void setauthkey();
/*
* Initialize, initialize
*/
#ifdef DEBUG
debug = 0;
#endif /* DEBUG */
config_pt = gizmo_config_data;
config_csum = 0;
while ((tok = cgettoken())
!= 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
hmode = MODE_BROADCAST;
cgetnetnum(&peeraddr);
#ifdef REFCLOCK
if (!ISREFCLOCKADR(&peeraddr) && ISBADADR(&peeraddr)) {
#else
if (ISBADADR(&peeraddr)) {
#endif
syslog(LOG_ERR,
"attempt to configure invalid address %s",
ntoa(&peeraddr));
break;
}
errflg = 0;
peerversion = NTP_VERSION;
peerkey = 0;
peerflags = 0;
while ((tok = cgettoken()) != CONFIG_END) {
switch (tok) {
case CONF_MOD_VERSION:
peerversion = cgetuchar();
if (peerversion != NTP_VERSION
&& peerversion != NTP_OLDVERSION) {
syslog(LOG_ERR,
"inappropriate version number %d, %s ignored",
peerversion, ntoa(&peeraddr));
errflg = 1;
}
break;
case CONF_MOD_KEY:
peerkey = cgetulong();
peerflags |= FLAG_AUTHENABLE;
break;
case CONF_MOD_MINPOLL:
peerflags |= FLAG_MINPOLL;
break;
default:
syslog(LOG_ERR,
"inappropriate code for peer configuration <%d>, %s ignored\n",
tok, ntoa(&peeraddr));
errflg++;
break;
}
}
if (!errflg && applyit) {
if (peer_config(&peeraddr,
(struct interface *)0,
hmode, peerversion, peerkey,
peerflags) == 0) {
syslog(LOG_ERR,
"configuration of %s failed",
ntoa(&peeraddr));
}
}
break;
case CONFIG_PRECISION:
i = cgetchar();
if (i >= 0 || i < -25)
syslog(LOG_ERR,
"unlikely precision %d, line ignored", i);
else if (applyit)
proto_config(PROTO_PRECISION, i);
break;
case CONFIG_DRIFT:
cgetts(&ts);
if (applyit)
loop_config(LOOP_DRIFTCOMP, &ts);
break;
case CONFIG_BROADCASTCLIENT:
i = cgetuchar();
if (i == CONF_YORN_YES) {
if (applyit)
proto_config(PROTO_BROADCLIENT, 1);
} else if (i = CONF_YORN_NO) {
if (applyit)
proto_config(PROTO_BROADCLIENT, 0);
} else {
syslog(LOG_ERR,
"Invalid argument for broadcastclient <%d>", i);
}
break;
case CONFIG_AUTHENTICATE:
i = cgetuchar();
if (i == CONF_YORN_YES) {
if (applyit)
proto_config(PROTO_AUTHENTICATE, 1);
} else if (i = CONF_YORN_NO) {
if (applyit)
proto_config(PROTO_AUTHENTICATE, 0);
} else {
syslog(LOG_ERR,
"Invalid argument for authenticate <%d>", i);
}
break;
case CONFIG_KEYS:
i = cgetuchar();
while (i-- > 0) {
u_long keys[2];
peerkey = cgetulong();
keys[0] = cgetulong();
keys[1] = cgetulong();
if (applyit)
setauthkey(peerkey, keys);
}
break;
case CONFIG_MONITOR:
i = cgetuchar();
if (i == CONF_YORN_YES) {
if (applyit)
mon_start();
} else if (i = CONF_YORN_NO) {
if (applyit)
mon_stop();
} else {
syslog(LOG_ERR,
"Invalid argument for monitor <%d>", i);
}
break;
case CONFIG_AUTHDELAY:
peerkey = cgetulong();
if (applyit)
proto_config(PROTO_AUTHDELAY, (long)peerkey);
break;
case CONFIG_RESTRICT:
cgetnetnum(&peeraddr);
cgetnetnum(&maskaddr);
i = cgetushort();
/*
* Use peerversion as flags, peerkey as mflags. Ick.
*/
peerversion = 0;
peerkey = 0;
if (i & CONF_RES_IGNORE)
peerversion |= RES_IGNORE;
if (i & CONF_RES_NOSERVE)
peerversion |= RES_DONTSERVE;
if (i & CONF_RES_NOTRUST)
peerversion |= RES_DONTTRUST;
if (i & CONF_RES_NOQUERY)
peerversion |= RES_NOQUERY;
if (i & CONF_RES_NOMODIFY)
peerversion |= RES_NOMODIFY;
if (i & CONF_RES_NOPEER)
peerversion |= RES_NOPEER;
if (i & CONF_RES_NOTRAP)
peerversion |= RES_NOTRAP;
if (i & CONF_RES_LPTRAP)
peerversion |= RES_LPTRAP;
if (i & CONF_RES_NTPPORT)
peerkey |= RESM_NTPONLY;
if (SRCADR(&peeraddr) == INADDR_ANY)
maskaddr.sin_addr.s_addr = 0;
if (applyit)
restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
(int)peerkey, peerversion);
break;
case CONFIG_BDELAY:
cgetts(&ts);
peerkey = LFPTOFP(&ts);
if (applyit)
proto_config(PROTO_BROADDELAY, peerkey);
break;
case CONFIG_TRUSTEDKEY:
i = cgetuchar();
while (i-- > 0) {
peerkey = cgetulong();
if (applyit)
authtrust(peerkey, 1);
}
break;
case CONFIG_REQUESTKEY:
peerkey = cgetulong();
if (applyit)
info_auth_keyid = peerkey;
break;
case CONFIG_CONTROLKEY:
peerkey = cgetulong();
if (applyit)
ctl_auth_keyid = peerkey;
break;
case CONFIG_TRAP:
cgetnetnum(&peeraddr);
/*
* Use peerversion for port number. Barf.
*/
errflg = 0;
peerversion = 0;
localaddr = 0;
while ((tok = cgettoken()) != CONFIG_END) {
switch (tok) {
case CONF_TRAP_PORT:
peerversion = cgetushort();
if (peerversion == 0
|| peerversion > 32767) {
syslog(LOG_ERR,
"invalid port number %d, trap %s ignored",
peerversion, ntoa(&peeraddr));
errflg = 1;
}
break;
case CONF_TRAP_INTERFACE:
cgetnetnum(&maskaddr);
if (applyit) {
localaddr
= findinterface(&maskaddr);
if (localaddr == NULL) {
syslog(LOG_ERR,
"can't find interface with address %s",
ntoa(&maskaddr));
errflg = 1;
}
}
break;
default:
errflg++;
break;
}
}
if (!errflg && applyit) {
extern struct interface *any_interface;
if (peerversion != 0)
peeraddr.sin_port = htons(peerversion);
else
peeraddr.sin_port = htons(TRAPPORT);
if (localaddr == NULL)
localaddr = any_interface;
if (!ctlsettrap(&peeraddr, localaddr, 0,
NTP_VERSION))
syslog(LOG_ERR,
"can't set trap for %s, no resources",
ntoa(&peeraddr));
}
break;
case CONFIG_FUDGE:
cgetnetnum(&peeraddr);
errflg = 0;
if (!ISREFCLOCKADR(&peeraddr)) {
syslog(LOG_ERR,
"%s is inappropriate address for the fudge command",
ntoa(&peeraddr));
errflg++;
}
bzero((char *)&clock, sizeof clock);
while ((tok = cgettoken()) != CONFIG_END) {
switch (tok) {
case CONF_FDG_TIME1:
cgetts(&clock.fudgetime1);
clock.haveflags |= CLK_HAVETIME1;
break;
case CONF_FDG_TIME2:
cgetts(&clock.fudgetime2);
clock.haveflags |= CLK_HAVETIME2;
break;
case CONF_FDG_VALUE1:
clock.fudgeval1 =
(long) cgetulong();
clock.haveflags |= CLK_HAVEVAL1;
break;
case CONF_FDG_VALUE2:
clock.fudgeval2 =
(long) cgetulong();
clock.haveflags |= CLK_HAVEVAL2;
break;
case CONF_FDG_FLAG1:
case CONF_FDG_FLAG2:
case CONF_FDG_FLAG3:
case CONF_FDG_FLAG4:
peerversion = cgetuchar();
if (peerversion != CONF_YORN_NO
&& peerversion != CONF_YORN_YES) {
syslog(LOG_ERR,
"incorrect flag value <%d> for fudge %s",
peerversion, ntoa(&peeraddr));
errflg++;
}
switch(tok) {
case CONF_FDG_FLAG1:
hmode = CLK_FLAG1;
clock.haveflags|=CLK_HAVEFLAG1;
break;
case CONF_FDG_FLAG2:
hmode = CLK_FLAG2;
clock.haveflags|=CLK_HAVEFLAG2;
break;
case CONF_FDG_FLAG3:
hmode = CLK_FLAG3;
clock.haveflags|=CLK_HAVEFLAG3;
break;
case CONF_FDG_FLAG4:
hmode = CLK_FLAG4;
clock.haveflags|=CLK_HAVEFLAG4;
break;
}
if (peerkey == CONF_YORN_NO)
clock.flags &= ~hmode;
else
clock.flags |= hmode;
break;
default:
errflg++;
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 & applyit) {
extern void refclock_control();
refclock_control(&peeraddr, &clock,
(struct refclockstat *)0);
}
#endif
break;
case CONFIG_MAXSKEW:
peerkey = cgetulong();
if (applyit)
proto_config(PROTO_MAXSKEW, peerkey);
break;
case CONFIG_SYSLOGHOST:
cgetnetnum(&peeraddr);
setloghost(&peeraddr);
break;
case CONFIG_DEBUGLEVEL:
i = cgetuchar();
#ifdef DEBUG
debug = i;
if (debug)
printf("debug level set to %d\n", i);
#endif
break;
}
}
/*
* If we got here, there should be a checksum in the next
* 4 bytes of the file. Check it out.
*/
check_size(4);
data_csum = 0;
for (i = 0; i < 4; i++) {
data_csum <<= 8;
data_csum += ((u_long)(*config_pt++)) & 0xff;
}
if ((config_csum + data_csum) != 0) {
syslog(LOG_ERR,
"configuration checksum error (0x%08x != 0x%08x)",
config_csum, -data_csum);
#ifdef notdef
exit(1);
#endif
}
}
/*
* check_size - check to see if there are enough bytes in the buffer.
*/
static void
check_size(nbytes)
int nbytes;
{
if ((config_pt + nbytes) > &gizmo_config_data[GIZMO_CONFIG_SIZE]) {
syslog(LOG_ERR, "whoops! Slipped off end of config info");
exit(1);
}
}
/*
* cgetuchar - return an unsigned char (as an int)
*/
int
cgetuchar()
{
register u_char u;
check_size(sizeof(u_char));
u = *config_pt++;
config_csum += (u_long)u;
return (int)u;
}
/*
* cgettoken - return a token value
*/
int
cgettoken()
{
register u_char u;
check_size(sizeof(u_char));
u = *config_pt++;
config_csum += (u_long)u;
return (int)u;
}
/*
* cgetushort - return an unsigned short value (as an int)
*/
int
cgetushort()
{
register u_char u;
register u_short s;
check_size(sizeof(u_short));
u = *config_pt++;
config_csum += (u_long)u;
s = ((u_short)u) << 8;
u = *config_pt++;
config_csum += (u_long)u;
s += (u_short)u;
return (int)s;
}
/*
* cgetulong - return an unsigned long value
*/
u_long
cgetulong()
{
register int i;
register u_long v;
register u_char u;
check_size(sizeof(u_long));
v = 0;
for (i = 0; i < sizeof(u_long); i++) {
u = *config_pt++;
config_csum += (u_long)u;
v <<= 8;
v += (u_long)u;
}
return v;
}
/*
* cgetchar - return a signed char value
*/
int
cgetchar()
{
register int i;
config_csum += (u_long)(*config_pt);
i = (int)*((s_char *)config_pt);
config_pt++;
config_csum += (u_long)(i & 0xff);
return i;
}
/*
* cgetts - return an l_fp timestamp
*/
void
cgetts(ts)
l_fp *ts;
{
register int i;
register u_long v;
register u_char u;
check_size(sizeof(l_fp));
v = 0;
for (i = 0; i < sizeof(l_fp); i++) {
if (i == (sizeof(l_fp)/2)) {
ts->l_ui = v;
v = 0;
}
u = *config_pt++;
config_csum += (u_long)u;
v <<= 8;
v += (u_long)u;
}
ts->l_uf = v;
}
/*
* cgetnetnum - return a net number
*/
void
cgetnetnum(addr)
struct sockaddr_in *addr;
{
register int i;
register u_long uaddr;
register u_char u;
/*
* make up socket address. Clear it out for neatness.
*/
bzero((char *)addr, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_port = htons(NTP_PORT);
check_size(sizeof(u_long));
for (i = 0, uaddr = 0; i < sizeof(u_long); i++) {
u = *config_pt++;
config_csum += (u_long)u;
uaddr <<= 8;
uaddr += (u_long)u;
}
addr->sin_addr.s_addr = htonl(uaddr);
}