BSD 4_2 release
[unix-history] / usr / src / new / new / hyper / src / hyr_main.c
#ifndef lint
static char sccsid[] = "@(#)hyr_main.c 4.2 (Berkeley) 7/8/83";
static char origsccsid[] = "@(#)hyr_main.c 2.1 Hyperchannel Routing Daemon 82/11/29";
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <vaxif/if_hy.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#define MAIN
#include "hyr_sym.h"
struct hyroute hy_route;
struct hyroute ker_hy_route;
int cflag = 0;
int sflag = 0;
int pflag = 0;
int dflag = 0;
int lexdebug;
int lex_error;
int maxgate = 0;
char *progname = "hy-route";
/*
* hash a hyperchannel address into the table
* return NULL if table is full or entry not found and adding a new one
*/
struct hy_hash *
rhash(key, new, r)
unsigned key;
int new;
register struct hyroute *r;
{
register struct hy_hash *rh = &r->hyr_hash[HYRHASH(key)];
int n = 0;
while (rh->hyr_key != key) {
if ((rh->hyr_flags & HYR_INUSE) == 0)
return(new ? rh : NULL);
if (n++ > HYRSIZE) {
return(NULL);
} else {
if (rh++ >= &r->hyr_hash[HYRSIZE])
rh = &r->hyr_hash[0];
}
}
return(rh);
}
/*
* add a direct entry to the hash table using the specified key,
* destination, control and access fields, return 0 if successful
*/
int
add_direct(key, dst, ctl, access, r)
unsigned key;
unsigned dst;
unsigned ctl;
unsigned access;
register struct hyroute *r;
{
register struct hy_hash *kh = rhash(key, 1, r);
if ((kh->hyr_flags & HYR_INUSE) == 0) {
kh->hyr_flags = (HYR_INUSE | HYR_DIR);
kh->hyr_key = key;
kh->hyr_dst = dst;
kh->hyr_ctl = ctl;
kh->hyr_access = access;
return(0);
}
return(1);
}
/*
* compare function for the qsort in add_gates, see below
*/
int
compare_gates(a, b)
unsigned *a, *b;
{
if (*a < *b)
return(-1);
else if (*a > *b)
return(1);
else
return(0);
}
/*
* add a gatewayed entry to the hash table using the sicified array of
* gateway keys. reuse space so as to make the gateway table small as
* possible. return 0 if successful
*/
int
add_gates(key, numgates, gates, r)
unsigned key;
unsigned numgates;
unsigned gates[256];
register struct hyroute *r;
{
register struct hy_hash *kh = rhash(key, 1, r);
register struct hy_hash *rh;
int i, j;
for (i = 0; i < numgates; i++) {
rh = rhash(gates[i], 1, r);
if (rh == NULL)
return(1);
gates[i] = rh - &r->hyr_hash[0];
}
qsort(gates, numgates, sizeof(unsigned), compare_gates);
/*
* loop through all existing hash table entries to find one that
* matches the currently requested list
*/
for (rh = &r->hyr_hash[0]; rh < &r->hyr_hash[HYRSIZE]; rh++) {
if (rh->hyr_flags & HYR_GATE) {
if ((rh->hyr_egate - rh->hyr_pgate + 1) == numgates) {
for (i = 0, j = rh->hyr_pgate; i < numgates ; i++, j++) {
if (gates[i] != r->hyr_gateway[j])
goto skipit;
}
/*
* found a match, just use it
*/
kh->hyr_flags = (HYR_INUSE | HYR_GATE);
kh->hyr_key = key;
kh->hyr_pgate = rh->hyr_pgate;
kh->hyr_egate = rh->hyr_egate;
kh->hyr_nextgate = rh->hyr_nextgate;
return(0);
}
}
skipit:
;
}
/*
* didn't find anything, if there is room add a new entry
*/
if (numgates + maxgate > 256)
return(1);
kh->hyr_flags = (HYR_INUSE | HYR_GATE);
kh->hyr_key = key;
kh->hyr_pgate = maxgate;
kh->hyr_egate = maxgate + numgates - 1;
kh->hyr_nextgate = maxgate;
for (i = 0; i < numgates; i++, maxgate++)
r->hyr_gateway[maxgate] = gates[i];
return(0);
}
/*
* set the kernel table
*/
settable(r)
struct hyroute *r;
{
int fd;
if ((fd = open("/dev/hy", 0)) < 0) {
perror("/dev/hy open in settable");
exit(1);
}
if (ioctl(fd, HYSETROUTE, (char *)r) < 0) {
perror("/dev/hy HYSETROUTE ioctl in settable");
exit(1);
}
if (close(fd) < 0) {
perror("/dev/hy close in settable");
exit(1);
}
}
/*
* get the kernel table
*/
gettable(r)
struct hyroute *r;
{
int fd;
if ((fd = open("/dev/hy", 0)) < 0) {
perror("/dev/hy open in gettable");
exit(1);
}
if (ioctl(fd, HYGETROUTE, (char *)r) < 0) {
perror("/dev/hy HYGETROUTE ioctl in gettable");
exit(1);
}
if (close(fd) < 0) {
perror("/dev/hy close in gettable");
exit(1);
}
}
/*
* print a somewhat readable version of the routine table
* that the kernel uses (mostly for debugging)
*/
print_table(r)
register struct hyroute *r;
{
register struct hy_hash *rh;
register int i;
extern char *ctime();
if (r->hyr_lasttime.tv_sec)
printf("table set time: %s", ctime(&r->hyr_lasttime.tv_sec));
else
printf("time not set\n");
for (i = 0; i < HYRSIZE; i++) {
rh = &r->hyr_hash[i];
if (rh->hyr_flags & HYR_INUSE) {
printf("hash %d key %04x flags %x\n", i, rh->hyr_key, rh->hyr_flags);
if (rh->hyr_flags & HYR_DIR)
printf("\tdst %04x ctl %04x access %04x\n",
ntohs(rh->hyr_dst),
ntohs(rh->hyr_ctl),
ntohs(rh->hyr_access));
else if (rh->hyr_flags & HYR_GATE)
printf("\tpgate %d egate %d nextgate %d\n",
rh->hyr_pgate,
rh->hyr_egate,
rh->hyr_nextgate);
}
}
for (i = 0; i < 256; i++) {
printf("gate[%d] = %d\n", i, r->hyr_gateway[i]);
if (r->hyr_gateway[i] == 0 && r->hyr_gateway[i+1] == 0)
break;
}
}
/*
* comnpare teo routing tables tom insure that they are the same
*/
compare_table(r1, r2)
register struct hyroute *r1, *r2;
{
register struct hy_hash *rh1, *rh2;
register int i;
int ndiffs = 0;
for (i = 0; i < HYRSIZE; i++) {
rh1 = &r1->hyr_hash[i];
rh2 = &r2->hyr_hash[i];
if (rh1->hyr_flags != rh2->hyr_flags) {
fprintf(stderr, "%s: hash entry %d - flags differ (%x vs %x)\n", progname, i, rh1->hyr_flags, rh2->hyr_flags);
ndiffs++;
} else if ((rh1->hyr_flags & HYR_INUSE) && (rh1->hyr_flags & HYR_DIR)) {
if (rh1->hyr_dst != rh1->hyr_dst ||
rh1->hyr_ctl != rh1->hyr_ctl ||
rh1->hyr_access != rh1->hyr_access) {
fprintf(stderr, "%s: direct hash entry %d - fields differ\n", progname, i);
fprintf(stderr, "\tdst: %04x vs %04x\tctl: %04x vs %04x\taccess: %04x vs %04x\n",
ntohs(rh1->hyr_dst), ntohs(rh2->hyr_dst),
ntohs(rh1->hyr_ctl), ntohs(rh2->hyr_ctl),
ntohs(rh1->hyr_access), ntohs(rh2->hyr_access));
ndiffs++;
}
} else if ((rh1->hyr_flags & HYR_INUSE) && (rh1->hyr_flags & HYR_GATE)) {
if (rh1->hyr_pgate != rh1->hyr_pgate ||
rh1->hyr_egate != rh1->hyr_egate ||
rh1->hyr_nextgate < rh1->hyr_pgate ||
rh1->hyr_nextgate > rh1->hyr_egate ||
rh2->hyr_nextgate < rh2->hyr_pgate ||
rh2->hyr_nextgate > rh2->hyr_egate) {
fprintf(stderr, "%s: direct hash entry %d - fields differ\n", progname, i);
fprintf(stderr, "\tpgate: %04x vs %04x\tegate: %04x vs %04x\tnextgate: %04x vs %04x\n",
rh1->hyr_pgate, rh2->hyr_pgate,
rh1->hyr_egate, rh2->hyr_egate,
rh1->hyr_nextgate, rh2->hyr_nextgate);
ndiffs++;
}
}
}
for (i = 0; i < 256; i++) {
if (r1->hyr_gateway[i] != r2->hyr_gateway[i]) {
fprintf(stderr, "%s: gate[%d] = %d v2 %d\n", progname, i,
r1->hyr_gateway[i], r2->hyr_gateway[i]);
}
}
return(ndiffs);
}
main(argc, argv)
int argc;
char *argv[];
{
char *filename = NULL; /* input file name (default stdin) */
char *cp;
if (argc)
progname = argv[0];
else
progname = "hy-route";
argc--; argv++;
while (argc) {
if (argv[0][0] == '-' && argv[0][1] != '\0') {
cp = &argv[0][0];
switch(*++cp) {
case 's': /* set the kernel table */
sflag++;
break;
case 'd': /* dump the kernel table */
dflag++;
break;
case 'p': /* print symbol table */
pflag++;
break;
case 'c': /* compare with kernel table */
cflag++;
break;
case 'l': /* check the parser */
lexdebug++;
break;
default:
fprintf(stderr, "%s: unrecognized switch -%c\n", progname, *cp);
exit(1);
}
} else if (filename == NULL) {
filename = argv[0];
} else {
fprintf(stderr, "%s: extra arguments starting with %s\n", progname, argv[0]);
exit(1);
}
argc--; argv++;
}
if (filename != NULL || sflag || cflag)
readin(filename, &hy_route);
if (pflag)
symtab_print();
if (sflag)
settable(&hy_route);
if (dflag || cflag)
gettable(&ker_hy_route);
if (dflag)
print_table(filename == NULL ? &ker_hy_route : &hy_route);
if (cflag)
compare_table(&hy_route, &ker_hy_route);
}
/*
* read in the control file named filename into structure r
*/
readin(filename, r)
char *filename;
register struct hyroute *r;
{
register char *cp;
register struct sym *s;
unsigned gates[256];
char buf[512];
unsigned i;
extern FILE *yyin;
if (filename == NULL || *filename == '\0' || strcmp(filename, "-") == 0) {
yyin = stdin;
} else {
yyin = fopen(filename, "r");
if (yyin == NULL) {
perror("/etc/hy-route");
exit(1);
}
}
maxgate = 0;
bzero((char *)r, sizeof(*r));
lex_error = 0;
yylex();
if (lex_error) {
fprintf(stderr, "hyroute: syntax errors, aborting operation\n");
exit(1);
}
for (s = sym_head; s != NULL; s = s->s_next) {
if (s->s_flags & HS_DIR) {
add_direct(inet_lnaof(s->s_fulladdr), s->s_dst, s->s_ctl, s->s_access, r);
} else if (s->s_flags & HS_INDIR) {
for (i = 0; i < s->s_ngate; i++)
gates[i] = inet_lnaof(s->s_gate[i]->s_fulladdr);
add_gates(inet_lnaof(s->s_fulladdr), s->s_ngate, gates, r);
}
}
}