home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
524.L2B.C
< prev
next >
Wrap
Text File
|
1988-05-14
|
40KB
|
793 lines
/**************************************************************************\
* *
* *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** The Firmware. The Net. *
* ***** ***** Portable. Compatible. *
* ***** ***** Public Domain. *
* ***** ***** By NORD><LINK. *
* *
* *
* *
* L2B.C - Level 2, Teil 2 *
* *
* angelegt: DC4OX *
* modifiziert: *
* *
\**************************************************************************/
/* Includes */
/**************************************************************************/
#include "all.h" /* allgemeine Festlegungen */
#include "l2.h" /* Festlegungen/Datenstrukturen fuer den Level 2 */
#include "l2s.h" /* Zugriff auf die State-Tabellen */
#include "l2ext.h" /* globale Variable / nicht int-Funktionen */
/**************************************************************************\
* *
* "check no activity" *
* *
* Alle aktiven Links (lnktbl, Linkstatus "Information Transfer") auf *
* "keine Aktivitaet" abtesten. Ist der Keine-Aktivitaet-Timer aktiv (!= 0) *
* und nach Dekrementieren abgelaufen, Disconnect einleiten. *
* *
* ACHTUNG: Diese Funktion muss sekuendlich aufgerufen werden, *
* wird aber nur fuer TheNet benoetigt. *
* *
\**************************************************************************/
#ifndef FIRMWARE
VOID chknoa()
{
unsigned n;
for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
if (lnkpoi->state >= L2SIXFER)
if (lnkpoi->noatou != 0 && !(--lnkpoi->noatou)) disc();
}
#endif
/**************************************************************************\
* *
* "new link" *
* *
* Link (lnkpoi) neu aufbauen. Wenn Link noch nicht aktiv war, die Anzahl *
* aktiver Links (nmblks) erhoehen. *
* *
\**************************************************************************/
VOID newlnk()
{
reslnk(); /* Sequenzvars/Timer ruecksetzen */
setiT1(); /* FRACK-Timer neu starten */
txfV2 = lnkpoi->V2link; /* welche Protokollversion */
xsabm(); /* SABM senden */
if (lnkpoi->state == L2SDSCED) /* neuer Link ? */
++nmblks; /* ja ... */
lnkpoi->state = L2SLKSUP; /* Linkstatus "Link Setup" */
}
/**************************************************************************\
* *
* "disconnect link" *
* *
* Disconnect-Wunsch an aktuellen Link (lnkpoi) : *
* *
* Linkstatus "Disconnected" *
* -> Ax.25-Parameter "frisch" *
* *
* Linkstatus "Link Setup" oder "Disconnect Request" *
* -> Link aufloesen, neuer Linkstatus "Disconnected" *
* *
* sonst *
* -> Empfangsinfoframeliste loeschen, Linkstatus bleibt, Flag "nach *
* Loswerden aller zu sendenden Infoframes disconnecten" setzen *
* *
\**************************************************************************/
VOID dsclnk()
{
unsigned lstate;
if (!(lstate = lnkpoi->state)) /* Disced, nur */
inilbl(); /* AX-Pars neu */
else
if (lstate == L2SLKSUP || lstate == L2SDSCRQ) /* Linksetup oder */
{ /* Discreq, */
clrlnk(); /* Link aufloesen */
lnkpoi->state = L2SDSCED; /* Diconnected ! */
}
else
{ /* sonst */
dealml(&lnkpoi->rcvdil); /* RX-Infoframe- */
lnkpoi->rcvd = 0; /* loeschen und */
lnkpoi->flag |= L2FDSLE; /* Flag, s.o. */
}
}
/**************************************************************************\
* *
* "information to link" *
* *
* Infobuffer, auf den imbp zeigt, an in diesem Buffer festgelegten Link *
* (l2link) zwecks Aussendung als Paket weitergeben. Wenn nocgnc == YES *
* keine "Erstickungskontrolle", sonst conctl beachten (s.u.). *
* Der Infobuffer wird bei Weitergabe an den Link mit der normalen Level 2 *
* PID versehen, der Keine-Aktivitaets-Timer wird neu gestartet. *
* *
* Return: TRUE - imbp wurde angenommen und an den Link weitergegeben *
* FALSE - imbp wurde nicht angenommen wegen Congestion Control *
* = Grenze der pro Link maximal zu speichernden Pakete *
* (conctl) wuerde ueberschritten werden *
* *
\**************************************************************************/
BOOLEAN itolnk(nocgnc,imbp)
BOOLEAN nocgnc; /* "no congestion control" */
MBHEAD *imbp; /* "I message buffer pointer" */
{
LNKBLK *linkp;
if ((linkp = imbp->l2link)->tosend < conctl || nocgnc == YES)
{
imbp->l2fflg = L2CPID; /* Standard-L2-PID */
relink(unlink(imbp),linkp->sendil.tail); /* -> ab in den Link */
++linkp->tosend; /* ein Sendepaket mehr */
linkp->noatou = ininat; /* wieder Aktivitaet */
return (TRUE); /* ... imbp angenommen */
}
return (FALSE); /* ... imbp abgelehnt */
}
/**************************************************************************\
* *
* "digipeat" *
* *
* Framebuffer, auf den fbp zeigt, abtesten, ob er ein zu digipeatendes *
* Paket enthaelt. Wenn ja, Paket an den entsprechenden Port (falls ein *
* bekannter Nachbarknoten direkt in der Digiliste folgt oder nach *
* kompletten Digipeaten das Ziel ist, kann das Paket auch auf einem *
* anderen als dem normalen HDLC-Port digipeatet werden) ausgeben. *
* Das Paket muss schon durch takfhd() analysiert sein, die rxf...- *
* Parameter muessen gesetzt sein. *
* *
* Return: YES - das Frame wurde entweder digipeatet, oder der *
* Framebuffer wurde deallokiert, weil das Frame noch von *
* einer anderen Station digipeatet werden muss oder ich *
* nicht digipeaten darf *
* NO - das Frame muss nicht mehr digipeated werden, hat alle *
* noetigen Digipeater durchlaufen, ist zur Auswertung frei *
* *
\**************************************************************************/
BOOLEAN digipt(fbp)
MBHEAD *fbp;
{
char *viap; /* Zeiger in via-Liste */
unsigned n; /* Zaehler */
viap = rxfhdr + L2ILEN; /* Anfang via-Liste */
while (*viap != '\0') /* via-Liste durchgehen */
{
if (!(viap[L2IDLEN - 1] & L2CH)) /* zu digipeaten ? */
{
if (Rpar == YES && istome(viap) == TRUE) /* ja, darf ich */
{ /* und muss ich : */
rwndmb(fbp); /* Zeiger auf Hbit */
n = (unsigned)(viap - (rxfhdr+L2ILEN) + (L2ILEN+L2IDLEN));
while (n-- != 0) getchr(fbp); /* berechnen */
*(fbp->mbbp - 1) |= L2CH; /* Hbit setzen */
viap += L2IDLEN; /* Nachbardigi */
fbp->l2port = nbrprt( *viap != '\0' /* ich letzter ? */
? viap /* nein, Port Digi */
: rxfhdr); /* ja, Port Ziel */
fbp->l2fflg = 0; /* kein Linkframe */
sdl2fr(fbp); /* Frame senden */
}
else /* Frame ist noch nicht komplett digipeatet */
dealmb(fbp); /* und/oder nix fuer mich, Frame wegwerfen */
return (YES); /* fuer aufrufende Funk.: Frame ist weg ! */
}
viap += L2IDLEN; /* naechsten Digi in Digiliste untersuchen */
}
return (NO); /* fuer aufrufende Funk.: Frame auswerten ! */
}
/**************************************************************************\
* *
* "to level 3 switch" *
* *
* Aus I- oder UI-Frame (Framekopf fbp, Getzeiger/Zaehler auf 1. Byte *
* hinter Level-2-Adressfeld) PID holen, falls vorhanden. Falls es nicht *
* Level-2-PID ist, das Paket an die Level-3-Empfangsframeliste l3rxfl *
* haengen. Im Framekopf wird in jedem Fall l2fflg auf PID, wenn vorhanden, *
* oder 0 gesetzt, l2link auf den aktuellen Link (lnkpoi). *
* *
* Return: YES - das I/UI-Frame hat ein Nicht-Level-2-PID und wurde an die *
* Level-3-Empfangsframeliste gehaengt *
* NO - Frame hat Standard-Level-2-PID *
* *
\**************************************************************************/
BOOLEAN tol3sw(fbp)
MBHEAD *fbp;
{
fbp->l2fflg = fbp->mbgc < fbp->mbpc ? getchr(fbp) : 0; /* PID holen */
fbp->l2link = lnkpoi; /* Linkzeiger */
if ((fbp->l2fflg & 0xFF) != L2CPID)
{ /* wenn nicht L2-Frame, Frame an */
relink(fbp,l3rxfl.tail); /* Level 3 weiterreichen */
return (YES); /* Meldung, dass weitergereicht */
}
return (NO); /* Meldung, dass Level-2-Frame */
}
/**************************************************************************\
* *
* "level 2 information to level x" *
* *
* Infopakete aus dem aktuellen Link (lnkpoi) an hoehere Level weiter- *
* reichen. nocgnc gibt an, ob der hoehere Level die "Erstickungskontrolle" *
* (hier = Beruecksichtigung der maximal noch anzunehmenden I-Pakete) *
* machen soll (NO) oder in jedem Fall alle uebermittelten I-Pakete *
* annehmen muss (YES). Falls die I-Pakete vom hoeheren Level angenommen *
* wurden, Empfangszaehler rcvd und Aktivitaetstimer noatou entsprechend *
* updaten. Es wird l2link in den Framekoepfen der weitergereichten Pakete *
* auf lnkpoi gesetzt und type auf 2 fuer "Level 2". *
* *
\**************************************************************************/
VOID i2tolx(nocgnc)
unsigned nocgnc;
{
MBHEAD *rcvdip; /* Zeiger auf Framekopf weiterzureichendes I */
while (lnkpoi->rcvd != 0) /* solange I's aus Link vorhanden */
{
(rcvdip = lnkpoi->rcvdil.head)->l2link = lnkpoi; /* Linkzeiger */
rcvdip->type = 2; /* Level 2 ! */
if (!fmlink(nocgnc,rcvdip)) /* I an hoeheren Level geben */
return; /* Abbruch, wenn nicht angenommen */
lnkpoi->noatou = ininat; /* angenommen, wieder Aktivitaet */
--lnkpoi->rcvd; /* Empfangspaketezaehler updaten */
}
}
/**************************************************************************\
* *
* "serve received N(R)" *
* *
* Aktuell empfangenes N(R) (rxfctl) des aktuellen Links (lnkpoi) auswerten *
* und entsprechend verfahren (s.u.). *
* *
* Return: YES - aktuell empfangenes N(R) ist okay oder Linkzustand *
* laesst N(R)-Empfang nicht zu *
* NO - aktuell empfangenes N(R) ist falsch *
* *
\**************************************************************************/
BOOLEAN srxdNR()
{
unsigned rxdNR; /* empfangenes N(R) */
unsigned newok; /* Anzahl neu bestaetigte I's */
unsigned outstd; /* Anzahl ausstehende (nicht bestaetigte) I's */
unsigned l2state; /* Linkstatus des aktuellen Links */
if ((l2state = lnkpoi->state) >= L2SIXFER) /* darf N(R) kommen ? */
{
if ( ( outstd = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07
) != 0
&& ( newok = ( (rxdNR = (rxfctl >> 5) & 0x07) - lnkpoi->lrxdNR
) & 0x07
) != 0 /* N(R) nur auswerten, wenn I's aus- */
) /* stehen und neue bestaetigt werden */
if (newok <= outstd) /* N(R) okay ? */
{
lnkpoi->lrxdNR = rxdNR; /* ja, N(R) annehmen */
clrT1(); /* T1 stoppen */
if (newok != outstd) /* wenn immer noch I's ausstehend */
setT1(); /* T1 neu starten */
while (newok-- != 0)
{ /* alle neu */
dealmb(unlink(lnkpoi->sendil.head)); /* bestaetigten */
--lnkpoi->tosend; /* I's wegwerfen */
}
}
else
{ /* nein, */
sdfrmr(0x08); /* Kontrollfeld hat falsches N(R) */
return (FALSE); /* N(R) nicht okay ! */
}
if ( l2state == L2SWA /* falls Linkzustand "Warten auf */
|| l2state == L2SWADBS /* Bestaetigung" ist, */
|| l2state == L2SWARBS
|| l2state == L2SWABBS
)
if (!rxfCR && rxfPF != 0) /* wenn empfangenes Frame */
{ /* Response mit Final war, */
clrT1(); /* Timer 1 stoppen und */
lnkpoi->VS = lnkpoi->lrxdNR; /* V(S) updaten */
}
else /* sonst Timer 1 neu */
if (!lnkpoi->T1) setT1(); /* starten falls inaktiv */
}
return (TRUE); /* N(R) okay oder nicht benutzt */
}
/**************************************************************************\
* *
* "is next I" *
* *
* Testen, ob das aktuell empfangene I-Frame (rxf...) das naechste fuer den *
* aktuellen Linkblock (lnkpoi) erwartete I-Frame ist, wenn der Linkzustand *
* Informationstransfer zulaesst. Bei nicht erwarteter Sequenznummer *
* entsprechende Statetable abarbeiten. *
* *
* Return : YES - I-Frame ist das naechste erwartete oder Linkzustand *
* laesst keinen Informationstransfer zu *
* NO - sonst *
* *
\**************************************************************************/
BOOLEAN isnxti()
{
unsigned iseqno; /* I Sequence Number */
if (lnkpoi->state >= L2SIXFER) /* I-Transfer ? */
if ((iseqno = (rxfctl >> 1) & 0x07) == lnkpoi->VR) /* I erwartet ? */
if (((lnkpoi->ltxdNR + 7) & 0x07) != iseqno) /* kein Ueber- */
{ /* lauf ? */
if (!(lnkpoi->flag & L2FBUSY)) /* wenn nicht busy, neue */
lnkpoi->VR = (iseqno + 1) & 0x07; /* V(R) setzen */
}
else
{
sdfrmr(0x01); /* Kontrollfeld falsch/nicht implementiert */
return (FALSE);
}
else /* unerwartetes I (nicht */
{ /* naechstes in Reihe) */
l2stma(!rxfPF ? stbl26 : stb26b); /* INVALID N(S) RECEIVED */
return (FALSE); /* unerwartetes I ! */
}
return (TRUE); /* I richtig oder Linkzustand ohne I-Transfer */
}
/**************************************************************************\
* *
* "initialize link" *
* *
* Aktuellen Linkblock (lnkpoi) initialisieren. Sequenzvariablen und Timer *
* initialisieren, Quellcall/Zielcall/via-Liste/ Port setzen aus der *
* txf...-Liste. *
* *
\**************************************************************************/
VOID inilnk()
{
reslnk(); /* Sequenzvars/Timer init. */
cpyid(lnkpoi->srcid,txfhdr + L2IDLEN); /* Quellcall */
cpyid(lnkpoi->dstid,txfhdr); /* Zielcall */
cpyidl(lnkpoi->viaidl,txfhdr + L2ILEN); /* via-Liste */
lnkpoi->liport = txfprt; /* Port */
setiT1(); /* initial Timer 1 */
}
/**************************************************************************\
* *
* "set initial T1" *
* *
* Den initialen Timer-1-Zaehlerstand des aktuellen Linkblocks (lnkpoi) *
* (= derjenige Zaehlerstand, der bei Start des Timer 1 immer gesetzt wird) *
* berechnen nach der Formel : *
* *
* *
* initT1 [1/100 sec] *
* *
* = (Anzahl der Digipeater * 2 + 1) * FRACK [sec] * 100 *
* | *
* +---> fuer jeden Linkblock *
* und im Linkblock setzen (initT1). einzeln, snglT1 *
* *
\**************************************************************************/
VOID setiT1()
{
char *viap; /* Zeiger in via-Liste */
unsigned n; /* Digizaehler */
viap = lnkpoi->viaidl; /* Anfang via-Liste */
n = 0; /* noch kein Digi gezaehlt */
while (*viap != '\0') /* Digianzahl ermitteln */
{
++n;
viap += L2IDLEN;
}
n *= 2; /* Digianzahl * 2 + 1 */
++n;
lnkpoi->initT1 = lnkpoi->snglT1 * n * 100; /* " * FRACK * 100 */
}
/**************************************************************************\
* *
* "messaged clear link" *
* *
* Aktuellen Link aufloesen (siehe clrlnk()) und entsprechende Meldung an *
* hoehere Level geben ("Disconnected from"). *
* *
\**************************************************************************/
VOID mclrlk()
{
clrlnk(); /* Link aufloesen */
l2tolx(L2MDISCF); /* und hoehere Level informieren */
}
/**************************************************************************\
* *
* "clear link" *
* *
* Aktuellen Link (lnkpoi) aufloesen. Alle Sequenzvariablen und Timer *
* zuruecksetzen, Sende- und Empfangsinfoframelise loeschen, Linkblock neu *
* mit AX.25-Parametern besetzen, Anzahl der aktiven Links (nmblks) um 1 *
* erniedrigen. *
* *
\**************************************************************************/
VOID clrlnk()
{
reslnk(); /* Sequenzvars/Timer ruecksetzen */
dealml(&lnkpoi->rcvdil); /* Empfangsinfoliste loeschen */
dealml(&lnkpoi->sendil); /* Sendeinfoliste loeschen */
lnkpoi->rcvd = lnkpoi->tosend = 0; /* entsprechende Zaehler loeschen */
--nmblks; /* nun ein aktiver Link weniger */
inilbl(); /* Linkblock "frisch" */
}
/**************************************************************************\
* *
* "disconnect" *
* *
* Disconnect des aktuellen Links (lnkpoi) einleiten. Alle Sequenzvariablen *
* und Timer zuruecksetzen, DISC senden, neuer Status "Disconnect request". *
* *
\**************************************************************************/
VOID disc()
{
reslnk(); /* Sequenzvars/Timer ruecksetzen */
xdisc(); /* DISC senden */
lnkpoi->state = L2SDSCRQ; /* Linkstatus "Disc Request" */
}
/**************************************************************************\
* *
* "reset link" *
* *
* Aktuellen Link (lnkpoi) zuruecksetzen. Alle Sequenzvariablen und Timer *
* initialisieren. *
* *
\**************************************************************************/
VOID reslnk()
{
lnkpoi->VS
= lnkpoi->VR
= lnkpoi->ltxdNR
= lnkpoi->lrxdNR
= lnkpoi->flag
= 0;
clrT1();
clrT2();
}
/**************************************************************************\
* *
* "initialize link block" *
* *
* Aktuellen Linkblock (lnkpoi) mit AX.25-Parametern initialisieren. *
* Loeschen des Quellrufzeichens, Setzen von FRACK, MAXFRAME, RETRY, *
* AX25V2. *
* *
\**************************************************************************/
VOID inilbl()
{
*lnkpoi->srcid = '\0';
lnkpoi->snglT1 = Fpar;
lnkpoi->k = Opar;
lnkpoi->N2 = Npar;
lnkpoi->V2link = Vpar;
}
/**************************************************************************\
* *
* "send outstanding I's" *
* *
* Aus dem aktuellen Linkblock (lnkpoi) soviele I-Frames senden, wie im *
* Moment unbestaetigt ausstehen. *
* *
\**************************************************************************/
VOID sdoi()
{
unsigned nmbtos; /* Anzahl I's zu senden */
if (nmbtos = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07) /* wieviel darf */
{ /* ich ? */
lnkpoi->VS = lnkpoi->lrxdNR; /* V(S) resetten */
sdi(nmbtos); /* I's senden */
}
}
/**************************************************************************\
* *
* "send I" *
* *
* Aus dem aktuellen Linkblock (lnkpoi) maximal max I-Frames aus der *
* Infomessageliste aufbauen und senden. Infos ueber 256 Bytes werden *
* gesplittet und dann gesendet. Die Frames werden als Commandframes ohne *
* Poll/Final-Bit gesendet. V(S) wird fuer jedes gesendete Frame erhoeht *
* modulo 7. Timer 2 und Timer 3 werden abgeschaltet. *
* *
\**************************************************************************/
VOID sdi(max)
unsigned max;
{
unsigned n; /* Zaehler zu sendende Infos */
MBHEAD *sendip; /* Kopfzeiger Infobuffer */
MBHEAD *fbp; /* Kopfzeiger Framebuffer */
for ( n = 0, sendip = lnkpoi->sendil.head; /* maximal max I-Frames */
n < lnkpoi->tosend && n < max; /* aus der Linkblock- */
++n, sendip = sendip->nextmh /* infoliste senden */
) /* wenn vorhanden */
{
stxfad(); /* Frameadresse aufbauen */
txfV2 = lnkpoi->V2link; /* Version */
txfCR = L2CCR; /* Command ! */
txfPF = 0; /* kein Poll/Final */
txfctl = setNR(lnkpoi->VS << 1); /* Controlbyte I setzen */
++lnkpoi->VS; /* V(S) erhoehen */
lnkpoi->VS &= 0x07; /* modulo 7 */
putchr(sendip->l2fflg, /* Frame aufbauen, PID */
fbp = makfhd(L2FT1ST));
if (splcpy(256,fbp,sendip) == YES) /* Message hineinkopieren */
++lnkpoi->tosend; /* falls Split eine mehr */
sdl2fr(fbp); /* Frame senden */
clrT2(); /* Timer 2 abschalten */
clrT3(); /* Timer 3 abschalten */
}
}
/**************************************************************************\
* *
* "split copy" *
* *
* Die Bytes aus dem Messagebuffer, auf dessen Kopf mbhd zeigt, in den *
* Framebuffer, auf dessen Kopf fbp zeigt, kopieren. Es werden hoechstens *
* max Bytes kopiert, hat die Message mehr Bytes, so wird ein neuer *
* Messagebuffer angelegt, die restlichen Messagebytes werden in diesen *
* Buffer kopiert, der neue Buffer wird hinter den alten Messagebuffer *
* gehaengt, der Putcount des alten Buffers wird auf max gestellt, das *
* "more follows"-Flag morflg des neuen Buffers wird geloescht, l2fflg wird *
* uebertragen. *
* *
* Return : YES - der Messagebuffer wurde aufgesplittet *
* NO - sonst *
* *
\**************************************************************************/
BOOLEAN splcpy(max,fbp,mbhd)
unsigned max;
MBHEAD *fbp;
MBHEAD *mbhd;
{
char *mbbpsa; /* Sicherung mbbp */
BOOLEAN split; /* TRUE: Split erfolgt */
unsigned mbgcsa; /* Sicherung mbgc */
unsigned mbgc2; /* mbgc alt -> mbpc alt */
unsigned n; /* Zaehler */
MBHEAD *mbhd2; /* Kopfzeiger neuer Messagebuffer */
split = NO; /* zunaechst nichts gesplittet */
mbbpsa = mbhd->mbbp; /* Bufferpointer sichern */
mbgcsa = mbhd->mbgc; /* Getcounter sichern */
for (n = 0; mbhd->mbgc < mbhd->mbpc && n < max; ++n)
putchr(getchr(mbhd),fbp); /* maximal max Bytes kopieren */
if (mbhd->mbgc < mbhd->mbpc) /* noch Bytes ueber -> Split ! */
{
mbgc2 = mbhd->mbgc; /* Getcount fuer spaeter merken */
mbhd2 = allocb(); /* neuen Buffer erzeugen */
while (mbhd->mbgc < mbhd->mbpc) /* die restlichen Bytes in diesen */
putchr(getchr(mbhd),mbhd2); /* Buffer kopieren */
rwndmb(mbhd2); /* neuen Buffer rewinden */
mbhd2->morflg = NO; /* noch dem neuen folgt keiner */
mbhd2->l2fflg = mbhd->l2fflg; /* Frameflag uebertragen */
relink(mbhd2,mbhd); /* neu. Buf. hinter alten haengen */
mbhd->mbpc = mbgc2; /* alter Buffer nur max Zeichen ! */
split = YES; /* wir mussten splitten */
}
mbhd->mbbp = mbbpsa; /* Bufferpointer restaurieren */
mbhd->mbgc = mbgcsa; /* Getcount restaurieren */
return (split); /* Split oder nicht */
}
/**************************************************************************\
* *
* "send UI" *
* *
* UI-Frame aufbauen und senden. Das UI-Frame wird an ID dest geschickt *
* ueber den Port port und die via-Liste (nullterminiert) vial, als Quelle *
* wird source genommen, die Infobytes des Frames stehen im Messagebuffer, *
* auf dessen Kopf mbhd zeigt, die PID wird aus l2fflg dieses Buffers *
* genommen. *
* *
\**************************************************************************/
VOID sdui(vial,dest,source,port,mbhd)
char *vial;
char *dest;
char *source;
unsigned port;
MBHEAD *mbhd;
{
MBHEAD *fbp; /* Zeiger auf Framekopf */
cpyid(txfhdr + L2IDLEN,source); /* Quelle setzen */
cpyid(txfhdr,dest); /* Ziel setzen */
cpyidl(txfhdr + L2ILEN,vial); /* via-Liste setzen */
txfprt = port; /* Port setzen */
txfV2 = Vpar; /* Protokollversion */
txfCR = L2CCR; /* Command ! */
txfPF = 0; /* kein Poll/Final */
txfctl = L2CUI; /* UI-Frame ! */
putchr(mbhd->l2fflg,fbp = makfhd(0)); /* Frame aufbauen, PID */
while (mbhd->mbgc < mbhd->mbpc) /* Message -> Frame */
putchr(getchr(mbhd),fbp);
sdl2fr(fbp); /* Frame senden */
}
/**************************************************************************\
* *
* "level 2 state machine" *
* *
* Ausfuehren der Zustandsuebergangsfunktion des Linkstatus (state) des *
* aktuellen Linkblocks (lnkpoi) in der Statetable stbl, danach einnehmen *
* des durch die Statetable gegebenen neuen Zustands. *
* *
* In der Protokollversion 1 (dort gibt es nur 5 Zustaende), alle Zustaende *
* oberhalb Informationstransfer auf Informationstransfer setzen. *
* *
\**************************************************************************/
VOID l2stma(stbl)
STENTRY stbl[];
{
(*stbl[lnkpoi->state].func)(); /* Funktion ... */
lnkpoi->state = stbl[lnkpoi->state].newstate; /* neuer Zustand */
if (!lnkpoi->V2link && lnkpoi->state > L2SIXFER) /* Version 1 */
lnkpoi->state = L2SIXFER; /* Stutzung */
}
/* Ende von L2B.C */