home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
544.TNL4.C
< prev
next >
Wrap
Text File
|
1988-05-14
|
28KB
|
659 lines
/*****************************************************************************/
/* */
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNet */
/* ***** ***** Portable. Compatible. */
/* ***** ***** Public Domain */
/* ***** ***** NORD><LINK */
/* */
/* This software is public domain ONLY for non commercial use */
/* */
/* */
/*****************************************************************************/
/* Level 4, Transport
/* Version 1.01 */
/* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig */
/* 01-MAY-88 */
# include "tndef.h" /* Definition von Konstanten */
# include "tntyp.h" /* Definition der Typen */
# include "tnl4v.c" /* Defintion der globalen Variablen */
# include "tnl4e.h" /* Externe Definitionen */
/*---------------------------------------------------------------------------*/
VOID initl4() /* Level 4 initialisieren */
{
unsigned cnt; /* Sratch Zaehler */
inithd(&l4rxfl); /* Liste fuer empfangene Frames */
for (cnt = 0, cirpoi = cirtab; /* gesamte Circuit Tabelle */
cnt < NUMCIR; /* bearbeiten */
++cnt, ++cirpoi)
{
cirpoi->state3 = /* Eintrag ist leer */
cirpoi->numrx = /* keine Frames empfangen */
cirpoi->numtx = 0; /* keine Frames zu senden */
cirpoi->fragme = NULL; /* kein Frame Fragment da */
inithd(&cirpoi->mbhdrx); /* Empfangskette ist leer */
inithd(&cirpoi->mbhdtx); /* Sendekette ist leer */
inithd(&cirpoi->mbhdos); /* Kette "ausser Reihenfolge" leer */
}
if (! iswarm()) /* im Kaltstart Standardwerte */
{
tratou = DEFTTO; /* Timeout */
tratri = DEFTTR; /* Versuche */
traack = DEFTAC; /* ACK Wartezeit */
trabsy = DEFTBS; /* Busy Wartezeit */
trawir = DEFTWI; /* Fenstergroesse */
}
}
/*---------------------------------------------------------------------------*/
VOID l4serv() /* Level 4 Service */
{
l4tx(); /* Frames senden */
l4rx(); /* Frames empfangen */
l4rest(); /* sonstige Funktionen */
}
/*---------------------------------------------------------------------------*/
VOID l4tx() /* Frames senden */
{
unsigned unack; /* unbestaetigte Frames */
unsigned cnt; /* Sratch Zaehler */
unsigned isweg; /* schon gesendete Frames */
mhtyp *nxtfra; /* naechstes Frame */
for (cnt = 0, cirpoi = cirtab;/* gesamte Circuittabelle */
cnt < NUMCIR;
++cnt, ++cirpoi) {
if ((cirpoi->state3 == 2) /* Eintrag ist connected */
&& (!(cirpoi->l4flag & 0x20)) /* und Partner nicht choked */
&& ((unack = (cirpoi->l4vs - cirpoi->l4rxvs) & 0xff) < cirpoi->numtx)
&& (unack < cirpoi->window)) { /* Fenstergroesse nicht erreicht */
for (isweg = 0, nxtfra = (mhtyp *) cirpoi->mbhdtx.lnext; /* neue Frames*/
isweg < unack; /* schon gesendete offene Frames uebergehen */
++isweg, nxtfra = (mhtyp *) nxtfra->link.lnext);
do {
nxtfra->l4trie = 0; /* Versuche := 0 */
sndfrm(cirpoi->l4vs++, nxtfra); /* naechstes Frame senden */
nxtfra = (mhtyp *) nxtfra->link.lnext; /* vorruecken */
}
while ((++unack < cirpoi->numtx) /* bis Ende der Kette */
&& (cirpoi->window > unack)); /* oder Fenstergroesse ueberschritten */
}
}
}
/*---------------------------------------------------------------------------*/
VOID l4rx() /* Frames empfangen */
{
char usrcal[7]; /* Call des Users */
char orgnod[7]; /* Call des absendenden Knotens */
unsigned fenste; /* Fenstergroesse */
unsigned cnt; /* Scratch Zaehler */
mhtyp *nxtfra; /* naechstes Frame */
mhtyp *antwor; /* Antwort auf Frame */
cirtyp *cirent; /* CIRTAB Eintrag des Users */
while ((nxtfra = (mhtyp *) l4rxfl.lnext) != (mhtyp *) &l4rxfl.lnext) {
unlink(nxtfra); /* Frame aus Kette loesen */
if ((nxtfra->putcnt - nxtfra->getcnt) >= 5) { /* lang genug? */
l4hdr0 = getchr(nxtfra); /* Header holen */
l4hdr1 = getchr(nxtfra);
l4hdr2 = getchr(nxtfra);
l4hdr3 = getchr(nxtfra);
if (((l4opco = getchr(nxtfra)) & 0x07) != 0x01) { /* CONREQ immer gut */
if ((l4hdr0 < NUMCIR) /* Index im Bereich? */
&& ((cirpoi = &cirtab[l4hdr0])->state3 != 0)
&& (cirpoi->ideige == l4hdr1)) {
l4pidx = cirpoi->idxpar;
l4pcid = cirpoi->idpart;
}
else { /* schlechter Header */
dealmb(nxtfra); /* Frame vernichten */
continue;
}
}
switch (l4opco & 0x07) { /* ueber Opcode verzweigen */
/*=============================*/
case 1: /* Connect Request */
if (((nxtfra->putcnt - nxtfra->getcnt) >= 15) /* Frame lang genug? */
&& ((fenste = getchr(nxtfra) & 0xff) != 0) /* Fenster muss angegeben sein*/
&& (getfid(usrcal, nxtfra) == 1) /* gueltiges Usercall */
&& (getfid(orgnod, nxtfra) == 1) /* gueltiger Absender */
&& (seades(orgnod) == 1)) { /* Absender bekannt */
l4pidx = l4hdr0; /* Index und */
l4pcid = l4hdr1; /* ID des Partners merken */
for (cirent = 0, cnt = 0, cirpoi = cirtab; /* Circuit Tabelle absuchen */
cnt < NUMCIR;
++cnt, ++cirpoi) {
if (cirpoi->state3 != 0) {
if ((cmpid(usrcal, cirpoi->upcall) == 1)
&& (cmpid(orgnod, cirpoi->downca) == 1)) {
if ((cirpoi->idxpar == l4hdr0)
&& (cirpoi->idpart == l4hdr1)) break;
}
}
else {
if (cirent == 0) cirent = cirpoi;
}
}
if (cnt == NUMCIR) { /* Ende der Tabelle erreicht? */
if ((cirent != 0) /* freien Platz gefunden? */
&& (fvalca(VCpar, usrcal) == 1)) { /* User Call gueltig? */
cirpoi = cirent; /* dann Eintrag nehmen */
cpyid(cirpoi->upcall, usrcal); /* Call eintragen */
cpyid(cirpoi->downca, orgnod);
cirpoi->idxpar = l4hdr0; /* Parameter des Partnerknotens */
cirpoi->idpart = l4hdr1;
cirpoi->ideige = random(); /* eigener ID */
cirpoi->l3node = despoi; /* Nachbar fuer den Eintrag */
l2tol7(1, cirpoi, 4); /* UA von Circuit nach zurueck */
cirpoi->tranoa = ininat; /* Timeout setzen */
}
else { /* kein Platz - ungueltiges Call */
l4ahd2 = /* Antwort aufbauen */
l4ahd3 = 0;
l4aopc = 0x82; /* Opcode = choked, Acknowledge */
(antwor = gennhd())->l2lnk = (l2ltyp *) despoi; /* Antwort aufbauen */
relink(antwor, l3txl.lprev); /* in Sendekette haengen */
break;
}
} /* Eintrag gibt es schon */
cirpoi->window = (fenste > trawir)? trawir : fenste;
clrcir(); /* Eintrag initialisieren */
l4ahd2 = (cirpoi - &cirtab[0]);
l4ahd3 = cirpoi->ideige; /* eigene Parameter setzen */
l4aopc = 0x02; /* Antwort wird ACK */
putchr(cirpoi->window, (antwor = gennhd()));
itol3(antwor); /* senden */
cirpoi->state3 = 2; /* Status = connected */
}
break;
/*=============================*/
case 2: /* Connect Acknowledge */
if (cirpoi->state3 == 1) { /* macht nur Sinn, wenn Connect verlangt */
if ((l4opco & 0x80) == 0) { /* Partner darf nicht choked sein */
if (nxtfra->getcnt < nxtfra->putcnt) { /* noch Info da? */
cirpoi->window = getchr(nxtfra); /* holen */
cirpoi->idpart = l4hdr3; /* Partner Parameter setzen */
cirpoi->idxpar = l4hdr2;
clrcir(); /* Eintrag initialisieren */
l2tol7(1, cirpoi, 4); /* Antwort ist UA vom Circuit */
cirpoi->tranoa = ininat; /* Timeout setzen */
cirpoi->state3 +=1; /* Status = connected */
}
}
else { /* Partner ist choked */
l4nsta(3); /* melden */
}
}
break;
/*=============================*/
case 3: /* Disconnect Request */
clr4rx(1); /* restliche Info senden */
l4nsta(2); /* nach oben melden */
l4ahd2 =
l4ahd3 = 0; /* Antwort aufbauen */
l4aopc = 0x04; /* Opcode = Disconnect ACK */
itol3(gennhd()); /* Frame senden */
break;
/*=============================*/
case 4: /* Disconnect Acknowledge */
if (cirpoi->state3 == 3) { /* wurde DISC gegeben? */
l4nsta(2); /* melden */
}
break;
/*=============================*/
case 5: /* Info Transfer */
if (cirpoi->state3 != 2) /* nur wenn connected */
break;
chksts(); /* Status Info auswerten */
if (((nxtfra->pid = (l4hdr2 - cirpoi->l4vr) & 0xff) < cirpoi->window)
&& ((cirpoi->l4flag & 0x40) == 0)) { /* passt das Frame ins Fenster? */
nxtfra->morflg = (l4opco & 0x20) != 0; /* fragmentiert? */
if (nxtfra->pid == 0) { /* passt Sequenz? */
takfrm(nxtfra); /* Frame uebernehmen */
for (cnt = 1, antwor = (mhtyp *) cirpoi->mbhdos.lnext; /* Frames, */
(mhtyp *) &(cirpoi->mbhdos) != antwor; /* die zu frueh kamen, absu- */
antwor = (mhtyp *) antwor->link.lnext) { /* chen, ob nun passt */
if ((antwor->pid -=cnt) == 0) { /* neuer Offset */
nxtfra = (mhtyp *) antwor->link.lprev; /* Frame passt bei Offset 0 */
takfrm(unlink(antwor)); /* Frame aus Kette nehmen und verwerten */
antwor = nxtfra;
++cnt; /* zulaessiger Offset eins weiter */
}
}
cirpoi->l4rs = 0; /* Antwort wird ACK */
cirpoi->acktim = traack; /* ACK Timer laden */
}
else { /* Sequenz passt nicht */
for (antwor = (mhtyp *) cirpoi->mbhdos.lnext;;)
{ /* in extra Kette haengen */
if ((mhtyp *) &(cirpoi->mbhdos) == antwor) { /* Ende der Kette? */
relink(nxtfra, cirpoi->mbhdos.lprev); /* dann einhaengen */
break;
}
if (antwor->pid == nxtfra->pid) { /* Frame schon mal angekommen? */
dealmb(nxtfra); /* dann wegwerfen */
break;
}
if (antwor->pid > nxtfra->pid) { /* an passender Stelle einhaengen */
relink(nxtfra, antwor->link.lprev);
break;
}
antwor = (mhtyp *) antwor->link.lnext; /* ein Frame weiter */
}
if (cirpoi->l4rs == 0) { /* Frame haengt in extra Kette */
cirpoi->l4rs = 1; /* wenn ACK gefordert war, nun NAK */
cirpoi->acktim = traack; /* ACK Wartezeit setzen */
}
}
continue; /* naechstes Frame */
}
else /* ungueltiges Frame oder selbst choked */
cirpoi->acktim = traack; /* Antwort hat Zeit */
break;
/*=============================*/
case 6: /* Info Acknowledge */
if (cirpoi->state3 == 2) /* nur sinnvoll, wenn connected */
chksts(); /* enthaltene Statusinfo auswerten */
break;
/*=============================*/
default: /* ungueltiger Opcode */
break; /* uebergehen */
/*=============================*/
} } /* Ende des Switch ueber Opcode */
dealmb(nxtfra); /* fertig bearbeitet, wegwerfen */
} }
/*---------------------------------------------------------------------------*/
VOID l4rest() /* diverse Level4 Funktionen */
{
unsigned cnt; /* Scratch Zaehler */
for (cnt = 0, cirpoi = cirtab; /* gesamte Tabelle bearbeiten */
cnt < NUMCIR;
++cnt, ++cirpoi) {
if (cirpoi->state3 == 2) { /* nur fuer connectete Eintrage */
if (((cirpoi->l4flag & 0x80) != 0) /* Abwurf gefordert */
&& (cirpoi->numtx == 0)) { /* und alles gesendet? */
endcir(); /* Eintrag loeschen */
}
else {
clr4rx(0); /* kein Abwurf gefordert: Info senden */
if ((cirpoi->l4flag & 0x40) == 0) { /* selbst choked? */
if ((nmbfre < 80) /* nein: kein Platz im Buffer? */
|| (cirpoi->numrx >= conctl)) { /* oder zu viel empfangen? */
cirpoi->l4flag |= 0x40; /* dann selbst choked setzen */
cirpoi->l4rs = 0; /* ACK als naechste Antwort */
sndack();
}
}
else {
if ((nmbfre > 112) /* selbst choked: wieder Platz im Buffer? */
&& (cirpoi->numrx < (conctl / 2))) { /* und Datenstau abgebaut? */
cirpoi->l4flag &= 0xffbf; /* dann choked ruecksetzen */
sndack(); /* melden */
} }
} }
} }
/*---------------------------------------------------------------------------*/
VOID trasrv() /* Timerservice fuer Level 4 */
{
unsigned actsts; /* Status des aktuellen Eintrages */
unsigned fropen; /* Zahl der unbestaetigten Frames */
unsigned cnt; /* Scratch Zaehler */
unsigned tosend; /* Zahl der zu sendenden Frames */
mhtyp *nxtfra; /* aktuelles Frame */
for (cnt = 0, cirpoi = cirtab; /* gesamte Tabelle bearbeiten */
cnt < NUMCIR;
++cnt, ++cirpoi) {
if ((actsts = cirpoi->state3) != 0) { /* nur aktive Eintraege */
if (cirpoi->traout != 0) { /* Timeout noch nicht abgelaufen */
if (--cirpoi->traout == 0) { /* Timeout nun abgelaufen? */
if (actsts == 2) /* Status = connected? */
cirpoi->l4flag &= 0xffdf; /* nichts neues senden */
else { /* anderer Status: */
if (++cirpoi->l4try < tratri) /* noch mal versuchen? */
(actsts == 1)? sconrq() : sdisrq(); /* ja */
else l4nsta(4); /* Fehler melden */
}
} }
else { /* Timeout ist schon 0 */
if ((actsts == 2) /* connectet und Frames unbestaetigt? */
&& ((fropen = (cirpoi->l4vs - cirpoi->l4rxvs) & 0xff) != 0)) {
for (tosend = 0, nxtfra = (mhtyp *) cirpoi->mbhdtx.lnext;
tosend < fropen; /* Frames wiederholen */
++tosend, nxtfra = (mhtyp *) nxtfra->link.lnext) {
if (--nxtfra->l4time == 0) { /* wenn Timeout abgelaufen */
if (++nxtfra->l4trie < tratri) /* und noch Versuche frei */
sndfrm(nxtfra->pid, nxtfra);
else {
l4nsta(4); /* sonst melden */
break;
}
}
}
}
}
if (actsts == 2) { /* connectet? */
if ((cirpoi->acktim != 0)
&& (--cirpoi->acktim == 0)) /* ACK-Timer gerade abgelaufen? */
sndack(); /* dann ACK senden */
if ((cirpoi->tranoa != 0)
&& (--cirpoi->tranoa == 0)) /* No-activity-Timeout abgelaufen? */
endcir(); /* dann abwerfen */
}
} } }
/*---------------------------------------------------------------------------*/
VOID newcir() /* neuen Circuit aufbauen */
{
clrcir(); /* Eintrag in CIRTAB loeschen */
cirpoi->ideige = random(); /* eigenen ID erzeugen */
cirpoi->l4try = 0; /* Versuche = 0 */
sconrq(); /* Connect Request senden */
cirpoi->state3 = 1; /* neuer Status */
}
/*---------------------------------------------------------------------------*/
VOID discir() /* Circuit aufloesen */
{
if ((cirpoi->state3 == 1) /* Status CON-REQ? */
|| (cirpoi->state3 == 3)) /* oder DIS-REQ? */
l4nsta(0); /* nicht nach oben, nur intern melden */
else { /* connectet: */
kilfra(); /* alle Fragmente loeschen */
dealml(&cirpoi->mbhdrx); /* empfangene Frames loesschen */
cirpoi->numrx = 0;
cirpoi->l4flag |= 0x80; /* Abwurf einleiten */
}
}
/*---------------------------------------------------------------------------*/
BOOLEAN itocir(cflg, mbhd) /* Info an Circuit senden */
mhtyp *mbhd; /* Message Header */
unsigned cflg; /* Congestion Flag */
{
cirtyp *cblk; /* Kontrollblock */
if (((cblk = (cirtyp *) mbhd->l2lnk)->numtx < conctl) /* Platz? */
|| (cflg == 1)) /* immer senden? */
{
relink(unlink(mbhd), cblk->mbhdtx.lprev); /* Info umhaengen */
++cblk->numtx; /* Frames zaehlen */
mbhd->morflg = 0; /* Frame komplett */
cblk->tranoa = ininat; /* Timeout neu */
return(TRUE); /* hat funktioniert */
}
else return(FALSE); /* Fehler, ging nicht*/
}
/*---------------------------------------------------------------------------*/
VOID clr4rx(cflg) /* restliche Info senden */
unsigned cflg; /* Congestion Flag */
{
mhtyp *mbhd; /* Message Header */
while (cirpoi->numrx != 0) { /* ein Frame nach dem anderen */
(mbhd = (mhtyp * )cirpoi->mbhdrx.lnext)->l2lnk = (l2ltyp *)cirpoi;
mbhd->usrtyp = 4; /* User ist Circuit */
if (fmlink(cflg, mbhd) == 0) break; /* Ende bei Fehler */
cirpoi->tranoa = ininat; /* Timeout setzen */
--cirpoi->numrx; /* ein Frame ist weg */
}
}
/*---------------------------------------------------------------------------*/
VOID chksts() /* Status des eingelaufenen Frames auswerten */
{
unsigned frofs; /* bestaetigter Offset */
unsigned fropen; /* unbestaetigte Frames */
if ((
fropen = (cirpoi->l4vs - cirpoi->l4rxvs) & 0xff
) != 0) { /* Frames offen? */
if ((
frofs = (l4hdr3 - cirpoi->l4rxvs) & 0xff /* neu bestaetigte Frames */
) != 0) {
if (frofs <= fropen) {
while (frofs-- != 0) {
dealmb(unlink(cirpoi->mbhdtx.lnext)); /* koennen weg */
--cirpoi->numtx; /* eins weniger zu senden */
++cirpoi->l4rxvs; /* eins mehr bestaetigt */
} } } }
if ((l4opco & 0x80) == 0) { /* Partner choked? */
cirpoi->l4flag &= 0xffdf; /* nein: merken */
cirpoi->traout = 0; /* Timeout kann nicht kommen */
if (((l4opco & 0x40) != 0) /* NAK Flag? */
&& (cirpoi->l4vs != cirpoi->l4rxvs)) /* und noch was offen? */
sndfrm(cirpoi->l4rxvs, cirpoi->mbhdtx.lnext); /* dann wiederholen */
}
else { /* Partner ist choked */
cirpoi->l4flag |= 0x20; /* merken */
cirpoi->traout = trabsy; /* warten */
cirpoi->l4vs = cirpoi->l4rxvs; /* keine Frames offen */
}
}
/*---------------------------------------------------------------------------*/
VOID takfrm(mbhd) /* empfangenes Frame uebernehmen */
mhtyp *mbhd;
{
char *nxt1; /* naechstes Zeichen des ersten Teils */
unsigned get1; /* Getcount des ersten Teils */
unsigned more; /* Frame ist auch nur Fragment */
mhtyp *fragmn; /* Fragment des Frames */
if ((cirpoi->l4flag & 0x80) == 0) { /* liegt DISC-REQ vor? */
if ((fragmn = cirpoi->fragme) == NULL) { /* noch kein Fragment vorhanden */
if (mbhd->morflg == 1) { /* ist dies ein Fragment? */
cirpoi->fragme = mbhd; /* dann nur merken */
mbhd = NULL; /* Frame ist weg */
} }
else { /* Fragment schon vorhanden */
nxt1 = fragmn->nxtchr; /* altes Ende merken */
get1 = fragmn->getcnt;
while (fragmn->getcnt < fragmn->putcnt)
getchr(fragmn); /* auf Ende des ertsen Teils gehen */
while (mbhd->getcnt < mbhd->putcnt)
putchr(getchr(mbhd), fragmn); /* neues Frame anhaengen */
fragmn->nxtchr = nxt1; /* Pointer wieder auf alten Stand */
fragmn->getcnt = get1;
more = mbhd->morflg; /* kommt noch mehr? */
dealmb(mbhd); /* neuer Teil kann weg */
if (more == 0) { /* nichts mehr im Rohr? */
mbhd = fragmn; /* dann ist das Ergebniss die neue Summe */
cirpoi->fragme = 0; /* kein Fragment mehr da */
}
else mbhd = 0; /* es kommt noch was: Fragment bleibt */
}
if (mbhd != 0) { /* Frame noch da? */
relink(mbhd, cirpoi->mbhdrx.lprev); /* dann in RX Liste haengen */
++cirpoi->numrx; /* ein Frame mehr da */
}
}
else { /* Kanal soll abgeworfen werden */
dealmb(mbhd); /* Frame vernichten */
}
++cirpoi->l4vr; /* RX-Sequenz erhoehen */
}
/*---------------------------------------------------------------------------*/
VOID sndfrm(txsequ, mbhd) /* Frame senden */
mhtyp *mbhd; /* Info */
unsigned txsequ; /* Sendesequenz fuer L4 */
{
char *next; /* Pointer auf letztes Zeichen des Headers */
mhtyp *netmhd; /* Netzwerk MBHD */
l4ahd2 = /* VS in Netzwerkheader */
mbhd->pid = txsequ; /* VS als PID */
l4aopc = 5; /* Opcode = Info */
ackhdr(); /* Rest des Headers erzeugen */
next =
(netmhd = gennhd()) /* Buffer fuer Netzwerkframe holen */
->nxtchr; /* Position Opcode merken (eins davor) */
if ((
splcpy((256 - netmhd->putcnt), netmhd, mbhd) /* Info umkopieren */
) == 1) { /* hat alles reingepasst? */
++cirpoi->numtx; /* neun: ein Frame mehr */
mbhd->morflg = TRUE; /* Fragmentierung markieren */
}
if (mbhd->morflg == TRUE)
*(next -1) |= 0x20; /* MORE Flag im Opcode setzen */
itol3(netmhd); /* Frame an Level3 liefern */
mbhd->l4time = tratou; /* Timeout im Infoframe setzen */
}
/*---------------------------------------------------------------------------*/
VOID l4nsta(frtyp) /* Statusaenderung in Level4 */
char frtyp; /* als Reaktion auf : 0=intern, 1=UA, 2=DISC */
{ /* 3=DM, 4=L4-Versuche abgelaufen */
clrcir(); /* alle Pointer im Eintrag loeschen */
if (frtyp != 0) { /* nach oben melden? */
l2tol7(frtyp, cirpoi, 4); /* meldender User ist der Circuit */
}
dealml(&cirpoi->mbhdrx); /* keine Frames empfangen */
dealml(&cirpoi->mbhdtx); /* keine Frames zu senden */
cirpoi->numrx = /* Emfangsliste ist leer */
cirpoi->numtx = /* Sendeliste ist leer */
cirpoi->state3 = 0; /* Status = Eintrag ist leer */
}
/*---------------------------------------------------------------------------*/
VOID endcir() /* Circuit aufloesen */
{
clrcir(); /* Eintrag in CIRTAB loeschen */
cirpoi->l4try = 0; /* Versuche ruecksetzen */
sdisrq(); /* Abwurf einleiten */
cirpoi->state3 = 3; /* neuer Status: DISC-REQ gegeben */
}
/*---------------------------------------------------------------------------*/
VOID clrcir() /* Eintrag in CIRTAB loeschen */
{
kilfra(); /* Fragmente loeschen */
dealml(&cirpoi->mbhdos); /* Messageliste dafuer auch */
cirpoi->l4rxvs = /* alle Sequenzen auf 0 */
cirpoi->l4vs =
cirpoi->l4vr =
cirpoi->l4rs = /* ACK-NAK Flag */
cirpoi->traout = /* Timeout */
cirpoi->l4flag = 0; /* niemand choked, kein DISC-REQ */
}
/*---------------------------------------------------------------------------*/
VOID sconrq() /* CON-REQ senden */
{
mhtyp *mbhd; /* Buffer fuer Frame */
l4pidx = cirpoi - &cirtab[0]; /* Index setzen */
l4pcid = cirpoi->ideige; /* Partner und eigener Index */
l4ahd2 = /* zwei Bytes leer */
l4ahd3 = 0;
l4aopc = 1; /* Opcode */
putchr (trawir, (mbhd = gennhd())); /* Rest des Headers */
putfid(cirpoi->upcall, mbhd); /* beide Calls in das Frame */
putfid(myid, mbhd);
itol3(mbhd); /* an Level3 liefern */
cirpoi->traout = tratou; /* Timeout setzen */
}
/*---------------------------------------------------------------------------*/
VOID sdisrq() /* DISC-REQ senden */
{
l4pidx = cirpoi->idxpar; /* Index setzen */
l4pcid = cirpoi->idpart; /* und ID */
l4ahd2 = /* zwei Bytes leer */
l4ahd3 = 0;
l4aopc = 3; /* Opcode */
itol3(gennhd()); /* Rest des Headers und dann an Level3 */
cirpoi->traout = tratou; /* Timeout setzen */
}
/*---------------------------------------------------------------------------*/
VOID sndack() /* ACK senden */
{
l4ahd2 = 0;
l4aopc = 6; /* Opcode */
ackhdr(); /* Rest des Headers */
itol3(gennhd()); /* Rest des Headers und dann an Level3 */
}
/*---------------------------------------------------------------------------*/
VOID ackhdr() /* ACK Header erzeugen */
{
l4pidx = cirpoi->idxpar; /* Partner Index */
l4pcid = cirpoi->idpart; /* Partner ID */
l4ahd3 = cirpoi->l4vr; /* RX-Sequenz */
if ((cirpoi->l4flag & 0x40) != 0) /* selbst choked? */
l4aopc |= 0x80; /* dann Flag setzen */
else {
if (cirpoi->l4rs == 1) { /* wird es ein NAK Header? */
l4aopc |= 0x40; /* dann Flag setzen */
cirpoi->l4rs = 2; /* NAK als gesendet markieren */
}
}
cirpoi->acktim = 0; /* ACK Timer ruecksetzen */
}
/*---------------------------------------------------------------------------*/
VOID itol3(mbhd) /* Info an Level3 */
mhtyp *mbhd;
{
mbhd->l2lnk = (l2ltyp *) cirpoi->l3node; /* Controllblock */
relink(mbhd, l3txl.lprev); /* nur umhaengen */
}
/*---------------------------------------------------------------------------*/
mhtyp *gennhd() /* Netzwerk Header erzeugen */
{
unsigned cnt; /* Scratch Zaehler */
mhtyp *mbhd; /* Buffer fuer Info */
mbhd = (mhtyp *) allocb(); /* Buffer besorgen */
for (cnt = 0; cnt < 15; ++cnt) /* die ersten 15 Bytes fuer den Header leer */
putchr(0, mbhd);
putchr(l4pidx, mbhd); /* Transport Header schreiben */
putchr(l4pcid, mbhd);
putchr(l4ahd2, mbhd);
putchr(l4ahd3, mbhd);
putchr(l4aopc, mbhd);
return(mbhd); /* Buffer wird zurueck gegeben */
}
/*---------------------------------------------------------------------------*/
VOID kilfra() /* Fragmente loeschen */
{
if (cirpoi->fragme != NULL) { /* schon leer? */
dealmb(cirpoi->fragme); /* Fragment loeschen */
cirpoi->fragme = NULL; /* Eintrag loeschen */
}
}
/*- Ende Level 4 ------------------------------------------------------------*/