home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
p
/
pcrte224.zip
/
SOURCE.ZIP
/
CONFIG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-09
|
22KB
|
668 lines
/**************************************************************************/
/* config.c config.c */
/**************************************************************************/
/* config.c is an simple configuration program that creates
(or edits) a file called 'pcroute.cfg' that containing configuration
information for the pcroute program. the pcroute file is a Binary
file whose structure is simply a PCROUTE_CONFIG structure followed
by a list of ROUTE structures */
/* AUTHOR: Vance Morrison
DATE : 1/10/89
ADDRESS: morrison@accuvax.nwu.edu */
/**************************************************************************/
#include <stdio.h>
#define MAX_DATA 4096
typedef struct {
unsigned char type; /* type of configuration data */
unsigned char version; /* version of this piece of data */
unsigned short len; /* length of the DATA (that comes next) */
char buff[MAX_DATA]; /* the config data */
} CONF;
/* types for the 'type' field */
#define CONF_GENERIC 1 /* interface that requires no special config data */
#define CONF_LOCALTALK 2 /* Special localtalk extentions (zone name etc) */
#define CONF_SLIP 3 /* Special SLIP extentions (speed) */
#define CONF_ROUTE 10 /* static route configuration data */
#define CONF_BOOTP 20 /* Bootp configration data (forwarding host) */
#define CONF_ADMIN 21 /* administrative data (admin host) */
#define CONF_SYSLOG 22 /* host to send loging messages to */
typedef struct {
unsigned char addr[4];
} INET_ADDR;
typedef struct {
INET_ADDR address;
INET_ADDR mask;
unsigned short flags;
unsigned short metric;
} CONFIG_GENERIC;
typedef struct {
INET_ADDR address;
INET_ADDR mask;
unsigned short flags;
unsigned short metric;
unsigned char zones[64]; /* actually variable length */
} CONFIG_LOCALTALK;
typedef struct {
INET_ADDR address;
INET_ADDR mask;
unsigned short flags;
unsigned short metric;
unsigned short speed; /* actual 8250 divisor */
} CONFIG_SLIP;
typedef struct {
INET_ADDR net;
INET_ADDR gateway;
unsigned char metric;
unsigned char flags;
} CONFIG_ROUTE_ENTRY;
typedef struct {
unsigned short len;
CONFIG_ROUTE_ENTRY routes[1]; /* actually variable length */
} CONFIG_ROUTE;
typedef struct {
INET_ADDR forward_addr;
} CONFIG_BOOTP;
typedef struct {
INET_ADDR log_host;
short log_priority;
short log_mask;
} CONFIG_SYSLOG;
typedef struct {
INET_ADDR admin;
} CONFIG_ADMIN;
/**************************************************************************/
main()
{
FILE *cfg_rfile, *cfg_wfile;
char config[64];
printf("This program creates/edits the pcroute.cfg file\n");
if (get_config(config, 64) != 0) {
fprintf(stderr, "Could not get configuration from 'pcroute.exe'\n");
return;
}
cfg_wfile = fopen("pcroute.new", "wb");
if (cfg_wfile == NULL) {
fprintf(stderr, "Could not open 'pcroute.new'\n");
return;
}
cfg_rfile = fopen("pcroute.cfg", "rb");
if (update_config(cfg_wfile, cfg_rfile, config) == 0) {
fclose(cfg_wfile);
unlink("pcroute.cfg");
rename("pcroute.new", "pcroute.cfg");
}
else {
fclose(cfg_wfile);
unlink("pcroute.new");
fprintf(stderr, "Error generating configuration file\n");
}
}
/**************************************************************************/
/* update_config writes out a configuration file 'cfg_wfile' conforming
to the configuration in 'config' using 'cfg_rfile' as defaults. It
returns 0 on success */
int update_config(cfg_wfile, cfg_rfile, config)
FILE *cfg_wfile, *cfg_rfile;
char *config;
{
CONF data, datain;
int len;
datain.type = 0;
while(*config != 0) {
/* get the old data structure if possible */
while (datain.type < *config) {
read_config(&datain, cfg_rfile);
if (datain.type == 0)
break;
}
if (datain.type == *config) {
memcpy(&data, &datain, sizeof(CONF));
datain.type = 0;
}
else
memset(&data, 0, sizeof(CONF));
len = -1;
switch(config[0]) {
case CONF_GENERIC:
len = config_generic(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_ROUTE:
len = config_routes(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_LOCALTALK:
len = config_localtalk(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_SLIP:
len = config_slip(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_BOOTP:
len = config_bootp(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_SYSLOG:
len = config_syslog(data.version, config[1], data.buff, MAX_DATA);
break;
case CONF_ADMIN:
break;
}
if (len < 0 || len > MAX_DATA) {
fprintf(stderr, "I do not understand the pcroute.exe config\n");
return(-1);
}
data.len = len;
data.type = *config++;
data.version = *config++;
fwrite(&data, data.len+4, 1, cfg_wfile);
}
return(0);
}
/***************************************************************************/
/* read_config reads in the next configuration object from the file 'cfg_rfile'
and puts in in the conf structure 'data'. If any errors return, the conf
structure is nulled */
read_config(data, cfg_rfile)
CONF *data;
FILE *cfg_rfile;
{
memset(data, 0, sizeof(CONF));
if (cfg_rfile != NULL)
if (fread(data, 4, 1, cfg_rfile) == 1)
if (data->len <= MAX_DATA)
if (fread(data->buff, data->len, 1, cfg_rfile) == 1)
return;
memset(data, 0, sizeof(CONF));
}
/**************************************************************************/
/* config_generic prompts for the generic interface configuration data
it puts it in the buffer 'generic' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_generic(oldver, newver, generic, len)
unsigned int oldver, newver;
CONFIG_GENERIC *generic;
int len;
{
int flags;
if (len < sizeof(CONFIG_GENERIC) || newver != 2) {
fprintf(stderr,"Can't configure this version of PCroute's interface\n");
return(-1);
}
if (oldver == 1)
generic->metric = 0;
else if (oldver > 2)
memset(generic, 0, sizeof(CONFIG_GENERIC));
printf("\nConfiguring an interface\n");
get_INET_addr(&generic->address, "Address for the interface");
get_INET_addr(&generic->mask, "Subnet mask for the interface");
printf("Flag Meanings (if set)\n");
printf(" Bit 0 (1h) - Don't send routing updates out this interface\n");
printf(" Bit 1 (2h) - Don't listen to routing updates from this interface\n");
printf(" Bit 2 (4h) - Proxy Arp for all subnets\n");
printf(" Bit 3 (8h) - Turn off directed broadcasts\n");
printf(" Bit 4 (10h) - Turn off the issuing of ICMP redirects\n");
printf(" Bit 5 (20h) - Broadcast using old (0's) format\n");
get_hex(&generic->flags, "Flags (HEX) for the interface");
if (generic->metric == 0)
generic->metric = 1;
for(;;) {
get_hex(&generic->metric, "Routing Metric (HEX) for the interface");
if (generic->metric >= 0 && generic->metric < 16)
break;
generic->metric = 1;
}
return(sizeof(CONFIG_GENERIC));
}
/**************************************************************************/
/* config_localtalk prompts for the localtalk configuration data
It puts it in the buffer 'localt' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_localtalk(oldver, newver, localt, len)
int oldver, newver;
CONFIG_LOCALTALK *localt;
int len;
{
int flags;
unsigned char *ptr;
char buff[256];
char changed;
if (len < sizeof(CONFIG_LOCALTALK) || newver != 2) {
fprintf(stderr,"Can't configure this version of PCroute's localtalk\n");
return(-1);
}
if (oldver == 1)
memset(&localt->metric, 0, 66);
if (oldver > 2)
memset(localt, 0, len);
printf("\nConfiguring an interface\n");
get_INET_addr(&localt->address, "Address for LOCALTALK interface");
get_INET_addr(&localt->mask, "Subnet mask for LOCALTALK interface");
printf("Flag Meanings (if set)\n");
printf(" Bit 0 (1h) - Don't send routing updates out this interface\n");
printf(" Bit 1 (2h) - Don't listen to routing updates from this interface\n");
printf(" Bit 2 (4h) - Proxy Arp for all subnets\n");
printf(" Bit 3 (8h) - Turn off directed broadcasts\n");
printf(" Bit 4 (10h) - Turn off the issuing of ICMP redirects\n");
get_hex(&localt->flags, "Flags (HEX) for the interface");
if (localt->metric == 0)
localt->metric = 1;
for(;;) {
get_hex(&localt->metric, "Routing Metric (HEX) for the interface");
if (localt->metric > 0 && localt->metric < 16)
break;
localt->metric = 1;
}
printf("\nPlease list all LOCALTALK zones that have gatways that this\n");
printf("router talks to. (don't forget '*' (the current zone)\n");
printf("End with a '.'\n");
ptr = localt->zones;
changed = 0;
for(;;) {
if (changed)
*ptr = 0;
strncpy(buff, &ptr[1], ptr[0]); /* copy the default */
buff[ptr[0]] = '\0'; /* make sure the string is ended */
printf("Zone [%s]: ", buff);
gets(buff);
if (*buff == '.')
break;
if (*buff != '\0') { /* not the default */
changed = 1;
ptr[0] = strlen(buff);
if (ptr + ptr[0] < &localt->zones[64 - 2]) { /* will it fit? */
strcpy(&ptr[1], buff);
}
else {
printf("Sorry, zone buffer full\n");
break;
}
}
ptr += ptr[0]+1;
}
*ptr = 0;
return(sizeof(CONFIG_LOCALTALK));
}
/**************************************************************************/
/* config_slip prompts for the slip configuration data
It puts it in the buffer 'slip' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_slip(oldver, newver, slip, len)
int oldver;
CONFIG_SLIP *slip;
int len;
{
unsigned int speed;
unsigned char *ptr;
char buff[256];
char changed;
if (len < sizeof(CONFIG_SLIP) || newver != 1) {
fprintf(stderr,"Can't configure this version of PCroute's slip\n");
return(-1);
}
if (oldver != 1)
memset(slip, 0, len);
printf("\nConfiguring a SLIP interface\n");
get_INET_addr(&slip->address, "Address for SLIP interface");
get_INET_addr(&slip->mask, "Subnet mask for SLIP interface");
printf("Flag Meanings (if set)\n");
printf(" Bit 0 (1h) - Don't send routing updates out this interface\n");
printf(" Bit 1 (2h) - Don't listen to routing updates from this interface\n");
printf(" Bit 2 (4h) - Proxy Arp for all subnets\n");
printf(" Bit 3 (8h) - Turn off directed broadcasts\n");
printf(" Bit 4 (10h) - Turn off the issuing of ICMP redirects\n");
get_hex(&slip->flags, "Flags (HEX) for the interface");
if( slip->speed == 0 )
slip->speed = 12; /* default of 9600 baud */
for(;;) {
printf( "\nEnter speed for this interface (ex. 9600, 19200, ...) [%ld] ", 115200L / slip->speed );
gets(buff);
if( *buff == 0 ) {
speed = slip->speed;
break;
}
speed = 115200L / (unsigned) atol( buff );
if( (long)speed * (unsigned) atol( buff ) == 115200L )
break;
printf( "Bad speed\n" );
}
slip->speed = speed;
if (slip->metric == 0)
slip->metric = 1;
for(;;) {
get_hex(&slip->metric, "Routing Metric (HEX) for the interface");
if (slip->metric > 0 && slip->metric < 16)
break;
slip->metric = 1;
}
return(sizeof(CONFIG_SLIP));
}
/**************************************************************************/
/* config_bootp prompts for the bootp configuration data.
It puts it in the buffer 'bootp' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_bootp(oldver, newver, bootp, len)
int oldver, newver;
CONFIG_BOOTP *bootp;
int len;
{
if (len < sizeof(CONFIG_BOOTP) || newver != 1) {
fprintf(stderr, "Can't configure this version of PCroute's bootp\n");
return(-1);
}
if (oldver != 1)
memset(bootp, 0, sizeof(CONFIG_BOOTP));
printf("\nIf you wish to forward bootp packets please enter the address\n");
printf(" of the address to forward it to. This address can be a\n");
printf(" directed broadcast. 0.0.0.0 means don't forward\n\n");
get_INET_addr(&bootp->forward_addr, "Address to forward bootp packets");
return(sizeof(CONFIG_BOOTP));
}
/**************************************************************************/
/* config_syslog prompts for the logging configuration data.
It puts it in the buffer 'localt' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_syslog(oldver, newver, log, len)
int oldver, newver;
CONFIG_SYSLOG *log;
int len;
{
if (len < sizeof(CONFIG_SYSLOG) || newver != 1) {
fprintf(stderr, "Can't configure this version of PCroute's syslog\n");
return(-1);
}
if (oldver != 1)
memset(log, 0, sizeof(CONFIG_SYSLOG));
printf("\nOnce PCroute boots up, it sends all log messages to a network\n");
printf(" host running a BSD UNIX syslogd daemon. To disable\n");
printf(" logging enter 0.0.0.0\n\n");
get_INET_addr(&log->log_host, "Host to send loging info to");
printf("Mask Meanings (0 = Log, 1 = Don't log)\n");
printf(" Bit 0 (1h) - System\n");
printf(" Bit 1 (2h) - Routing\n");
printf(" Bit 2 (4h) - Monitor\n");
printf(" Bit 3 (8h) - Localtalk\n");
get_hex(&log->log_mask, "Logging mask for this router");
printf("There are 8 routing 'levels' supported\n");
printf(" 0 - Emergency 1 - Alert 2 - Critical 3 - Error\n");
printf(" 4 - Warning 5 - Notice 6 - info 7 - Debug\n");
printf("Only messages with a level less than the logging level are sent\n");
get_hex(&log->log_priority, "Logging level");
return(sizeof(CONFIG_SYSLOG));
}
/**************************************************************************/
/* config_routes prompts for the static routes data.
It puts it in the buffer 'localt' of length 'len'. The buffer is
loaded with version 'oldver' and should be inititialized for version
'newver' */
int config_routes(oldver, newver, route, len)
int oldver, newver;
CONFIG_ROUTE *route;
int len;
{
CONFIG_ROUTE_ENTRY *ptr;
int count;
short holder;
if (len < sizeof(CONFIG_ROUTE_ENTRY)+2 || newver != 1) {
fprintf(stderr, "Can't configure this version of PCroute's RIP\n");
return(-1);
}
if (oldver != 1)
memset(route, 0, len);
printf("\nIf you wish to configure static routes do so here. ");
printf("To stop type a '.'\n\n");
printf(" Flag Meanings (if set)\n");
printf(" Bit 0 (1h) - Local route, do not propagate it\n");
printf(" Bit 1 (2h) - Transient route, subject to RIP protocol\n");
count = 0;
ptr = route->routes;
while (count < (len-2)/sizeof(CONFIG_ROUTE_ENTRY)) {
printf("\n");
if (get_INET_addr(&ptr->net, "Network") < 0)
break;
if (get_INET_addr(&ptr->gateway, "Gateway") < 0)
break;
holder = ptr->metric;
if (holder == 0)
holder = 9;
if (get_hex(&holder, "Metric (HEX) ") < 0)
break;
ptr->metric = holder;
holder = ptr->flags;
if (get_hex(&holder, "Flags (HEX)") < 0)
break;
ptr->flags = holder;
count++;
ptr++;
}
route->len = count;
return(count*sizeof(CONFIG_ROUTE_ENTRY)+2);
}
/**************************************************************************/
/* get_config reads in the binary file 'pcroute.exe' and extracts the
configuration information from it and put it in the string 'str' of
length 'len' It returns 0 on SUCCESS */
int get_config(str, len)
char *str;
int len;
{
FILE *pcroute;
static char look_for[] = "CONFIG ->";
char *ptr;
int c;
pcroute = fopen("pcroute.exe", "rb");
if (pcroute == NULL) {
return(-1);
}
ptr = look_for;
while(*ptr != '\0') {
c = getc(pcroute);
if (c < 0) {
fclose(pcroute);
return(-1);
}
else if (c == *ptr)
ptr++;
else
ptr = look_for;
}
--len;
--len;
for(;;) {
if (len <= 0)
break;
*str = getc(pcroute);
if (*str <= 0) /* either EOF or null character */
break;
str++;
--len;
}
*str++ = '\0';
*str = '\0'; /* need a word of null, just in case */
fclose(pcroute);
return(0);
}
/**************************************************************************/
/* get_hex prompts the user with 'prompt' and retrieves a two byte
hex number and returns it in in addr. It returns
0 if successful. If the user inputs an invalid address, get_hex
will loop. If the user inputs a '.' it returns -1 if the user inputs
a '^', get_INET_addr returns -2 */
get_hex(addr, prompt)
short *addr;
char *prompt;
{
char buffer[256];
int flags;
for(;;) {
printf("%s [%xH] ? ", prompt, *addr);
gets(buffer);
if (*buffer == 0) /* carrage return = default */
return(0);
if (*buffer == '.') /* wish to return */
return(-1);
if (*buffer == '^') /* wish to return */
return(-2);
if (sscanf(buffer, "%x", &flags) == 1) {
*addr = flags;
return(0);
}
}
}
/**************************************************************************/
/* get_INET_addr prompts the user with 'prompt' and retrieves an internet
address (in dot notation) from the user and places it in addr. It returns
0 if successful. If the user inputs an invalid address, get_INET_addr
will loop. If the user inputs a '.' it returns -1 if the user inputs
a '^', get_INET_addr returns -2 */
get_INET_addr(addr, prompt)
INET_ADDR *addr;
char *prompt;
{
char buffer[256];
for(;;) {
INET_to_dot(*addr, buffer);
printf("%s [%s] ? ", prompt, buffer);
gets(buffer);
if (*buffer == 0) /* carrage return = default */
return(0);
if (*buffer == '.') /* wish to return */
return(-1);
if (*buffer == '^') /* wish to return */
return(-2);
if (dot_to_INET(buffer, addr))
return(0);
}
}
/*****************************************************************************/
/* routines for converting to and from dot notation and INET_ADDR structures */
INET_to_dot(inet, dot)
INET_ADDR inet;
char *dot;
{
sprintf(dot, "%d.%d.%d.%d", inet.addr[0], inet.addr[1],
inet.addr[2], inet.addr[3]);
}
dot_to_INET(dot, inet)
char *dot;
INET_ADDR *inet;
{
int bytes[4];
int ret;
ret = sscanf(dot,"%d.%d.%d.%d", &bytes[0], &bytes[1], &bytes[2], &bytes[3]);
if (ret != 4)
return(0);
inet->addr[0] = bytes[0];
inet->addr[1] = bytes[1];
inet->addr[2] = bytes[2];
inet->addr[3] = bytes[3];
return(1);
}