home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
525.L2C.C
< prev
next >
Wrap
Text File
|
1988-05-14
|
42KB
|
877 lines
/**************************************************************************\
* *
* *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** *
* ***** ***** The Firmware. The Net. *
* ***** ***** Portable. Compatible. *
* ***** ***** Public Domain. *
* ***** ***** By NORD><LINK. *
* *
* *
* *
* L2C.C - Level 2, Teil 3 *
* *
* 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 */
/**************************************************************************\
* *
* action : Zustandsuebergangsfunktionen der Level-2-Statetable *
* (x.../t...), Level-2-Timer setzen/aufloesen (setT./clrT.) *
* und Utilities fuer diese Funktionen. *
* *
* t2rrr() - Timer 2 setzen, nach Ablauf RR als Response zu senden *
* t2rnrr() - Timer 2 setzen, nach Ablauf RNR als Response zu senden *
* t2rejr() - Timer 2 setzen, nach Ablauf REJ als Response zu senden *
* *
* xnull() - nichts tun *
* *
* xrrc() - RR als Command senden *
* xrrr() - RR als Response senden *
* xrnrc() - RNR als Command senden *
* xrnrr() - RNR als Response senden *
* xrejr() - REJ als Response senden *
* *
* xdm() - DM senden *
* xua() - UA senden *
* xsabm() - SABM senden *
* xdisc() - DISC senden *
* *
* xfrmr() - FRMR senden (-> L2E.C) *
* *
* setT1() - Timer 1 setzen und Timer 3 loeschen *
* clrT1() - Timer 1 und tries loeschen, Timer 3 setzen *
* setT2() - Timer 2 und nach Ablauf zu sendenden Frametyp setzen *
* clrT2() - Timer 2 und nach Ablauf zu sendenden Frametyp loeschen *
* setT3() - Timer 3 setzen, wenn Version 2 Protokoll benutzt wird *
* clrT3() - Timer 3 loeschen *
* *
* sendS() - Supervisory-Frame fuer Sendung aufbauen, Timer 2 *
* loeschen, Frame senden *
* sdfrmr() - FRMR-Frame fuer Sendung aufbauen und senden (-> L2E.C) *
* *
\**************************************************************************/
VOID t2rrr() { setT2(L2CRR); }
VOID t2rnrr() { setT2(L2CRNR); }
VOID t2rejr() { setT2(L2CREJ); }
VOID setT1() { lnkpoi->T1 = lnkpoi->initT1 + random(); clrT3(); }
VOID clrT1() { lnkpoi->T1 = lnkpoi->tries = 0; setT3(); }
VOID setT2(Stype) char Stype;
{ lnkpoi->RStype = Stype; lnkpoi->T2 = T2par; }
VOID clrT2() { lnkpoi->T2 = 0; lnkpoi->RStype = 0; }
VOID setT3() { if (lnkpoi->V2link == YES) lnkpoi->T3 = T3par; }
VOID clrT3() { lnkpoi->T3 = 0; }
VOID xnull() { }
VOID xrrc() { stxcfr(); xrrr(); }
VOID xrrr() { sendS(L2CRR); }
VOID xrnrc() { stxcfr(); xrnrr(); }
VOID xrnrr() { sendS(L2CRNR); }
VOID xrejr() { sendS(L2CREJ); }
VOID sendS(control) char control;
{ clrT2(); txfctl=setNR(control);
sdl2fr(makfhd(!txfCR ? L2FUS : (L2FUS | L2FT1ST))); }
VOID xdm() { txfctl = L2CDM; sdl2fr(makfhd(L2FUS)); }
VOID xua() { txfctl = L2CUA; sdl2fr(makfhd(L2FUS)); }
VOID xsabm() { stxcfr(); txfctl = L2CSABM; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
VOID xdisc() { stxcfr(); txfctl = L2CDISC; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
/**************************************************************************\
* *
* "set tx command frame" *
* *
* TX-Frame-Adressierung setzen (siehe stxfad()) und Frame zum Kommando- *
* frame machen mit gesetztem Pollbit (txfCR,txfPF). *
* *
\**************************************************************************/
VOID stxcfr()
{
stxfad(); /* Adressierung */
txfCR = L2CCR; /* Command ! */
txfPF = L2CPF; /* Pollbit ! */
}
/**************************************************************************\
* *
* "set tx frame address" *
* *
* Adressierung des aktuellen Sendeframes (txfhdr, txfprt) setzen aus den *
* im aktuellen Linkblock (lnkpoi) gegebenen Parametern (srcid, destid, *
* viaidl, liport). *
* *
\**************************************************************************/
VOID stxfad()
{
cpyid(txfhdr + L2IDLEN,lnkpoi->srcid); /* von ... */
cpyid(txfhdr,lnkpoi->dstid); /* nach ... */
cpyidl(txfhdr + L2ILEN,lnkpoi->viaidl); /* ueber ... */
txfprt = lnkpoi->liport; /* auf Port ... */
}
/**************************************************************************\
* *
* "set NR" *
* *
* Im aktuellen Linkblock (lnkpoi) die zuletzt gesendete N(R) (ltxdNR) auf *
* V(R) (VR) setzen und Framecontrolbyte control fuer Frameaussendung mit *
* der N(R) versehen und zurueckgeben. *
* *
* Return : control mit N(R) versehen *
* *
\**************************************************************************/
unsigned setNR(control)
char control;
{
lnkpoi->ltxdNR = lnkpoi->VR; /* neue N(R) */
return((lnkpoi->VR << 5) | control); /* N(R) ins Kontrollfeld */
}
/**************************************************************************\
* *
* "send level 2 frame" *
* *
* Framebuffer, auf dessen Kopf fbp zeigt, rewinden und in die dem Port *
* (l2port) entsprechende Level-2-Sendeframeliste einhaengen, wenn noch *
* genug Buffer im System frei sind. Andernfalls nicht senden, sondern *
* sofort in die Gesendet-Liste (stfl) einhaengen. Bei TheNet die *
* Sendeaktiviatetsvariable (istraf) des entsprechenden Ports setzen. *
* *
\**************************************************************************/
VOID sdl2fr(fbp)
MBHEAD *fbp;
{
unsigned port; /* Portnummer */
port = fbp->l2port; /* Portnummer holen */
if (nmbfre > 64) /* noch genug Buffer ? */
{
rwndmb(fbp); /* ja - Framebuffer rewinden */
DIinc(); /* Listenkonsistenz ! */
relink(fbp,txl2fl[port].tail); /* Frame in Sendeliste */
kicktx(port); /* es ist was zu senden ! */
decEI(); /* Interrupts w. erlauben */
#ifndef FIRMWARE
istraf[port] = YES; /* es ist Port-Traffic */
#endif
}
else /* nein - Frame einfach sofort */
relink(fbp,stfl.tail); /* als gesendet betrachten */
}
/**************************************************************************\
* *
* "copy frame buffer" *
* *
* Framebuffer, auf den fbp zeigt, komplett mit Inhalt kopieren. Dazu freie *
* Buffer allokieren, Portnummer (l1port) wird kopiert, Bufferzeiger (mbbp) *
* und Getcounter (mbgc) werden nicht kopiert, bleiben aber im Quellframe *
* erhalten. *
* *
* Return : Zeiger auf Kopf des kopierten Framebuffers *
* *
\**************************************************************************/
#ifdef FIRMWARE
MBHEAD *cpyfb(fbp)
MBHEAD *fbp;
{
char *savmbbp; /* mbbp-Sicherung */
unsigned savmbgc; /* mbgc-Sicherung */
MBHEAD *newfbp; /* Zeiger auf die Kopie */
savmbbp = fbp->mbbp; /* mbbp sichern */
savmbgc = fbp->mbgc; /* mbgc sichern */
rwndmb(fbp); /* Quellframe rewinden */
newfbp = allocb(); /* Kopf der Kopie allokieren */
while (fbp->mbgc < fbp->mbpc) /* Daten byteweise kopieren */
putchr(getchr(fbp),newfbp);
newfbp->l2port = fbp->l2port; /* Portnummer kopieren */
fbp->mbbp = savmbbp; /* mbbp wieder auf alten Wert */
fbp->mbgc = savmbgc; /* mbgc wieder auf alten Wert */
return (newfbp); /* Zeiger auf Kopf der Kopie */
}
#endif
/**************************************************************************\
* *
* "take frame head" *
* *
* Adresskopf und Kontrollbyte des Frames aus dem Framebuffer, auf dessen *
* Kopf fbp zeigt, analysieren. Diese Funktion ist die erste, die auf ein *
* empfangenes Frame angewandt wird. *
* *
* *
* Folgende Parameter werden bei der Analyse gesetzt (siehe auch L2V.C) : *
* *
* rxfhdr, rxfV2, rxfPF, rxfCR, rxfctl, rxfprt *
* *
* *
* Folgende Parameter werden nach der Analyse gesetzt fuer ein moegliches *
* Antwortframe : *
* *
* txfhdr = Quell- und Zielcall aus rxfhdr, aber vertauscht, plus *
* reverse via-Liste aus rxfhdr *
* txfV2 = rxfV2 *
* txfPF = rxfPF *
* txfCR = 0, Response ! *
* txfprt = rxfprt *
* *
* *
* Return : TRUE - das Frame hat einen gueltigen AX.25-Framekopf *
* FALSE - sonst *
* *
\**************************************************************************/
BOOLEAN takfhd(fbp)
MBHEAD *fbp;
{
char *viap; /* Zeiger in via-Liste */
char *source; /* Quellzeiger Kopien */
char *dest; /* Zielzeiger Kopien */
rwndmb(fbp); /* Frame von vorne */
if ( !getfid(rxfhdr,fbp) /* Zielcall holen */
|| ((rxfhdr[L2IDLEN - 1] & L2CEOA) != 0) /* (Ende nach 1. Call ?)*/
|| !getfid(rxfhdr + L2IDLEN,fbp) /* Quellcall holen */
) return (FALSE); /* ... schon Fehler */
viap = rxfhdr + L2ILEN; /* ab hier via-Liste */
if (!(rxfhdr[L2ILEN - 1] & L2CEOA)) /* via-Liste da ? */
LOOP
{ /* alle via's */
if (!getfid(viap,fbp)) return (FALSE); /* Call holen */
viap += L2IDLEN; /* naechstes Call */
if ((*(viap - 1) & L2CEOA) != 0) break; /* Ende der Liste */
if (viap >= rxfhdr + L2AFLEN) return (FALSE); /* zu lange Liste */
}
*viap = '\0'; /* Listenende ! */
if (fbp->mbgc == fbp->mbpc) return (FALSE); /* Frame zu kurz */
rxfctl = getchr(fbp); /* Controlbyte */
/* Protokollversion feststellen und danach C/R und P/F festlegen */
if ( (rxfV2 = ((rxfhdr[L2IDLEN - 1] ^ rxfhdr[L2ILEN - 1]) & L2CCR) != 0)
== YES
)
{ /* nur Version 2 : */
rxfCR = rxfhdr[L2IDLEN - 1] & L2CCR; /* Command/Response */
rxfPF = rxfctl & L2CPF; /* Poll/Final */
}
else /* Version 1 : */
rxfPF = rxfCR = 0; /* P/F u. C/R sinnlos */
rxfctl &= ~L2CPF; /* P/F Control loeschen */
rxfprt = fbp->l2port; /* Portnummer holen */
/* Antwort-Sendeframeaufbau */
txfCR = 0; /* Response ! */
txfV2 = rxfV2; /* Version */
txfPF = rxfPF; /* Poll/Final */
txfprt = rxfprt; /* Portnummer */
cpyid(txfhdr,rxfhdr + L2IDLEN); /* TX-Ziel = RX-Quelle */
cpyid(txfhdr + L2IDLEN,rxfhdr); /* TX-Quelle = RX-Ziel */
source = rxfhdr + L2ILEN; /* TX-Antwort-via-Liste */
dest = txfhdr + L2ILEN; /* ist, falls vorhanden */
while (*source != '\0') source += L2IDLEN; /* reverse RX-via-Liste */
while (source != rxfhdr + L2ILEN)
{
source -= L2IDLEN;
cpyid(dest,source);
dest += L2IDLEN;
}
*dest = '\0'; /* Listenende ! */
return (TRUE); /* Frame soweit okay ! */
}
/**************************************************************************\
* *
* "get frame ID" *
* *
* Die naechste ID nach dest (Call + SSID, SSID wie im Frame) holen aus dem *
* Buffer (Call + SSID, beide wie im Frame), auf dessen Kopf mbhd zeigt. *
* Die geholte SSID enthaelt das End-Of-Address-Bit unveraendert. *
* *
* Return : TRUE - die naechste ID (Call + SSID) wurde richtig geholt *
* FALSE - es hat sich ein Fehler ereignet *
* *
\**************************************************************************/
BOOLEAN getfid(dest,mbhd)
char *dest;
MBHEAD *mbhd;
{
char c; /* aktuelles Zeichen aus Buffer */
unsigned n; /* Zaehler Call-Laenge */
if (mbhd->mbpc - mbhd->mbgc < L2IDLEN) /* im Buffer nicht mehr */
return (FALSE); /* genug Bytes fuer ID */
for (n = 0; n < L2CALEN; ++n) /* Call byteweise holen */
{
if (((c = getchr(mbhd)) & L2CEOA) != 0) /* Adressfeld zu frueh */
return (FALSE); /* zuende */
*dest++ = (c >> 1) & 0x7F; /* Framecall -> ASCII */
}
*dest = getchr(mbhd); /* SSID holen, EOA bleibt */
return (TRUE);
}
/**************************************************************************\
* *
* "make frame head" *
* *
* Neues Frame aufbauen aus den txf...-Parametern. Es werden neue Buffer *
* fuer das Frame allokiert, der aktuelle Linkblock (lnkpoi) wird *
* eingetragen und fflag fuer das Frameflag l2fflg. *
* *
* Return : Zeiger auf Framebufferkopf des neu erzeugten Frames *
* *
\**************************************************************************/
MBHEAD *makfhd(fflag)
unsigned fflag;
{
MBHEAD *fbp; /* Zeiger auf Kopf */
if (txfV2 == YES) /* wenn Version 2 ... */
{
txfhdr[L2IDLEN - 1] |= txfCR; /* ... C-Bits setzen */
txfhdr[L2ILEN - 1] |= txfCR ^ L2CCR;
}
putfid(txfhdr,fbp = allocb()); /* neuer Buffer, Ziel */
putfid(txfhdr + L2IDLEN,fbp); /* Quellcall */
putvia(txfhdr + L2ILEN,fbp); /* via-Liste */
putchr(!txfV2 ? txfctl : txfctl | txfPF,fbp); /* Control + P/F */
fbp->l2link = lnkpoi; /* Verweis Linkblock */
fbp->type = 2; /* Level 2 ! */
fbp->l2fflg = fflag; /* Frameflag */
fbp->l2port = txfprt; /* Portnummer */
return (fbp); /* Kopfzeiger zurueck */
}
/**************************************************************************\
* *
* "put via" *
* *
* Nullterminierte via-Liste, auf die idl zeigt, in den Framebuffer, auf *
* dessen Kopf mbhd zeigt, uebertragen. Die Nullterminierung nicht ueber- *
* tragen, aber am Ende der via-Liste das letzte Zeichen der via-Liste mit *
* dem HDLC End-Of-Address-Bit uebertragen. *
* *
\**************************************************************************/
VOID putvia(idl,mbhd)
char *idl;
MBHEAD *mbhd;
{
while (*idl != '\0') /* gesamte via-Liste in den */
{ /* Framebuffer uebertragen */
putfid(idl,mbhd);
idl += L2IDLEN;
} /* dann */
*(mbhd->mbbp - 1) |= L2CEOA; /* EoA direkt im Buffer setzen */
}
/**************************************************************************\
* *
* "put frame id" *
* *
* ID (Call und SSID, SSID wie im Frame), auf die id zeigt, in den *
* Framebuffer, auf dessen Kopf mbhd zeigt, uebertragen. Dabei Call von *
* ASCII in Frameformat (1 Bit linksgeschoben) umwandeln. *
* *
\**************************************************************************/
VOID putfid(id,mbhd)
char *id;
MBHEAD *mbhd;
{
unsigned n; /* Zaehler Call-Laenge */
for (n = 0; n < L2CALEN; ++n) /* Call uebertragen in Buffer, */
putchr(*id++ << 1,mbhd); /* 1 Bit linksgeschoben */
putchr(*id,mbhd); /* SSID unveraendert uebertragen */
}
/**************************************************************************\
* *
* "is to me" *
* *
* Pruefen, ob die ID (Call + SSID, SSID wie im Frame), auf die id zeigt, *
* mit der ID der eigenen Station (myid) uebereinstimmt (SSID wird ohne *
* Steuerbits verglichen), oder ob das Call, auf das id zeigt, mit dem *
* symbolischen Namen (alias) der eigenen Station uebereinstimmt. *
* *
* Return : TRUE - myid stimmt mit id ueberein oder alias mit dem *
* call in id *
* FALSE - sonst *
* *
\**************************************************************************/
BOOLEAN istome(id)
char *id;
{
return (cmpid(myid,id) == TRUE || cmpcal(alias,id) == TRUE);
}
/**************************************************************************\
* *
* "compare calls" *
* *
* Calls miteinander vergleichen. *
* *
* Return : TRUE - die Calls stimmen ueberein *
* FALSE - die Calls stimmen nicht ueberein oder mindestens eins *
* der Calls beginnt mit einem Blank *
* *
\**************************************************************************/
BOOLEAN cmpcal(call1,call2)
char *call1;
char *call2;
{
unsigned n; /* Zaehler */
for (n = 0; n < L2CALEN; ++n) /* jedes Zeichen */
if ( (!n && (*call2 == ' ' || *call1 == ' ')) /* 1. Zeich. ' ' ? */
|| (*call2++ != *call1++) /* sonst gleich ? */
) return (NO); /* nein */
return (YES); /* ja, alle gleich */
}
/**************************************************************************\
* *
* "compare ID list" *
* *
* Nullterminierte ID-Listen (Calls + SSID's, SSID wie im Frame) *
* miteinander vergleichen (SSID nur reine SSID 0-15 vergleichen ohne *
* Steuerbits). *
* *
* Return : TRUE - die ID-Listen stimmen ueberein *
* FALSE - sonst *
* *
\**************************************************************************/
BOOLEAN cmpidl(idl1,idl2)
char *idl1;
char *idl2;
{
while (*idl2 != '\0') /* bis Liste 2 zuende */
{
if (!cmpid(idl1,idl2)) return (NO); /* ID's vergleichen */
idl2 += L2IDLEN; /* Zeiger auf naechste */
idl1 += L2IDLEN; /* ID's */
} /* Listen gleich, wenn */
return (!*idl1); /* beide zuende */
}
/**************************************************************************\
* *
* "compare ID's" *
* *
* ID's (Call + SSID, SSID wie im Frame) miteinander vergleichen (SSID nur *
* reine SSID 0-15 vergleichen ohne Steuerbits). *
* *
* Return : TRUE - die ID's stimmen ueberein *
* FALSE - sonst *
* *
\**************************************************************************/
BOOLEAN cmpid(id1,id2)
char *id1;
char *id2;
{
unsigned n; /* Zaehler */
for (n = 0; n < L2CALEN; ++n) /* Calls vergleichen */
if (*id2++ != *id1++) return (NO);
return ((*id2 & 0x1E) == (*id1 & 0x1E)); /* reine SSID vergl. */
}
/**************************************************************************\
* *
* "copy ID list" *
* *
* Nullterminierte ID-Liste (Calls + SSID's, SSID wie im Frame) von source *
* nach dest kopieren, Zielliste mit '\0' abschliessen. *
* *
\**************************************************************************/
VOID cpyidl(dest,source)
char *dest;
char *source;
{
while (*source != '\0') /* solange Liste nicht zuende */
{
cpyid(dest,source); /* ID kopieren */
source += L2IDLEN; /* Zeiger um eine ID-Laenge */
dest += L2IDLEN; /* weiter */
}
*dest = '\0'; /* Zielliste abschliessen */
}
/**************************************************************************\
* *
* "copy ID" *
* *
* Komplette ID (Call + SSID, SSID wie im Frame), auf die source zeigt, *
* nach dest kopieren. In der kopierten SSID das End-Of-Address-Bit und das *
* Command/Response/Has-Been-Repeated-Bit loeschen. *
* *
\**************************************************************************/
VOID cpyid(dest,source)
char *dest;
char *source;
{
unsigned n; /* Laengenzaehler */
for (n = 0; n < L2CALEN; ++n) /* Call kopieren */
*dest++ = *source++;
*dest = *source & ~(L2CEOA | L2CCR); /* SSID kopieren, Bits loeschen */
}
/**************************************************************************\
* *
* "deallocate message list" *
* *
* Komplette Messageliste, auf deren Listenkopf mlp zeigt, deallokieren. *
* D.h. alle Messagespeicher (jeweils Kopf und daran haengende Datenbuffer) *
* deallokieren. *
* *
* *
* +--------+ +--------+ +--------+ *
* mlp --->| head |--->| |---> --->| |---> mlp *
* +--------+ +--------+ ... +--------+ *
* b <---| tail |<---| |<--- <---| |<--- b *
* +--------+ +--------+ +--------+ *
* | |---> \ | |---> \ *
* + + | + + | *
* | |<--- /| | |<--- /| *
* +--------+ | +--------+ | *
* | | | | | | *
* | | *
* deallokieren |------------------------| *
* siehe unten dealmb() *
* *
\**************************************************************************/
VOID dealml(mlp)
LEHEAD *mlp;
{
MBHEAD *bp; /* Zeiger auf Messagebufferhead */
LOOP /* fuer alle Messagebufferheads */
{ /* in Messagespeicherliste : */
DIinc(); /* Listenkonsistenz ! */
bp = mlp->nextle; /* Zeiger auf naechsten Msgbhead */
decEI(); /* Interrupts wieder erlauben */
if (mlp == bp) break; /* Schwanz beisst Kopf -> fertig */
dealmb(unlink(bp)); /* sonst Messagespeicher deallok. */
}
}
/**************************************************************************\
* *
* "deallocate message buffer" *
* *
* Einen kompletten Messagespeicher, auf dessen Kopf mbhd zeigt, *
* deallokieren, d.h. sowohl den Messagebufferhead als auch alle an dessen *
* Messagebufferliste haengende Datenbuffer deallokieren. *
* *
* *
* +--------+ deallokieren *
* mbhd -->| | *
* +--------+ *
* | | *
* +--------+ +--------+ +--------+ *
* a --->| |----->| |---> --->| |---> a *
* + mbl + +--------+ ... +--------+ *
* b <---| |<-----| |<--- <---| |<--- b *
* +--------+ +--------+ +--------+ *
* | | | | | | *
* *
\**************************************************************************/
VOID dealmb(mbhd)
MBHEAD *mbhd;
{
MB *bp; /* Datenbufferzeiger */
while ((bp = mbhd->mbl.head) != &mbhd->mbl) /* alle Datenbuffer */
dealoc(unlink(bp));
dealoc(mbhd); /* am Ende den Kopf */
}
/**************************************************************************\
* *
* "deallocate" *
* *
* Buffer, auf den bp zeigt, initialisieren als neuen Messagebufferhead *
* (rwndmb()) und deallokieren, d.h. in die Freiliste freel einhaengen und *
* den Freibufferzaehler nmbfre inkrementieren. *
* *
* *
* +--------+ *
* bp --->| | deallokieren *
* +--------+ *
* | | *
* +--------+ *
* | | *
* *
\**************************************************************************/
VOID dealoc(bp)
MBHEAD *bp;
{
bp->mbl.head /* als Messagehead initialisieren */
= bp->mbl.tail /* Bufferlistenkopf */
= &bp->mbl; /* initialisieren */
bp->mbpc = 0; /* Message leer */
rwndmb(bp); /* Rest initialisieren */
DIinc(); /* Listenkonsistenz ! */
relink(bp,freel.tail); /* Buffer an Freiliste anhaengen */
++nmbfre; /* 1 Freibuffer mehr */
decEI(); /* Interrupts wieder erlauben */
}
/**************************************************************************\
* *
* "initialize head" *
* *
* Listenkopf, auf den hd zeigt, initialisieren : *
* *
* *
* +----------------------+ *
* | +------------------+ | *
* | | | | *
* +--------+ v v +--------+ | | *
* hd --->| | -> hd ------->| |-----+ | *
* +--------+ +--------+ | *
* | | | |-------+ *
* +--------+ +--------+ *
* | | | | *
* *
\**************************************************************************/
VOID inithd(hd)
LHEAD *hd;
{
hd->head = hd->tail = hd;
}
/**************************************************************************\
* *
* "level 2 to level x" *
* *
* Meldung msg (L2M...) an Layer 3 und hoehere Layer weitergeben. *
* *
\**************************************************************************/
VOID l2tolx(msg)
unsigned msg;
{
l2tol3(msg); /* Layer 2 -> Layer 3 */
l2tol7(msg,lnkpoi,2); /* Layer 2 -> Layer 7 */
}
/**************************************************************************\
* *
* "uppercase" *
* *
* Zeichen c in Grossbuchstabe umwandeln, wenn Kleinbuchstabe, und *
* zurueckgeben. *
* *
\**************************************************************************/
upcase(c)
char c;
{
return ( ('a' > c || 'z' < c) ? c : c - ('a' - 'A') );
}
/* Ende von L2C.C */