home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
547.TNL7A.C
< prev
next >
Wrap
Text File
|
1988-05-14
|
21KB
|
513 lines
/*****************************************************************************/
/* */
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNet */
/* ***** ***** Portable. Compatible. */
/* ***** ***** Public Domain */
/* ***** ***** NORD><LINK */
/* */
/* This software is public domain ONLY for non commercial use */
/* */
/* */
/*****************************************************************************/
/* Level 7A, Dataswitch */
/* Version 1.01 */
/* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig */
/* 05-MAY-88 */
# include "tndef.h" /* Definition von Konstanten */
# include "tntyp.h" /* Definition der Typen */
# include "tnl7av.c" /* Definition Variablen */
# include "tnl7ae.h" /* externe Definitionen */
/*---------------------------------------------------------------------------*/
char beades[] = { 'I','D',' ',' ',' ',' ','\140' }; /* Call fuer Bake */
char beadil[] = ""; /* Digiliste fuer Bake */
char cqdest[] = { 'C','Q',' ',' ',' ',' ','\140' }; /* Call fuer CQ-Ruf */
char cqdil[] = ""; /* Digiliste fuer CQ-Ruf */
char dmmsg[] = "Busy from "; /* DM Meldung */
char conmsg[] = "Connected to "; /* Connect Meldung */
char signon[] = "TheNet Version 1.01 ("; /* Kopfmeldung */
/*---------------------------------------------------------------------------*/
partyp partab[] = { /* Parameter Tabelle */
&maxdes, 1, 400, /* maximale Laenge der Destination Liste */
&worqua, 0, 255, /* minimale Qualiatet fuer Autoupdate */
&ch0qua, 0, 255, /* HDLC Kanal Qualitaet */
&ch1qua, 0, 255, /* RS232 Kanal Qualitaet */
&obcini, 0, 255, /* Anfangswert Knotenlebensdauer */
&obcbro, 1, 255, /* min Wert Restlebensdauer fuer Rundspruch */
&broint, 0, 0xffff, /* Rundspruchintervall */
&timliv, 0, 255, /* Anfangswert Paketlebensdauer */
&tratou, 5, 600, /* Timeout in Level3 */
&tratri, 2, 127, /* Versuche in Level3 */
&traack, 1, 60, /* Level3 Wartezeit bis ACK */
&trabsy, 1, 1000, /* Level3 Busy Wartezeit */
&trawir, 1, 127, /* vorgeschlagene Fenstergroesse in Level3 */
&conctl, 1, 127, /* gebufferte Frames je Verbindung */
&ininat, 0, 0xffff, /* no-activity-timeout */
&Ppar, 0, 255, /* Entschlossenheit fuer Sendung frei */
&Wpar, 0, 127, /* Zeitschlitzbreite */
&Fpar, 1, 15, /* Level2, Timer1 */
&Opar, 1, 7, /* Level2, Fenstergroesse */
&Npar, 0, 127, /* Level2, Versuche */
&T2par, 0, 6000, /* Level2, Timer2 */
&T3par, 0, 0xffff, /* Level2, Timer3 */
&Rpar, 0, 1, /* Level2 Digipeating Freigabe */
&VCpar, 0, 1, /* Calls pruefen */
&beacen, 0, 2, /* Bake ein-aus */
&cqen, 0, 1 /* CQ-Ruf ein-aus */
};
/*---------------------------------------------------------------------------*/
cmdtyp cmdtab[] = { /* Befehlstabelle */
ccpcm1, ccpcon,
ccpcm8, ccpcq,
ccpcm2, ccpide,
ccpcm3, ccpnod,
ccpcm4, ccppar,
ccpcm9, ccprou,
ccpcm5, ccpres,
ccpcm6, ccpsys,
ccpcm7, ccpuse,
ccpc10, ccphig,
ccpc11, ccplow,
0, 0
};
char ccpcm1[] = "CONNECT";
char ccpcm8[] = "CQ";
char ccpcm2[] = "INFO";
char ccpcm3[] = "NODES";
char ccpcm4[] = "PARMS";
char ccpcm9[] = "ROUTES";
char ccpcm5[] = "RESET";
char ccpcm6[] = "SYSOP";
char ccpcm7[] = "USERS";
char ccpc10[] = "HIGH";
char ccpc11[] = "LOW";
/*---------------------------------------------------------------------------*/
mainf() { /* Einsprung vom Assembler Teil nach Init */
diinc(); /* Interrupts aus */
inivar(); /* Variable initialisieren */
initl4(); /* Level 4 " */
l3init(); /* Level 3 " */
l2init(); /* Level 2 " */
hosini(); /* Hostinterface initialisieren */
srand(); /* Zufallsgenerator initialisieren */
decei(); /* Interrupts wieder an */
bstrng("\015\012");
bstrng(signon); /* melden */
bcalou(myid); /* eigenes Call */
bstrng(")\015\012");
bstrng("by NORD><LINK (DF2AU/DC4OX)\015\012\012");
loop: /* ewige Schleife */
hostsv(); /* Hostinterface */
l2(); /* Level 2 */
l3serv(); /* Level 3 */
l4serv(); /* Level 4 */
timsrv(); /* Timerservice */
goto loop;
}
/*---------------------------------------------------------------------------*/
VOID inivar() /* Variable initialisieren */
{
unsigned cnt; /* Scratch Zaehler */
char *chaptr; /* fuer Passwort kopieren */
inithd(&usccpl); /* CCP User Liste initialisieren */
inithd(&userhd); /* User Liste initialisieren */
for (cnt = 0, ptcrdp = ptcrdl;/* Patchcordliste aufbauen */
cnt < NUMPAT; ++cnt, ++ptcrdp) {
ptcrdp->luserl = 0; /* kein Kontrollblock */
}
tic10 = /* loeschen: 10ms Timer */
lastic = /* letzte Ablesung bei 0 */
tic1s = /* Sekundenzaehler */
beatim = 0; /* Bakenuhr */
if (!iswarm()) { /* nur im Kaltstart */
Ypar = MAXL2L; /* maximal Links in Level2 */
Tpar = defTp; /* Senderverzoegerung */
Ppar = DEFPER; /* Persistance */
Wpar = DEFSLO; /* Zeitscheibengroesse */
Fpar = DEFRAK; /* Level2 FRACK */
Opar = DEFMAF; /* Fenstergroesse in Level2 */
Npar = DEFL2T; /* Versuche in Level2 */
T2par = DEFLT2; /* Level2 Timer 2 */
T3par = DEFLT3; /* Level2 Timer 3 */
Rpar = DEFRPA; /* Level2 Digipeating */
Vpar = DEFL2L; /* Level2 Protokollversion */
Dpar = DEFDPA; /* Full-Duplex */
xFpar = DEFXFP; /* Full-Duplex mit Flags */
ininat = DEFNOA; /* no-activity-timeout */
conctl = DEFCON; /* Frames im Buffer je Link */
beacen = DEFBEA; /* Bakenform */
paswle = 0; /* Passwort aus Eprom kopieren */
chaptr = &DEFPWD[0];
while (*chaptr != 0)
{
paswrd[paswle++] = *chaptr++;
}
infmsg[0] = 0; /* keine Info-Message */
cpyid(myid, DEFCAL); /* Call setzen */
cpy6ch(alias, DEFIDE); /* Ident setzen */
VCpar = DEFVAL; /* Call pruefen */
cqen = DEFCQ; /* CQ-Ruf erlaubt */
}
}
/*---------------------------------------------------------------------------*/
VOID timsrv() /* zeitabhaengige Funktionen */
{
char *usnxtc; /* naechstes Zeichen im Frame */
char *cmdnam; /* Befehlsname */
unsigned zeit; /* Zeit in 10ms seit letztem Service */
unsigned usget; /* Getcount */
unsigned cnt; /* Scratch Zaehler */
unsigned zeichen; /* Scratch fuer gelesene Zeichen */
mhtyp *mhdp; /* Pointer auf aktuelles Frame */
mhtyp *usrmhd; /* User MBHD Kopie */
cmdtyp *cmdpoi; /* Pointer in Befehlstabelle */
diinc(); /* Interrupts aus */
zeit = tic10 - lastic; /* vergangene Zeit seit letztem Service */
lastic = tic10; /* neuen Nullpunkt merken */
decei(); /* Interrupts wieder frei */
if (zeit != 0) /* nicht zu oft... */
{
l2timr(zeit); /* an Level2 melden */
if ((tic1s +=zeit) >= 100) /* alle Sekunde: */
{
tic1s -=100; /* Uebertrag merken */
hostim(); /* Hostinterface */
chknoa(); /* Nichtstuer ueberwachen */
brosrv(); /* Rundsprueche */
trasrv(); /* Level3 und Level4 Service */
beacon(); /* Bake */
}
}
/*=== eingelaufene Info Frames fuer den CCP verarbeiten ===*/
while ((mhdp = (mhtyp *) userhd.lnext) != (mhtyp *) &userhd.lnext)
{ /* Info Frames fuer CCP */
unlink(mhdp); /* Info aushaengen */
for (userpo = (usrtyp *) usccpl.lnext; /* User zur Info suchen */
(usrtyp *) &usccpl != userpo; /* gesamte Liste absuchen */
userpo = userpo->unext) {
if ((mhdp->usrtyp == userpo->typ_u) /* Usertyp und Kontrollblock */
&& (mhdp->l2lnk == userpo->cblk_u)) /* muessen passen */
break; /* dann gefunden */
}
if ((usrtyp *) &usccpl == userpo) { /* kein User gefunden */
userpo = (usrtyp *) allocb(); /* dann ist es ein neuer Teilnehmer */
userpo->mbhd = 0; /* keine Info wartend */
userpo->sysflg = ! (userpo->typ_u = mhdp->usrtyp); /* Typ setzen */
userpo->cblk_u = mhdp->l2lnk; /* Kontrollblock setzen */
userpo->errcnt = 0; /* bisher keine Fehler */
userpo->status = 1; /* am CCP, Befehl kommt */
relink(userpo, usccpl.lprev); /* User in Kette haengen */
}
/*=== eingelaufene Info Frames fuer User verarbeiten ===*/
if (!(usrmhd = userpo->mbhd))
userpo->mbhd = mhdp;
else {
usnxtc = usrmhd->nxtchr;
usget = usrmhd->getcnt;
while (usrmhd->getcnt < usrmhd->putcnt)
getchr(usrmhd);
while (mhdp->getcnt < mhdp->putcnt)
putchr(getchr(mhdp), usrmhd);
usrmhd->nxtchr = usnxtc;
usrmhd->getcnt = usget;
dealmb(mhdp);
}
while ((userpo != 0) /* existiert der User noch? */
&& ((mhdp = userpo->mbhd) != 0) /* ist Info da? */
&& (getlin(mhdp) == 1)) { /* ist es mindestens eine ganze Zeile? */
clipoi = clilin; /* Zeile als leer definieren */
clicnt = 0;
while ((mhdp->getcnt < mhdp->putcnt) /* so lange Zeichen vorhanden sind*/
&& ((zeichen = getchr(mhdp) & 0x7f) != 0x0d)) { /* und kein <CR> */
if ((zeichen == 0x08) || (zeichen == 0x7f)) { /* Backspace */
if (clicnt != 0) { /* und Delete aussortieren */
--clipoi;
--clicnt;
}
}
else {
if ((zeichen != 0x0a) /* Linefeed zaehlt nicht mit */
&& (clicnt < 80)) { /* Zeilenueberlauf beachten */
*clipoi++ = zeichen;/* Zeichen merken */
++clicnt; /* mitzaehlen */
}
}
}
if (mhdp->getcnt == mhdp->putcnt) { /* wenn nun alle Zeichen verbraucht*/
dealmb(mhdp); /* Buffer wieder freigeben */
userpo->mbhd = 0; /* und "keine Info mehr da" markieren */
}
/*=== Zeile vom User auswerten ===*/
clipoi = clilin; /* zum Auswerten Pointer nach vorn */
if (userpo->status == 3) { /* warten auf Passwort? */
for (cnt = 0; cnt < 5; ++cnt) { /* 5 Zeichen als Antwort */
if (skipsp(&clicnt, &clipoi) == 0) /* noch was da? */
break; /* nein, dann Ende */
zeichen = *clipoi++; /* sonst Zeichen holen */
--clicnt;
if (paswrd[userpo->paswrd[cnt] & 0xff] != zeichen) /* stimmt? */
break;
}
if (cnt == 5) /* 5 Richtige? */
userpo->sysflg = 1;
userpo->status = 1; /* neuer Status: warten auf Befehl */
}
else {
if (userpo->status == 2) { /* warten auf Connect? */
disusr(userpo->cblk_p, userpo->typ_p); /* dann beenden */
userpo->status = 1; /* neuer Status: warten auf Befehl */
}
if (skipsp(&clicnt, &clipoi) == 1) { /* noch was in der Zeile? */
usnxtc = clipoi;
usget = clicnt; /* Position in der Zeile merken */
for (cmdpoi = cmdtab; /* Eingabe mit Tabelle vergleichen */
cmdpoi->cmdstr != 0; /* Ende ist NULL */
++cmdpoi) {
clipoi = usnxtc;
clicnt = usget; /* fuer jeden Test auf Zeilenanfang */
cmdnam = cmdpoi->cmdstr;
while ((clicnt != 0) && (*clipoi != ' ')) {
if (upcase(*clipoi) != *cmdnam) break; /* Abbruch bei ungleich */
++clipoi;
--clicnt;
++cmdnam;
}
if ((clicnt == 0) || (*clipoi == ' ')) break; /* passt das Wort? */
}
if (cmdpoi->cmdfun != 0) { /* auf Tabellenende gelaufen? */
userpo->errcnt = 0; /* nein, Fehlerzaehler ruecksetzen */
skipsp(&clicnt, &clipoi); /* vorruecken auf Argument */
(*cmdpoi->cmdfun)(); /* Befehl ausfuehren */
}
else {
putmsg("Invalid Command (CONNECT CQ INFO NODES ROUTES USERS)");
if (++userpo->errcnt == 5) { /* Fehler zaehlen */
disusr(userpo->cblk_u, userpo->typ_u);
kilusr(); /* zuviel Mist? Rauswerfen */
} } } } } } }
/*---------------------------------------------------------------------------*/
VOID l2tol7(opcod, link, typ)/* auf S-Frame reagieren */
unsigned opcod; /* Frametyp: 1=UA, 2=DISC, 3=DM, 4=? */
ctyp *link; /* Kontrollblock */
unsigned typ; /* User Typ */
{
unsigned cnt; /* Scratch Zaehler */
if (opcod < 5) { /* zulaessiger Frametyp? */
if (opcod == 1) { /* UA Frame */
for (userpo = (usrtyp *) usccpl.lnext; /* User in CCP-Liste suchen */
(usrtyp *) &usccpl != userpo;
userpo = userpo->unext) {
if ((userpo->status == 2) /* Status des Users: "SABM gegeben"? */
&& (userpo->typ_p == typ) /* Partner muss erwarteter Typ sein */
&& (userpo->cblk_p == (l2ltyp *) link)){ /* Kontrollblock passt? */
msgfrm('D', link, typ, conmsg); /* Erfolg melden */
for (ptcrdp = ptcrdl; /* Platz in Patchcordliste suchen */
ptcrdp->luserl != 0;
ptcrdp += 2);
ptcrdp->luserl = userpo->cblk_u; /* beide User eintragen */
ptcrdp->lusert = userpo->typ_u; /* Kontrollblock und Typ */
(++ptcrdp)->luserl = (l2ltyp *) link;
ptcrdp->lusert = typ;
kilusr(); /* User aus Level7 entfernen */
break;
}
}
return; /* fertig */
}
for (cnt = 0, ptcrdp = ptcrdl; /* DISC oder DM erhalten */
cnt < NUMPAT; /* Patchcordliste nach User absuchen */
++cnt, ++ptcrdp)
{
if ((ptcrdp->lusert == typ)
&& (ptcrdp->luserl == (l2ltyp *) link))
{
ptcrdp->luserl = 0; /* Eintrag loeschen */
cnt ^= 1; /* auf andere Seite der Verbindung */
ptcrdp = &ptcrdl[cnt];
disusr(ptcrdp->luserl, ptcrdp->lusert); /* Partner */
ptcrdp->luserl = 0; /* Eintrag loeschen */
return; /* fertig */
}
}
for (userpo = (usrtyp *) usccpl.lnext; /* muss CCP User sein */
(usrtyp *) &usccpl != userpo; /* Tabelle absuchen */
userpo = userpo->unext) {
if ((userpo->typ_u == typ)
&& (userpo->cblk_u == (l2ltyp *) link)) {
if (userpo->status == 2) /* User hat Connect gefordert? */
disusr(userpo->cblk_p, userpo->typ_p); /* Partner abwerfen */
kilusr(); /* und User selbst abwerfen */
return; /* fertig */
}
if (userpo->status == 2) { /* User hat Connect gefordert */
if ((userpo->typ_p == typ) /* und Antwort kam vom Partner */
&& (userpo->cblk_p == (l2ltyp *) link)) {
msgfrm('D', link, typ, ((opcod == 3)? dmmsg : "Failure with "));
userpo->status = 1; /* neuer Status ist "warten auf Befehl" */
return;
} }
}
}
}
/*---------------------------------------------------------------------------*/
VOID disusr(link, typ) /* User abwerfen */
ctyp *link; /* Kontrollblock */
unsigned typ; /* User Typ */
{
l2ltyp *cblk2; /* Kopien der Kontrollblockpointer */
cirtyp *cblk4;
hustyp *cblk0;
switch(typ)
{
case 4: /* Circuit? */
cblk4 = cirpoi;
cirpoi = (cirtyp *) link;
discir();
cirpoi = cblk4;
break;
case 2: /* Level2? */
cblk2 = lnkpoi;
lnkpoi = (l2ltyp *) link;
dsclnk();
lnkpoi = cblk2;
break;
default: /* Host */
cblk0 = hstusr;
hstusr = (hustyp *) link;
hstout();
hstusr = cblk0;
}
}
/*---------------------------------------------------------------------------*/
BOOLEAN fmlink(conflg, bufpoi) /* Frame an User weiterreichen */
mhtyp *bufpoi; /* Info */
BOOLEAN conflg; /* Congestion Flag */
{
unsigned cnt; /* Scratch Zaehler */
for (cnt = 0, ptcrdp = ptcrdl; /* Patchcordliste absuchen */
cnt < NUMPAT; /* ob User connected ist zu Partner */
++cnt, ++ptcrdp)
{
if ((bufpoi->usrtyp == ptcrdp->lusert) /* Usertyp */
&& (bufpoi->l2lnk == ptcrdp->luserl)) /* und Kontrollblock gleich? */
{
cnt ^= 1; /* auf andere Seite der Verbindung */
ptcrdp = &ptcrdl[cnt];
bufpoi->l2lnk = ptcrdp->luserl; /* Kontrollblock des Pratners eintragen*/
switch (ptcrdp->lusert)
{
case 4: /* User ist Circuit? */
return(itocir(conflg, bufpoi));
case 2: /* User ist Level2? */
return(itolnk(conflg, bufpoi));
default:
return(hstrec(conflg, bufpoi)); /* User ist Host */
}
}
}
relink(unlink(bufpoi), userhd.lprev); /* User ist im CCP */
return(TRUE);
}
/*---------------------------------------------------------------------------*/
VOID seteom(bufpoi) /* Ende Kennung an Frame anhaengen */
mhtyp *bufpoi;
{
mhtyp *mbhd;
putchr('\015', bufpoi); /* Zeilenende */
rwndmb(bufpoi); /* alle Pointer auf Null */
inithd(&mbhd);
relink(bufpoi, &mbhd);
switch (bufpoi->usrtyp)
{
case 4: /* User ist Circuit */
itocir(1, bufpoi);
break;
case 2: /* User ist Level2 */
itolnk(1, bufpoi);
break;
default: /* User ist Host */
hstrec(1, bufpoi);
}
}
/*---------------------------------------------------------------------------*/
VOID beacon() /* Bakenservice */
{
unsigned kanal; /* Kanal fuer Sendung */
mhtyp *bufpoi; /* Buffer fuer Frame */
if ((beacen != 0) && (nmbfre > 128)) { /* Bake frei und Platz? */
if (++beatim >= 600) { /* alle 10 min */
beatim = 0;
(bufpoi = (mhtyp *) allocb())->pid = 0xf0; /* Buffer beschaffen */
putstr("TheNet 1.0", bufpoi); /* Meldung in Buffer */
if (alias[0] != ' ') { /* Ident definiert? */
putstr(" (", bufpoi);
putcal(alias, bufpoi); /* dann Ident auch in Buffer */
putchr(')', bufpoi);
}
putchr('\015', bufpoi); /* Frame schliessen */
for (kanal = 0; kanal < 2; ++kanal) /* auf beide Kanaele geben */
{
if ((beacen == 2) || (istraf[kanal] == 1))
{
rwndmb(bufpoi); /* alle Pointer auf Null */
sdui(beadil, beades, myid, kanal, bufpoi); /* als UI senden */
istraf[kanal] = 0; /* Bake fuer diesen Kanal erledigt */
}
}
dealmb(bufpoi); /* Buffer wieder freigeben */
}
}
}
/*--- Ende Level 7a ---------------------------------------------------------*/