home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
541.TNL3.C
< prev
next >
Wrap
Text File
|
1988-05-14
|
41KB
|
960 lines
/*****************************************************************************/
/* */
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNet */
/* ***** ***** Portable. Compatible. */
/* ***** ***** Public Domain */
/* ***** ***** NORD><LINK */
/* */
/* This software is public domain ONLY for non commercial use */
/* */
/* */
/*****************************************************************************/
/* Level 3, Routing */
/* Version 1.01 */
/* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig */
/* 14-MAY-88 */
# include "tndef.h" /* Definition von Konstanten */
# include "tntyp.h" /* Definition der Typen */
# include "tnl3v.c" /* Definition der eigenen Variablen */
# include "tnl3e.h" /* externe Deklarationen */
/*---------------------------------------------------------------------------*/
/* Strings fuer Level3 */
char brodes[] = /* Ziel (Rundsprueche) */
/* ASCII Call */
/* SSID links geschoben */
{'N','O','D','E','S',' ','\140'};
char brodil[] = {'\000'}; /* Digiliste (Rundsprueche) */
/* Call im Standardformat */
/* Listenende = 0 */
char nulide[] = /* leerer Ident */
{' ',' ',' ',' ',' ',' '};
/*---------------------------------------------------------------------------*/
VOID l3init() /* Level 3 initialisieren */
{
nbrtyp *nbrpoi; /* Pointer auf Nachbarn */
numdes = /* Ziel Liste ist leer */
brotim = 0; /* Uhr fuer Rundsprueche ruecksetzen */
inithd(&l3rxfl); /* Liste empfangene Frames loeschen */
inithd(&l3txl); /* Liste zu sendende Frames loeschen */
if (!iswarm()) /* nur im Kaltstart */
{
inithd(&destil); /* Liste Ziele loeschen */
inithd(&neigbl); /* Liste Nachbarn loeschen */
maxdes = DEFDES; /* Ziele maximal */
broint = DEFBRI; /* Rundspruch Intervall */
obcini = DEFOBC; /* Abwesenheitszaehler */
obcbro = DEFOBB; /* maximale Abwesenheit fuer Rundspruch */
worqua = DEFWQU; /* Qualitaet fuer Rundspruch minimal */
timliv = DEFTLI; /* Paketlebensdauer */
ch0qua = DEFCH0; /* Kanal 0 Qualitaet */
ch1qua = DEFCH1; /* Kanal 1 Qualitaet */
}
else /* Warmstart */
{
for (despoi = (nodtyp *) destil.lnext; /* Zielliste bearbeiten */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext)
{
if (despoi->nodcal[0] != 0) /* Eintrag belegt? */
{
numdes += 1; /* ein Ziel mehr */
despoi->actrou = 0; /* kein aktiver Weg */
inithd(&despoi->nodinf); /* keine Info fuer dieses Ziel */
}
else /* leerer Eintrag */
{
unlink((despoi = (nodtyp *)despoi->nodlnk.lprev)->nodlnk.lnext);
}
}
for (nbrpoi = (nbrtyp *) neigbl.lnext; /* Nachbarn Liste bearbeiten */
nbrpoi != (nbrtyp *) &neigbl.lnext;
nbrpoi = (nbrtyp *) nbrpoi->nbrlnk.lnext)
{
nbrpoi->nbrl2l = 0; /* Querverweis in L2Link loeschen */
}
}
}
/*---------------------------------------------------------------------------*/
VOID l3serv() /* Level 3 Service */
{
char orgnod[7]; /* Call des Quellknotens */
char desnod[7]; /* Call des Zielknotens */
char beaide[6]; /* Ident des Rundspruch sendenden Knotens */
char nbrcal[7]; /* Call des Nachbarn */
char *rxnxt; /* erstes Zeichen im Frame */
char *nxtsav; /* Zwischenspeicher fuer erstes Zeichen */
BOOLEAN destin; /* aktuelles Ziel */
unsigned cnt; /* Scratch Zaehler */
unsigned chaqua; /* Qualitaet des aktuellen Kanals */
unsigned rxgetc; /* Getcount des Frames */
unsigned getsav; /* Zwischenspeicher fuer Getcount */
mhtyp *mbhd; /* Kopf des aktuellen Frames */
/*=== empfangene Frames verarbeiten ===*/
while ((mbhd = (mhtyp *) l3rxfl.lnext) != (mhtyp *) &l3rxfl) /* Liste leer?*/
{
unlink(mbhd); /* Frame aus Kette loesen */
if ((mbhd->pid & 0xff) == 0xcf) /* PID stimmt? */
{
rxnxt = mbhd->nxtchr; /* erstes Zeichen des Frames und */
rxgetc = mbhd->getcnt; /* Getcount merken */
if (mbhd->l2lnk != 0) /* Info Frame? */
/*------------------------------*/
/*--- Info Frame ---*/
/*------------------------------*/
{
if ((getfid(orgnod, mbhd) == 1) /* Call des Quellknotens holen */
&&(getfid(desnod, mbhd) == 1) /* Call des Zielknotens holen */
&&(mbhd->getcnt < mbhd->putcnt)) /* Info im Frame? */
{
getchr(mbhd); /* Restlebensdauer ueberlesen */
nxtsav = mbhd->nxtchr; /* Position im Frame merken */
getsav = mbhd->getcnt;
takfhd(mbhd); /* Header zerlegen */
mbhd->nxtchr = nxtsav; /* wieder auf alten Stand */
mbhd->getcnt = getsav;
if ((cmpid(myid, orgnod) == 0) /* kein eigenes Frames */
&&(isgood() == TRUE) /* und gute Qualitaet */
&&(
((destin = iscall(orgnod)) == FALSE)
||(istweg(&txfhdr[14], &rxfhdr[7], rxfprt) == ERROR)
))
{
chgnod('+', obcini, 0, rxfprt, &txfhdr[14], &rxfhdr[7],
(destin == FALSE)? &nulide[0] : &despoi->nodide[0],
orgnod); /* Zielliste auf neuen Stand bringen */
}
if (cmpid(myid, desnod) == 1) /* Frame fuer mich? */
{
relink(mbhd, l4rxfl.lprev); /* dann an Level 4 geben */
continue; /* naechstes Frame */
}
if (iscall(desnod) == 1) /* Ziel bekannt? */
{
if (--*(mbhd->nxtchr -1) != 0) /* noch Restlebensdauer? */
{
mbhd->nxtchr = rxnxt; /* auf Transportheader */
mbhd->getcnt = rxgetc;
if ((despoi->actrou != 0) /* aktiver Weg zum Ziel? */
&&(mbhd->l2lnk ==
despoi->weg[despoi->wegnr].nachba->nbrl2l))
{
despoi->actrou &=0xfff8;
despoi->actrou |= 0x02;
}
if ((cmpid(myid, orgnod) == 0)
|| ((despoi->actrou & 0x07) == 2))
{
todest(mbhd); /* Info absetzen */
continue;
} /* Info kann abgesetzt werden */
} /* noch Restlebensdauer */
} /* Ziel ist bekannt */
} /* Info ist im Frame */
} /* es ist ein I-Frame */
/*--------------------------------------*/
else /* UI Frame */
{
if (worqua != 0) /* darf Auswertung erfolgen? */
{
takfhd(mbhd); /* Header zerlegen */
mbhd->nxtchr = rxnxt; /* zurueck auf Anfang */
mbhd->getcnt = rxgetc;
if (isgood() == TRUE)
{
if ((mbhd->getcnt < mbhd->putcnt) /* Info im Frame? */
&&((getchr(mbhd) & 0xff) == 0xff) /* stimmt Signatur? */
&&(ge6chr(beaide, mbhd) == 1) /* Ident des Knotens */
&&(chgnod('+', obcini, qualty, rxfprt, &txfhdr[14],
&rxfhdr[7], &beaide[0], &rxfhdr[7]) == 1))
{
while ((getfid(desnod, mbhd) == 1) /* Rest des Frames */
&& (ge6chr(beaide, mbhd) ==1)
&& (getfid(nbrcal, mbhd) == 1)
&& (mbhd->getcnt < mbhd->putcnt))
{
chaqua = getchr(mbhd) & 0xff;
if (cmpid(myid, desnod) == 0) /* selbst Ziel? */
{
if ((chaqua = (((chaqua * qualty) +128) / 256))
>= worqua)
{
if (cmpid(myid, nbrcal) == 1) chaqua = 0;
if (chgnod('+', obcini, chaqua, rxfprt,
&txfhdr[14], &rxfhdr[7],
((chaqua == 0) && (iscall(desnod) == 1))?
&despoi->nodide[0] : &beaide[0],
desnod) == 0) break;
} /* Qualitaet gut genug fuer Update */
} /* nicht selbst das Ziel */
} /* bis Framenende */
if (nbrpoi != NULL)
{ /* Nachbar definiert */
for (despoi = (nodtyp *) destil.lnext; /* Ziel? */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext)
{
if (despoi->actrou != 0)
{ /* aktiver Weg zum Ziel? */
for (cnt = 0; /* alle Wege des Zieles */
despoi->wege > cnt;
++cnt)
{
if (despoi->weg[cnt].nachba == nbrpoi)
{ /* fuehrt der Weg ueber diesen Nachb */
if (despoi->wegnr > cnt)
{ /* gibt es einen besseren Weg? */
despoi->wegnr = cnt;
makrou(); /* diesen Weg versuchen*/
} /* es gibt einen besseren Weg*/
break;
} /* Weg fuehrt ueber diesen Nachbarn */
} /* dieser Weg bearbeitet */
} /* aktiver Weg existiert */
} /* dieses Ziel bearbeitet */
} /* Weg geht ueber einen Nachbarn */
} /* Signatur ist gut */
} /* Qualitaet des Kanals stimmt */
} /* Auswertung zulaessig */
} /* ist UI Frame */
} /* PID stimmt */
dealmb(mbhd); /* Frame ist bearbeitet, wegwerfen */
} /* Frames in der Kette */
/*=== zu sendende Frames verarbeiten ===*/
while ((mbhd = (mhtyp *) l3txl.lnext) != (mhtyp *) &l3txl.lnext) { /* leer?*/
unlink(mbhd); /* Frame aushaengen */
despoi = (nodtyp *) mbhd->l2lnk; /* Pointer auf Nachbarn */
if ((despoi->nodcal[0] != 0) /* Ziel definiert */
&& (nmbfre > 64)) { /* und Platz im Speicher */
rwndmb(mbhd); /* alle Pointer auf Ausgangsstellung */
getchr(mbhd); /* alles initialisieren */
--mbhd->nxtchr;
rxgetc = mbhd->putcnt; /* Framelaenge merken */
mbhd->putcnt = 1; /* auf Anfang */
putfid(myid, mbhd); /* Absender ins Frame */
putfid(&despoi->nodcal[0], mbhd); /* Ziel ins Frame */
*(mbhd->nxtchr -1) |= 1; /* Ende der Adresse setzen */
putchr(timliv, mbhd); /* Lebensdauer setzen */
mbhd->putcnt = rxgetc; /* Putcount zurueck */
rwndmb(mbhd); /* Pointer wieder aufziehen */
todest(mbhd); /* weg damit */
}
else dealmb(mbhd); /* geht nicht, Frame vernichten */
}
/*=== sonstige Funktionen ===*/
for (despoi = (nodtyp *) destil.lnext; /* Zielliste bearbeiten */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext) {
switch (despoi->actrou & 0x07) { /* ueber Wegstatus verzweigen */
/*------------------------------*/
case 2: /* Fehler aufgetreten, neuen Weg nehmen */
if (++despoi->wegnr >= despoi->wege) {
if ((despoi->actrou & 0x80) == 0)
despoi->wegnr = 0;
else {
destot(); /* Ziel nicht erreichbar, Frames wegwerfen */
break;
} }
makrou(); /* Weg aufbauen */
break;
/*------------------------------*/
case 3: /* Info Transfer laeuft */
while ((mbhd = (mhtyp *) despoi->nodinf.lnext)
!= (mhtyp *) &despoi->nodinf)
{
unlink(mbhd); /* Frame aus Kette holen */
mbhd->pid = 0xcf; /* PID setzen */
relink(mbhd,
(lnkpoi = despoi->weg[despoi->wegnr].nachba->nbrl2l)
->sendil.lprev); /* Frame in L2 umhaengen */
++lnkpoi->tosend; /* ein Frame mehr senden */
lnkpoi->noatou = ininat; /* Timeout setzen */
}
break;
/*------------------------------*/
case 4: /* */
makrou(); /* Weg aufbauen */
break;
/*------------------------------*/
default: /* leer oder connect laeuft */
break;
} } }
/*---------------------------------------------------------------------------*/
VOID l2tol3(status) /* Level 2 meldet neuen Status */
unsigned status; /* 0=nicht verwendet, 1=connected */
/* 2=disconnected, 3=busy, 4=Failure */
{
unsigned wegsts; /* Status des aktuellen Weges */
nbrtyp *nbrpoi; /* Pointer auf Nachbarn */
if (status < 5) /* nicht alles verwenden */
{
for (despoi = (nodtyp *) destil.lnext; /* gemeldeten Link suchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext)
{
if (((wegsts = despoi->actrou & 0x07) != 0) /* aktiver Weg? */
&& ((despoi->weg[despoi->wegnr].nachba)->nbrl2l == lnkpoi))
{
if (status == 1) /* Connect gemeldet */
{
if (wegsts == 1) /* und war auch gefordert */
despoi->actrou = 3; /* neuer Status des Zieles: connected*/
}
else
{
if (wegsts != 4)
{
despoi->actrou &= 0xfff8; /* Busy: */
despoi->actrou |= 0x02; /* neuer Status: anderen Weg */
}
}
}
}
if (status != 1) /* bei Busy / Failure */
{
for (nbrpoi = (nbrtyp *) neigbl.lnext; /* Nachbar Liste absuchen */
nbrpoi != (nbrtyp *) &neigbl.lnext;
nbrpoi = (nbrtyp *) nbrpoi->nbrlnk.lnext)
{
if (nbrpoi->nbrl2l == lnkpoi)
nbrpoi->nbrl2l = 0; /* Querverweis loeschen */
}
}
}
}
/*---------------------------------------------------------------------------*/
VOID brosrv() /* Rundspruchservice */
/* jede Sekunde aufgerufen */
{
unsigned cnt; /* Zaehler */
mhtyp *mbhd; /* Buffer fuer Meldung */
wegtyp *route; /* aktueller Weg */
if (broint != 0) { /* Rundspruch erlaubt? */
if (++brotim >= broint) { /* Zeit zum Senden gekommen? */
brotim = 0; /* Uhr ruecksetzen */
mbhd = brobuf(); /* Buffer besorgen */
for (despoi = (nodtyp *) destil.lnext; /* Zielliste absuchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext) {
if (despoi->nodcal[0] != 0) { /* Eintrag belegt? */
if (obcini != 0) { /* wenn Abwesenheitszaehler gefuehrt wird */
for (cnt = 0; /* alle Wege testen */
cnt < despoi->wege;
++cnt) {
if (((route = &despoi->weg[cnt])->obscnt != 0) /* gueltig? */
&&(--(route->obscnt) == 0)) { /* gerade auf 0 angekommen? */
delrou(cnt); /* dann loeschen */
--cnt; /* ein Weg weniger */
} }
if (despoi->nodcal[0] == 0) /* gibt es den Weg noch? */
continue;
}
if (((route = &despoi->weg[0])->qualit != 0) /* Qualitaet */
&&((route->obscnt == 0) /* muss sein, Eintrag permanent oder */
|| ((route->obscnt & 0xff) >= obcbro))){ /* gut genug */
if (mbhd == 0) /* ggfs neuen Buffer besorgen */
mbhd = brobuf();
putfid(&despoi->nodcal[0], mbhd); /* Call des Zieles */
pu6chr(&despoi->nodide[0], mbhd); /* Ident des Zieles */
putfid(&route->nachba->nbrcal[0], mbhd); /* Nachbar des Zieles */
putchr(route->qualit, mbhd); /* Qualitaet zum Ziel */
if ((mbhd->putcnt + 21) > 256) { /* droht Ueberlauf? */
sdbufr(mbhd); /* dann Buffer senden */
mbhd = 0; /* Buffer ist weg */
}
}
} }
if (mbhd != 0) /* noch Reste im Buffer? */
sdbufr(mbhd); /* dann senden */
} } }
/*---------------------------------------------------------------------------*/
mhtyp *brobuf() /* Buffer fuer Rundspruch besorgen */
{
mhtyp *mbhd; /* Buffer fuer Meldung */
putchr(0xff, (mbhd = allocb())); /* Buffer besorgen, Signatur rein */
pu6chr(alias, mbhd); /* Ident in Buffer */
return(mbhd); /* Buffer als Rueckgabe */
}
/*---------------------------------------------------------------------------*/
VOID sdbufr(mbhd) /* Buffer als Rundspruch senden */
mhtyp *mbhd;
{
unsigned kanal; /* Kanal, auf dem gesendet wird */
mbhd->pid = 0xcf; /* PID = Level3 */
for (kanal = 0;
kanal < 2; /* auf beiden Kanaelen senden */
++kanal)
{
rwndmb(mbhd); /* Pointer aufziehen */
sdui(&brodil[0], &brodes[0], &myid[0], kanal, mbhd); /* Level2 sendet */
}
dealmb(mbhd); /* Buffer wieder freigeben */
}
/*---------------------------------------------------------------------------*/
BOOLEAN chgnod(mode, obci, quali, port, digis, nachb, iden, call)
/* Zieleintrag aendern */
unsigned mode; /* '+'=neuer Eintrag, '-'=Eintrag loeschen */
unsigned obci; /* Abwesenheitszaehler, Initialisierung */
unsigned quali; /* Qualitaet des Weges */
unsigned port; /* Port zum Ziel */
char *digis; /* Digipeaterliste */
char *nachb; /* Nachbar zum Ziel */
char *iden; /* Ident des Zieles */
char *call; /* Rufzeichen des Zieles */
/* Rueckgabe: */
/* TRUE: loeschen verlangt, kein Eintrag da */
/* aendern war erfolgreich */
/* FALSE: Liste voll */
{
char *id1poi; /* Pointer fuer Call-Ident Vergleich */
char *id2poi; /* Pointer fuer Call-Ident Vergleich */
unsigned rout; /* aktueller Weg */
unsigned cnt; /* Scratch Zaehler */
nodtyp *ziel1; /* Pointer auf Ziel */
nodtyp *zielpt; /* Pointer auf Ziel */
zielpt = NULL;
for (despoi = (nodtyp *) destil.lnext; /* Zielliste absuchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext)
{
if (despoi->nodcal[0] != 0) { /* Eintrag belegt? */
if (cmpid(&despoi->nodcal[0], call) == 1) break; /* und passt? */
}
else { /* freier Eintrag */
if (zielpt == NULL) zielpt = despoi; /* ersten freien Eintrag merken */
}
}
if ((nodtyp *) &destil.lnext == despoi) { /* passender Eintrag? */
if (mode == '+') { /* hinzufuegen? */
if (zielpt == 0) { /* kein freier Platz bisher? */
if (numdes < maxdes) { /* Liste hat noch Platz? */
(zielpt = (nodtyp *) allocb())->actrou = 0; /* initialisieren */
zielpt->wege = 0; /* kein Weg bekannt */
inithd(&zielpt->nodinf); /* keine Info in der Schlange */
relink(zielpt, destil.lprev); /* in Zielliste haengen */
++numdes; /* Liste ist laenger geworden */
}
else return (FALSE); /* Liste ist voll */
}
despoi = zielpt; /* freien (neuen) Platz nehmen */
cpyid(&despoi->nodcal[0], call); /* Call eintragen, Rest spaeter */
}
else return (TRUE); /* loeschen verlangt, Eintrag existiert nicht*/
}
/*------------------------------ passender Eintrag existiert (CALL) */
cpy6ch(&despoi->nodide[0], iden); /* Ident umkopieren */
unlink(despoi); /* Eintrag aus Kette loesen */
for (ziel1 = (nodtyp *) destil.lnext; /* Zielliste absuchen */
ziel1 != (nodtyp *) &destil.lnext;
ziel1 = (nodtyp *) ziel1->nodlnk.lnext)
{
id1poi = (char *) &ziel1->nodide[0];
id2poi = (char *) &despoi->nodide[0];
for (cnt = 0; cnt < 13; ++cnt)
{ /* Call und Ident vergleichen */
if (*id1poi == *id2poi)
{
++id1poi;
++id2poi;
}
else break;
} /* Call und Ident verglichen */
if (*id1poi > *id2poi) break;
} /* Zielliste abgesucht */
relink(despoi, ziel1->nodlnk.lprev);
if ((rout = istweg(digis, nachb, port)) == -1)
{
if (mode == '+')
newnod(obci, quali, port, digis, nachb);
}
else
{
if (mode == '-')
delrou(rout);
else
{
if (despoi->weg[rout].obscnt != 0)
addweg(obci, quali, rout);
}
}
return (TRUE);
}
/*---------------------------------------------------------------------------*/
VOID newnod(obci, quali, port, digis, nachb)
/* Zieleintrag in Liste aufnehmen */
unsigned obci; /* Anwesenheitszaehler */
unsigned quali; /* Qualitaet des Weges */
unsigned port; /* Port zum Ziel */
char *digis; /* Digipeaterliste */
char *nachb; /* Nachbar zum Ziel */
{
unsigned neuweg; /* Position des neuen Weges in Liste */
wegtyp *wegptr; /* Pointer auf Weg */
nbrtyp *nbrptr; /* Pointer auf Nachbarn */
rouhin(); /* alle Wege in Arbeitsspeicher */
(wegptr = &routmp[despoi->wege]) /* auf neuen Weg. wege zaehlt 1-2-3! */
->qualit = quali; /* Qualitaet des neuen Weges */
wegptr->obscnt = obci; /* Anwesenheitszaehler */
wegptr->nachba = (nbrtyp *) -1; /* Zeiger auf Nachbarn loeschen */
neuweg = srtrou(despoi->wege++); /* Wege sortieren */
rouher(); /* Wege zurueck in Liste */
if (neuweg < 3) /* steht der neue Weg in der Liste? */
{
++(nbrptr = updnbr(digis, nachb, port)) /* Nachbarnliste neuer Stand */
->nbrrou; /* ein Weg mehr ueber diesen Nachbarn */
despoi->weg[neuweg].nachba = nbrptr; /* Nachbarn in Zielliste eintragen*/
}
if (despoi->wege > 3) { /* nun mehr als 3 Wege vorhanden? */
--despoi->wege; /* darf nicht sein */
if (neuweg < 3) /* wurde neuer Weg in die Liste aufgenommen? */
decrcn(&routmp[3]); /* dann muss ein anderer entfernt werden */
}
if ((despoi->actrou != 0) /* besteht ein aktiver Weg? */
&& (despoi->wegnr > 2)) { /* und ist es der nun schlechteste? */
despoi->wegnr = 0; /* dann den besten nehmen */
makrou(); /* und Link neu aufbauen */
}
}
/*---------------------------------------------------------------------------*/
VOID addweg(obci, quali, nummer)
/* Weg in Liste aufnehmen */
unsigned obci; /* Anwesenheitszaehler */
unsigned quali; /* Qualitaet des Weges */
unsigned nummer; /* Nummer des Eintrages */
{
wegtyp *wegptr; /* Pointer auf Weg */
(wegptr = &(despoi->weg[nummer]))->qualit = quali; /* Qualitaet */
wegptr->obscnt = obci; /* und Anwesenheitszaehler setzen */
rouhin(); /* auslagern in Arbeitsspeicher */
srtrou(-1); /* sortieren */
rouher(); /* zurueck in Liste */
}
/*---------------------------------------------------------------------------*/
VOID delrou(nummer) /* Weg aus Liste streichen */
unsigned nummer; /* Nummer des Eintrages */
{
wegtyp *wegptr; /* Pointer auf Weg */
decrcn(wegptr = &(despoi->weg[nummer])); /* Weg in Nachbarnliste loeschen */
if (despoi->wege > 1) { /* nun noch Wege fuer dieses Ziel vorhanden? */
wegptr->nachba = 0; /* ohne Nachbarn hat der Weg keine Qualitaet */
rouhin(); /* Wege in Arbeitsspeicher */
srtrou(-1); /* sortieren */
rouher(); /* wieder in Liste zurueck */
}
else { /* den letzten Weg entfernt */
destot(); /* Ziel existiert nicht mehr */
despoi->nodcal[0] = 0; /* Eintrag ist wieder frei */
}
if ((despoi->wegnr >= --despoi->wege) /* aktiven Weg geloescht? */
&& (despoi->actrou != 0)) {
despoi->wegnr = 0; /* neuen Weg suchen */
makrou();
}
}
/*---------------------------------------------------------------------------*/
VOID decrcn(weg) /* Weg aus Nachbarn-Liste streichen */
wegtyp *weg; /* zu loeschender Weg */
{
nbrtyp *nbrptr; /* Pointer auf Nachbarn */
if ((--(nbrptr = weg->nachba)->nbrrou == 0) /* den letzten Weg geloescht? */
&& (nbrptr->locked == 0)) /* und Eintrag nicht gesperrt */
{
dealoc(unlink(nbrptr)); /* dann Nachbarn komplett loeschen */
}
}
/*---------------------------------------------------------------------------*/
VOID rouhin() /* Wege in Arbeitsspeicher auslagern */
{
move4b(3, routmp, &despoi->weg[0]); /* 12 (=3*4) Bytes kopieren */
}
/*---------------------------------------------------------------------------*/
VOID rouher() /* Wege aus Arbeitsspeicher holen */
{
move4b(3, &despoi->weg[0], routmp); /* 12 (=3*4) Bytes kopieren */
}
/*---------------------------------------------------------------------------*/
unsigned srtrou(wegneu) /* Wegeliste in routmp sortieren */
int wegneu; /* Position des neuen Weges in routmp */
/* Rueckgabe: Position des neuen Weges */
{
unsigned wegcnt; /* Zahl der Wege in routmp */
unsigned waktiv; /* aktiver Weg dieses Zieles */
unsigned akt; /* aktuell untersuchter Weg (Nummer) */
unsigned nxt; /* naechster zu untersuchender Weg (Nummer) */
wegtyp *wakt; /* aktueller Weg */
wegtyp *wnxt; /* naechster Weg */
wegcnt = despoi->wege; /* Zahl der Wege holen */
waktiv = despoi->wegnr; /* aktiven Weg merken */
for (wakt = &routmp[akt = 0]; /* Bubble Sort ueber routmp */
(wegcnt-1) > akt;
++akt, ++wakt) {
for (wnxt = &routmp[nxt = akt + 1];
nxt < wegcnt;
++nxt, ++wnxt) {
if ((! wakt->nachba) /* der Weg muss einen Nachbarn haben */
|| ((wakt->qualit & 0xff) < (wnxt->qualit & 0xff))) { /* und besser */
move4b(1, &rouwrk, wakt); /* als der vorherige sein */
move4b(1, wakt, wnxt); /* dann die Wege tauschen */
move4b(1, wnxt, &rouwrk);
if (wegneu == akt) wegneu = nxt; /* neuen Weg merken */
else if (wegneu == nxt) wegneu = akt;
if (waktiv == akt) waktiv = nxt; /* aktiven Weg merken */
else if (waktiv == nxt) waktiv = akt;
} } }
despoi->wegnr = waktiv; /* aktiven Weg in Liste korrigieren */
return(wegneu); /* mit Position des neuen Weges zurueck */
}
/*---------------------------------------------------------------------------*/
VOID move4b(zahl, nach, von) /* 4 * Zahl Bytes kopieren */
unsigned zahl;
char *nach; /* Ziel */
char *von; /* Quelle */
{
unsigned cnt; /* Scratch Zaehler */
for (cnt = 0; (zahl * 4) > cnt; ++cnt) {
*nach++ = *von++;
}
}
/*---------------------------------------------------------------------------*/
VOID todest(mbhd) /* Info in Zielliste haengen */
mhtyp *mbhd; /* Info Header */
{
relink(mbhd, despoi->nodinf.lprev); /* Info umhaengen */
if (despoi->actrou == 0) { /* kein aktiver Weg da? */
despoi->wegnr = 0; /* mit dem besten Weg beginnend */
makrou(); /* Link aufbauen */
}
}
/*---------------------------------------------------------------------------*/
VOID makrou() /* Weg zu einem Ziel aufbauen */
{
unsigned cnt; /* Scratch Zaehler */
l2ltyp *l2poi; /* Pointer auf Level2 Kontrollblock */
nbrtyp *nbrpoi; /* Pointer auf Nachbarn */
if (despoi->nodinf.lnext != (lhtyp *) &despoi->nodinf.lnext) { /* Info? */
despoi->actrou &= 0xfff8; /* Status: kein aktiver Weg */
if ((lnkpoi = /* schon - noch Eintrag fuer L2 vorhanden? */
(nbrpoi = despoi->weg[despoi->wegnr].nachba)->nbrl2l)
== 0) {
for (l2poi = 0, cnt = 0, lnkpoi = &lnktbl[0];
cnt < MAXL2L; /* nein, freien Eintrag suchen */
++cnt, ++lnkpoi) {
if (lnkpoi->state != 0) { /* Eintrag belegt */
if ((cmpid(nbrpoi->nbrcal, lnkpoi->dstid) == 1)
&&(cmpid(myid, lnkpoi->srcid) == 1)
&&(lnkpoi->liport == nbrpoi->nbrpor))
break; /* passt er zufaellig? Dann benutzen */
}
else { /* Eintrag ist frei */
if ((l2poi == 0) && (lnkpoi->srcid[0] == 0))
l2poi = lnkpoi; /* ersten freien Eintrag merken */
}
}
if (cnt == MAXL2L) { /* kein passender Eintrag gefunden? */
if (l2poi != 0) { /* freier Eintrag vorhanden? */
lnkpoi = l2poi; /* dann nehmen wir ihn */
cpyid(lnkpoi->srcid, myid); /* Quellcall eintragen */
cpyid(lnkpoi->dstid, nbrpoi->nbrcal); /* Zielcall eintragen */
cpyidl(lnkpoi->viaid, nbrpoi->nbrdil); /* Digiliste eintragen */
lnkpoi->liport = nbrpoi->nbrpor; /* Port eintragen */
newlnk(); /* im Level 2 eine Verbindung bestellen */
}
else { /* L2 Tabelle ist voll */
despoi->actrou |= 0x02; /* Fehler markieren */
return; /* Abbruch */
}
}
nbrpoi->nbrl2l = lnkpoi; /* in Nachbarnliste Querverweis eintragen */
}
if (lnkpoi->state == 1) /* Status = Connect laeuft? */
despoi->actrou |= 0x01; /* dann auch in Nachbarnliste so markieren */
else
{
if (lnkpoi->state == 3) /* Status: Disc-Requested? */
despoi->actrou |= 0x04;
else
despoi->actrou = 3; /* sonst Status = connected */
}
if ((despoi->actrou == 1) /* Connect laeuft und */
&& (despoi->wegnr == 0)) /* noch kein Weg probiert */
despoi->actrou |= 0x80; /* markieren */
}
else despoi->actrou = 0; /* keine aktive Route */
}
/*---------------------------------------------------------------------------*/
VOID destot() /* Ziel ist nicht mehr erreichbar */
{
dealml(&despoi->nodinf); /* Info fuer das Ziel wegwerfen */
despoi->actrou = 0; /* kein aktiver Weg */
}
/*---------------------------------------------------------------------------*/
BOOLEAN isgood() /* Entscheidung ueber Qualitaet des Weges */
{ /* TRUE: Qualitaet ist gut fuer Speicherung */
return ( /* FALSE: schlechter Weg */
(qualty = (
(nbrpoi = getnei(&txfhdr[14], &rxfhdr[7], rxfprt)) /* welcher Nachbar? */
== NULL)? /* existiert er ueberhaupt? */
((rxfprt == 0)? ch0qua : ch1qua) /* Portqualitaet, wenn nicht da */
:
(nbrpoi->pathqu & 0xff)) /* sonst aus Nachbarliste */
>= worqua); /* vergleichen mit Minimalqualitaet */
}
/*---------------------------------------------------------------------------*/
nbrtyp *updnbr(digis, nachb, port) /* Nachbar auf neuen Stand bringen */
char *digis; /* Digiliste zum Nachbarn */
char *nachb; /* Call des Nachbarn */
unsigned port; /* Port zum Nachbarn */
{
nbrtyp *nbrbuf; /* Buffer fuer Eintrag */
if ((nbrbuf = getnei(digis, nachb, port)) == NULL)
{ /* Eintrag existiert noch nicht */
nbrbuf = (nbrtyp *) allocb(); /* Buffer beschaffen */
cpyid(&nbrbuf->nbrcal[0], nachb); /* Call eintragen */
digis[14] = 0; /* nur 2 Digis */
cpyidl(&nbrbuf->nbrdil[0], digis); /* Digiliste eintragen */
nbrbuf->pathqu =
((nbrbuf->nbrpor = port) == 0)?
ch0qua : ch1qua;
nbrbuf->locked =
nbrbuf->nbrrou = 0;
nbrbuf->nbrl2l = NULL;
relink(nbrbuf, neigbl.lprev);
}
return(nbrbuf); /* mit Pointer auf Eintrag zurueck */
}
/*---------------------------------------------------------------------------*/
nbrtyp *getnei(digis, name, port) /* Nachbarn suchen */
char *digis;
char *name;
unsigned port;
{
nbrtyp *nachb;
for (nachb = (nbrtyp *) neigbl.lnext;
nachb != (nbrtyp *) &neigbl.lnext;
nachb = (nbrtyp *) nachb->nbrlnk.lnext)
{
if (isneig(digis, name, port, nachb) == TRUE) return (nachb);
}
return(NULL);
}
/*---------------------------------------------------------------------------*/
nbrprt(call) /* Port fuer Ziel "call" suchen? */
char *call;
{
nbrtyp *nachb; /* aktueller Nachbar */
for (nachb = (nbrtyp *) neigbl.lnext; /* Nachbarnliste absuchen */
nachb != (nbrtyp *) &neigbl.lnext;
nachb = (nbrtyp *) nachb->nbrlnk.lnext)
{
if (cmpid(call, nachb->nbrcal) == TRUE)
{
return(nachb->nbrpor);
}
}
if (isidnt(call) == TRUE)
{
for (nachb = (nbrtyp *) neigbl.lnext;
nachb != (nbrtyp *) &neigbl.lnext;
nachb = (nbrtyp *) nachb->nbrlnk.lnext)
{
if (cmpid(&nachb->nbrcal[0], &despoi->nodcal[0]) == TRUE)
return(nachb->nbrpor);
}
}
return(0); /* HDLC als default */
}
/*---------------------------------------------------------------------------*/
BOOLEAN iscall(call) /* ist Call als Ziel eingetragen? */
char *call;
{
for (despoi = (nodtyp *) destil.lnext; /* Zielliste absuchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext) {
if (despoi->nodcal[0] != 0) { /* Eintrag definiert? */
if (cmpid(call, despoi->nodcal) == 1) /* dann testen */
return(TRUE);
} }
return(FALSE);
}
/*---------------------------------------------------------------------------*/
BOOLEAN isidnt(ident) /* ist Ident als Ziel eingetragen? */
char *ident;
{
for (despoi = (nodtyp *) destil.lnext; /* Zielliste absuchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext) {
if (despoi->nodcal[0] != 0) { /* Eintrag definiert? */
if (cmpcal(ident, despoi->nodide) == 1) /* dann testen */
return(TRUE);
} }
return(FALSE);
}
/*---------------------------------------------------------------------------*/
istweg(digis, call, port) /* Test, ob ein Weg existiert */
char *digis; /* Digiliste */
char *call; /* Call des Nachbarn */
char port; /* Port fuer den Weg */
{ /* Rueckgabe: Weg-Nummer */
unsigned cnt; /* Scratch Zaehler */
for (cnt = 0;
cnt < despoi->wege;
++cnt) /* alle Wege zum Ziel testen */
{
if (isneig(digis, call, port, despoi->weg[cnt].nachba) == TRUE)
return(cnt);
}
return(-1); /* Fehler, nicht gefunden */
}
/*---------------------------------------------------------------------------*/
BOOLEAN isrout(buffer) /* Test, ob buffer in Weglisten ist */
nbrtyp *buffer;
{
nbrtyp *nachb;
for (nachb = (nbrtyp *) neigbl.lnext; /* Nachbarnliste absuchen */
nachb != (nbrtyp *) &neigbl.lnext;
nachb = (nbrtyp *) nachb->nbrlnk.lnext)
{
if (nachb == buffer) return(TRUE);
}
for (despoi = (nodtyp *) destil.lnext; /* Zielliste absuchen */
despoi != (nodtyp *) &destil.lnext;
despoi = (nodtyp *) despoi->nodlnk.lnext)
{
if (despoi == (nodtyp *) buffer) return(TRUE);
}
return(FALSE); /* nicht gefunden */
}
/*---------------------------------------------------------------------------*/
BOOLEAN isneig(digis, call, port, nachb) /* Test, ob Daten in Nachbarliste */
char *digis; /* Digipeaterliste */
char *call; /* Call */
char port; /* Port */
nbrtyp *nachb; /* Pointer auf vermuteten Eintrag in Liste */
{
return((nachb->nbrpor == port)
&& (cmpid(nachb->nbrcal, call) == 1)
&& (cmpidl(nachb->nbrdil, digis) == 1));
}
/*---------------------------------------------------------------------------*/
BOOLEAN ge6chr(buffer, mbhd) /* 6 Zeichen aus mbhd nach Buffer */
char *buffer; /* Rueckgabe: TRUE=hat funktioniert */
mhtyp *mbhd;
{
unsigned cnt; /* Zaehler */
if ((mbhd->putcnt - mbhd->getcnt) >= 6) { /* genug Zeichen da? */
for (cnt = 0; cnt < 6; ++cnt) {
*buffer++ = getchr(mbhd); /* Zeichen holen, ablegen */
}
return(TRUE); /* Erfolg melden */
}
else return(FALSE); /* nicht genug Zeichen im mbhd */
}
/*---------------------------------------------------------------------------*/
VOID pu6chr(buffer, mbhd) /* 6 Zeichen aus Buffer in mbhd */
char *buffer;
mhtyp *mbhd;
{
unsigned cnt; /* Zaehler */
for (cnt = 0; cnt < 6; ++cnt) {
putchr(*buffer++, mbhd);
} }
/*---------------------------------------------------------------------------*/
VOID cpy6ch(dest, src)
char *src;
char *dest;
{
unsigned cnt;
for (cnt = 0; cnt < 6; ++cnt)
{
*dest++ = *src++;
}
}
/*- Ende Level 3 ------------------------------------------------------------*/