4.1cBSD/usr/src/new/hyper/hyr_main.c

Compare this file to the similar file:
Show the results in this format:

#include <stdio.h>
#include <sys/types.h>
#include <net/hyroute.h>
#include <sys/socket.h>
#include <net/in.h>
#include <net/in_systm.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";
static char sccsid[] = "@(#)hyr_main.c	2.1 Hyperchannel Routing Daemon 82/11/29";

/*
 * Return the local network address portion of an
 * internet address; handles class a/b/c network
 * number formats.
 */
long
in_lnaof(in)
	struct in_addr in;
{
#if vax || pdp11
#define	IN_LNAOF(in) \
	(((in).s_addr&IN_CLASSA) == 0 ? (in).s_addr&IN_CLASSA_LNA : \
		((in).s_addr&IN_CLASSB) == 0 ? (in).s_addr&IN_CLASSB_LNA : \
			(in).s_addr&IN_CLASSC_LNA)
	return ((int)htonl((u_long)IN_LNAOF(in)));
#else
	return (IN_LNAOF(in));
#endif
}

/*
 * 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)
		printf("table set time: %s", ctime(&r->hyr_lasttime));
	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(in_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] = in_lnaof(s->s_gate[i]->s_fulladdr);
			add_gates(in_lnaof(s->s_fulladdr), s->s_ngate, gates, r);
		}
	}
}