home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
stg_v4.lzh
/
sroute.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-11
|
11KB
|
585 lines
/*
* sroute - list/change network routing tables
*
* 93/04/24 StG initial version
*
*/
/* maximum # of nodes that can net with me */
#define MAX_ONEHOP 64
/* maximum number of hops to get to any other node */
#define MAX_HOPS 64
#include "stgnet.h"
#include "db9.h"
#include "nodes.h"
char buf[256];
char hostname[32];
int iAuto=0;
int iDisplay=0;
int iNetList=0;
int iRemove=0;
struct sNode sNode;
int hNet;
struct sNode sScan;
int hScan;
struct sRoute
{
char acName[28];
long lSpeed;
int iHops;
};
struct sRoute asRoute[MAX_ONEHOP];
int iRoutes=0;
struct sRoute asHop[MAX_HOPS];
int iHops=0;
InRoute(s)
char *s;
{
int r;
r=0;
while (r<iRoutes)
{
if (!stricmp(s,asRoute[r].acName))
break;
r++;
}
if (r==iRoutes)
return(0);
return(1);
}
void
AddRoute(s)
char *s;
{
int r;
if (!*s)
return;
r=0;
while (r<iRoutes)
{
if (!stricmp(s,asRoute[r].acName))
break;
r++;
}
if (r==iRoutes)
{
if (iDisplay>1 && !iRoutes)
writeln(1,"One Hop list:\n",80);
if (++iRoutes==MAX_ONEHOP)
exit(syserr("maximum one hop array exceeded"));
strcpy(asRoute[r].acName,s);
if (iDisplay>1)
{
stringf(b,"%s\n",s);
writeln(1,b,80);
}
}
}
Used(name)
char *name;
{
int i;
i=0;
while (i<iRoutes)
if (!stricmp(name,asRoute[i++].acName))
return(1);
i=0;
while (i<iHops)
if (!stricmp(name,asHop[i++].acName))
return(1);
return(0);
}
Search(name)
char *name;
{
int n;
char *pc;
int first=1;
*sScan.acN_Name=0;
iHops-=1;
search:
if (iHops<0)
return(0);
if (stricmp(asHop[iHops].acName,sScan.acN_Name))
{
pc=asHop[iHops].acName;
n=_db9(DB_SEEK,hScan,pc,strlen(pc)+1);
if (n==ERR)
exit(syserr("DB9 seek %s: %m",pc));
if (!n)
{
/* not found, go back */
iHops--;
goto search;
}
if (_db9(DB_READ,hScan,&sScan,sizeof(sScan))==ERR)
exit(syserr("DB9 read scan: %m"));
asHop[iHops].lSpeed=sScan.wN_Speed;
}
if (!asHop[iHops].iHops && !first)
{
if (!stricmp(asHop[iHops].acName,name))
{
iHops++;
return(1);
}
}
first=0;
while (asHop[iHops].iHops<4)
{
n=asHop[iHops].iHops++;
pc=sScan.asNode2[n].acN2_Name;
if (!*pc || Used(pc))
continue;
iHops++;
if (iHops==MAX_HOPS)
exit(syserr("maximum route depth exceeded"));
strcpy(asHop[iHops].acName,pc);
asHop[iHops].iHops=0;
goto search;
}
if (asHop[iHops].iHops<5)
{
if (iHops+1==MAX_HOPS)
exit(syserr("maximum route depth exceeded"));
n=_db9(DB_SEEK,hScan,0,0);
if (n==ERR)
exit(syserr("DB9 seek 0: %m"));
asHop[iHops].iHops++;
}
else
{
pc=asHop[iHops+1].acName;
n=_db9(DB_SEEK,hScan,pc,strlen(pc)+1);
if (n==ERR)
exit(syserr("DB9 seek %s: %m",pc));
if (!n)
exit(syserr("bug: node %s not refound",pc));
}
while (n=_db9(DB_NEXT,hScan,&sScan,sizeof(sScan)))
{
n=0;
while (n<4)
{
if (!stricmp(asHop[iHops].acName,sScan.asNode2[n].acN2_Name))
{
iHops++;
strcpy(asHop[iHops].acName,sScan.acN_Name);
asHop[iHops].iHops=0;
goto search;
}
n++;
}
}
iHops--;
goto search;
}
void
Auto()
{
char acNew[32];
long lSpeed;
int r,h,best,d;
int iNewHops;
/* don't bother with dead, down, or local */
if (sNode.bN_Status==NS_DEAD)
return;
if (sNode.bN_Status==NS_DOWN)
return;
if (!stricmp(hostname,sNode.acN_Name))
return;
/* preset new with current setting */
strcpy(acNew,sNode.sRoute.acN2_Name);
if (iDisplay>1)
{
stringf(b,"Auto-selecting route for node %s (currently '%s'):\n",
sNode.acN_Name,acNew);
writeln(1,b,80);
}
/* if no route settings, cancel */
if (!iRoutes)
{
*acNew=0;
iNewHops=0;
goto change;
}
/* scan route table for single hop */
r=0;
while (r<iRoutes)
{
if (!stricmp(sNode.acN_Name,asRoute[r].acName))
break;
asRoute[r].lSpeed=0;
asRoute[r].iHops=0;
r++;
}
if (r<iRoutes)
{
strcpy(acNew,asRoute[r].acName);
iNewHops=1;
if (iDisplay>1)
{
stringf(b,"%s -> %s (one hop)\n",hostname,acNew);
writeln(1,b,80);
}
goto change;
}
/* search deeper through each 1st hop to find sNode.acN_Name */
r=0;
while (r<iRoutes)
{
/* preset first hop and search deeper */
iHops=0;
asHop[iHops].iHops=0;
strcpy(asHop[iHops++].acName,asRoute[r].acName);
while (Search(sNode.acN_Name))
{
/* route found, tally speed and build display */
if (iDisplay>1)
writeln(1,hostname,strlen(hostname));
lSpeed=0;
h=0;
while (h<iHops)
{
if (iDisplay>1)
{
writeln(1," -> ",4);
writeln(1,asHop[h].acName,strlen(asHop[h].acName));
}
lSpeed+=asHop[h++].lSpeed;
}
if (iDisplay>1)
{
sprintf(b,": %d00 avg baud\n",(int)(lSpeed/iHops));
writeln(1,b,strlen(b));
}
/* if best, save route */
if (!asRoute[r].iHops || iHops<asRoute[r].iHops)
{
asRoute[r].iHops=iHops;
asRoute[r].lSpeed=lSpeed;
}
if (iHops==asRoute[r].iHops && lSpeed>asRoute[r].lSpeed)
{
asRoute[r].lSpeed=lSpeed;
}
}
r++;
}
/* search route table for best route */
best=-1;
r=0;
d=-1;
lSpeed=0;
iHops=MAX_HOPS;
while (r<iRoutes)
{
if (!stricmp(sNode.sRoute.acN2_Name,asRoute[r].acName))
d=r;
if (best==-1 || asRoute[r].iHops<=iHops)
{
if (asRoute[r].iHops!=iHops)
lSpeed=0;
if (asRoute[r].iHops && asRoute[r].lSpeed>lSpeed)
{
best=r;
iHops=asRoute[r].iHops;
lSpeed=asRoute[r].lSpeed;
}
}
r++;
}
/* no route to sNode.acN_Name? */
if (best<0)
{
*acNew=0;
iNewHops=0;
goto change;
}
/* current default not in route table? */
if (d<0 || !asRoute[d].iHops)
{
strcpy(acNew,asRoute[best].acName);
iNewHops=asRoute[best].iHops;
goto change;
}
/* check default against best */
if (asRoute[best].iHops<asRoute[d].iHops)
{
strcpy(acNew,asRoute[best].acName);
iNewHops=asRoute[best].iHops;
}
if (asRoute[best].iHops==asRoute[d].iHops)
{
if (asRoute[best].lSpeed>asRoute[d].lSpeed)
{
strcpy(acNew,asRoute[best].acName);
iNewHops=asRoute[best].iHops;
}
}
change:
if (stricmp(sNode.sRoute.acN2_Name,acNew))
{
sNode.sRoute.bN2_Hops=iNewHops;
if (iDisplay)
Display(acNew);
strcpy(sNode.sRoute.acN2_Name,acNew);
if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 write nodes: %m"));
}
}
Display(new)
char *new;
{
if (sNode.bN_Status==NS_DEAD)
strcpy(buf,"(DEAD)");
else
if (sNode.bN_Status==NS_DOWN)
strcpy(buf,"(down)");
else
if (!stricmp(hostname,sNode.acN_Name))
strcpy(buf,"(local)");
else
strcpy(buf,sNode.sRoute.acN2_Name);
if (!*buf)
strcpy(buf,"(no route)");
if (new)
{
if (!*new)
new="(no route)";
stringf(b,"Route to node %s was %s, changed to %s (%d hops)\n",
sNode.acN_Name,buf,new,sNode.sRoute.bN2_Hops);
}
else
stringf(b,"%-15.15s %-15.15s (%d hops)\n",
sNode.acN_Name,buf,sNode.sRoute.bN2_Hops);
writeln(1,b,strlen(b));
}
main(argc,argv)
char **argv;
{
int n;
openerr(*argv,0,LOG_STGNET);
gethostname(hostname,32);
if (!*hostname)
exit(syserr("network not configured"));
dash(argv)
{
case '#':
wstringf(2,"sroute: %s\n",STG_VER);
exit(0);
case '?':
writeln(2,"sroute {-adn} {node} {route} - list/change routing\n",80);
writeln(2," -a - figure best routes automatically\n",80);
writeln(2," -d - display automatic mode decisions\n",80);
writeln(2," -n - display list of nodes netting with this one\n",80);
writeln(2," node - list/change specified node\n",80);
writeln(2," route - change routing for node\n",80);
STGVER;
exit(0);
case 'a':
iAuto++;
break;
case 'd':
iDisplay++;
break;
case 'n':
iNetList++;
break;
case 'r':
iRemove++;
break;
default:
exit(syserr("invalid option: %s",--*argv));
}
if (getuid()>=16 && (iAuto || iRemove || iDisplay ||*argv))
exit(syserr("no permission"));
setuid(0);
hNet=open(STG_FILE,O_RDWR|O_BINARY);
if (hNet==ERR)
exit(syserr("open %s: %m",STG_FILE));
if (_db9(DB_OPEN,hNet,"nodes",6)==ERR)
exit(syserr("DB9 open nodes: %m"));
/* select case insensitive seek */
if (_db9(DB_MATCH,hNet,-1,0)==ERR)
exit(syserr("DB9 match c-i: %m"));
hScan=open(STG_FILE,O_RDONLY|O_BINARY);
if (hScan==ERR)
exit(syserr("open %s: %m",STG_FILE));
if (_db9(DB_OPEN,hScan,"nodes",6)==ERR)
exit(syserr("DB9 open nodes: %m"));
/* select case insensitive seek */
if (_db9(DB_MATCH,hScan,-1,0)==ERR)
exit(syserr("DB9 match c-i: %m"));
/* build route choice list */
while (n=_db9(DB_NEXT,hScan,&sScan,sizeof(sScan)))
{
if (n==ERR)
exit(syserr("DB9 next: %m"));
/* if this is me, put all my routes on list */
if (!stricmp(sScan.acN_Name,hostname))
{
n=0;
while (n<4)
AddRoute(sScan.asNode2[n++].acN2_Name);
continue;
}
/* else if this node contacts me, put it on list */
n=0;
while (n<4)
{
if (!stricmp(hostname,sScan.asNode2[n++].acN2_Name))
{
AddRoute(sScan.acN_Name);
continue;
}
}
}
if (iNetList)
{
n=0;
while (n<iRoutes)
{
stringf(b,"%s\n",asRoute[n++].acName);
writeln(1,b,strlen(b));
}
exit(0);
}
if (*argv)
{
n=_db9(DB_SEEK,hNet,*argv,strlen(*argv)+1);
if (n==ERR)
exit(syserr("DB9 seek %s: %m",*argv));
if (!n)
exit(syserr("node %s not found",*argv));
if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 read nodes: %m"));
if (*++argv)
{
if (!InRoute(*argv))
exit(syserr("node %s not in net list",*argv));
Display(*argv);
strcpy(sNode.sRoute.acN2_Name,*argv);
if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 write nodes: %m"));
/* relock */
if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 read nodes: %m"));
/* allow automatic mode to override */
if (!iDisplay)
iDisplay=1;
Auto();
}
else
{
if (iAuto)
Auto();
else
Display(0);
}
close(hNet);
exit(0);
}
while (n=_db9(DB_NEXT,hNet,&sNode,sizeof(sNode)))
{
if (n==ERR)
exit(syserr("DB9 next: %m"));
if (iRemove)
{
sNode.sRoute.bN2_Hops=0;
*sNode.sRoute.acN2_Name=0;
if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 write nodes: %m"));
}
if (iAuto)
Auto();
else
Display(0);
}
close(hNet);
}