home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 547.TNL7A.C < prev    next >
Text File  |  1988-05-14  |  21KB  |  513 lines

  1. /*****************************************************************************/
  2. /*                                              */
  3. /*                                         */
  4. /*    *****              *****                      */
  5. /*     *****            *****                         */
  6. /*       *****          *****                         */
  7. /*         *****        *****                         */
  8. /*  ***************      ***************                     */
  9. /*  *****************    *****************                     */
  10. /*  ***************      ***************                     */
  11. /*         *****        *****       TheNet                    */
  12. /*       *****          *****       Portable. Compatible.         */
  13. /*     *****            *****       Public Domain             */
  14. /*    *****              *****    NORD><LINK                  */
  15. /*                                         */
  16. /* This software is public domain ONLY for non commercial use                */
  17. /*                                                                           */
  18. /*                                         */
  19. /*****************************************************************************/
  20.  
  21. /* Level 7A, Dataswitch                                 */
  22. /* Version 1.01                                   */
  23. /* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig         */
  24. /* 05-MAY-88                                     */
  25.  
  26. # include "tndef.h"        /* Definition von Konstanten             */
  27. # include "tntyp.h"        /* Definition der Typen                 */
  28. # include "tnl7av.c"        /* Definition Variablen                 */
  29. # include "tnl7ae.h"        /* externe Definitionen                 */
  30.  
  31. /*---------------------------------------------------------------------------*/
  32. char    beades[] = { 'I','D',' ',' ',' ',' ','\140' }; /* Call fuer Bake     */
  33. char    beadil[] = "";                    /* Digiliste fuer Bake   */
  34. char    cqdest[] = { 'C','Q',' ',' ',' ',' ','\140' }; /* Call fuer CQ-Ruf   */
  35. char    cqdil[]  = "";                    /* Digiliste fuer CQ-Ruf */
  36. char    dmmsg[]  = "Busy from ";            /* DM Meldung         */
  37. char    conmsg[] = "Connected to ";            /* Connect Meldung         */
  38. char    signon[] = "TheNet Version 1.01 (";        /* Kopfmeldung         */
  39.  
  40. /*---------------------------------------------------------------------------*/
  41. partyp    partab[] = {        /* Parameter Tabelle                 */
  42.         &maxdes,   1,    400,    /* maximale Laenge der Destination Liste     */
  43.     &worqua,   0,    255,    /* minimale Qualiatet fuer Autoupdate         */
  44.     &ch0qua,   0,    255,    /* HDLC Kanal Qualitaet                 */
  45.     &ch1qua,   0,    255,    /* RS232 Kanal Qualitaet             */
  46.     &obcini,   0,    255,    /* Anfangswert Knotenlebensdauer         */
  47.     &obcbro,   1,    255,    /* min Wert Restlebensdauer fuer Rundspruch  */
  48.     &broint,   0, 0xffff,    /* Rundspruchintervall                 */
  49.     &timliv,   0,    255,    /* Anfangswert Paketlebensdauer             */
  50.     &tratou,   5,    600,    /* Timeout in Level3                 */
  51.     &tratri,   2,    127,    /* Versuche in Level3                 */
  52.     &traack,   1,     60,    /* Level3 Wartezeit bis ACK             */
  53.         &trabsy,   1,   1000,    /* Level3 Busy Wartezeit             */
  54.     &trawir,   1,    127,    /* vorgeschlagene Fenstergroesse in Level3   */
  55.     &conctl,   1,    127,    /* gebufferte Frames je Verbindung         */
  56.     &ininat,   0, 0xffff,    /* no-activity-timeout                 */
  57.     &Ppar,     0,    255,    /* Entschlossenheit fuer Sendung frei        */
  58.     &Wpar,     0,    127,    /* Zeitschlitzbreite                 */
  59.     &Fpar,     1,     15,    /* Level2, Timer1                 */
  60.     &Opar,     1,      7,    /* Level2, Fenstergroesse             */
  61.     &Npar,     0,    127,    /* Level2, Versuche                 */
  62.     &T2par,    0,   6000,    /* Level2, Timer2                 */
  63.     &T3par,    0, 0xffff,    /* Level2, Timer3                 */
  64.     &Rpar,     0,      1,    /* Level2 Digipeating Freigabe             */
  65.     &VCpar,    0,      1,    /* Calls pruefen                 */
  66.     &beacen,   0,      2,    /* Bake ein-aus                     */
  67.     &cqen,     0,      1    /* CQ-Ruf ein-aus                 */
  68.         };
  69.  
  70. /*---------------------------------------------------------------------------*/
  71. cmdtyp    cmdtab[] = {        /* Befehlstabelle                 */
  72.         ccpcm1, ccpcon,
  73.     ccpcm8, ccpcq,
  74.     ccpcm2, ccpide,
  75.     ccpcm3, ccpnod,
  76.     ccpcm4, ccppar,
  77.     ccpcm9, ccprou,
  78.     ccpcm5, ccpres,
  79.     ccpcm6, ccpsys,
  80.     ccpcm7, ccpuse,
  81.     ccpc10, ccphig,
  82.     ccpc11, ccplow,
  83.     0, 0
  84.         };
  85.  
  86. char    ccpcm1[] = "CONNECT";
  87. char    ccpcm8[] = "CQ";
  88. char    ccpcm2[] = "INFO";
  89. char    ccpcm3[] = "NODES";
  90. char    ccpcm4[] = "PARMS";
  91. char    ccpcm9[] = "ROUTES";
  92. char    ccpcm5[] = "RESET";
  93. char    ccpcm6[] = "SYSOP";
  94. char    ccpcm7[] = "USERS";
  95. char    ccpc10[] = "HIGH";
  96. char    ccpc11[] = "LOW";
  97.  
  98. /*---------------------------------------------------------------------------*/
  99. mainf() {            /* Einsprung vom Assembler Teil nach Init    */
  100.   diinc();            /* Interrupts aus                 */
  101.   inivar();            /* Variable initialisieren             */
  102.   initl4();            /* Level 4      "                 */
  103.   l3init();            /* Level 3      "                 */
  104.   l2init();            /* Level 2      "                     */
  105.   hosini();            /* Hostinterface initialisieren             */
  106.   srand();            /* Zufallsgenerator initialisieren         */
  107.   decei();            /* Interrupts wieder an                 */
  108.   bstrng("\015\012");
  109.   bstrng(signon);        /* melden                     */
  110.   bcalou(myid);            /* eigenes Call                     */
  111.   bstrng(")\015\012");
  112.   bstrng("by NORD><LINK (DF2AU/DC4OX)\015\012\012");
  113.  
  114.   loop:                /* ewige Schleife                 */
  115.     hostsv();            /* Hostinterface                 */
  116.     l2();            /* Level 2                     */
  117.     l3serv();            /* Level 3                     */
  118.     l4serv();            /* Level 4                     */
  119.     timsrv();            /* Timerservice                     */
  120.     goto loop;
  121.   }
  122.  
  123. /*---------------------------------------------------------------------------*/
  124. VOID    inivar()        /* Variable initialisieren             */
  125.   {
  126.   unsigned cnt;            /* Scratch Zaehler                 */
  127.   char     *chaptr;        /* fuer Passwort kopieren             */
  128.  
  129.   inithd(&usccpl);        /* CCP User Liste initialisieren         */
  130.   inithd(&userhd);        /* User Liste initialisieren             */
  131.  
  132.   for (cnt = 0, ptcrdp = ptcrdl;/* Patchcordliste aufbauen             */
  133.        cnt < NUMPAT; ++cnt, ++ptcrdp) {
  134.     ptcrdp->luserl = 0;        /* kein Kontrollblock                 */
  135.     }
  136.   tic10 =            /* loeschen: 10ms Timer                 */
  137.   lastic =            /* letzte Ablesung bei 0             */
  138.   tic1s =            /* Sekundenzaehler                 */
  139.   beatim = 0;            /* Bakenuhr                     */
  140.  
  141.   if (!iswarm()) {        /* nur im Kaltstart                 */
  142.     Ypar   = MAXL2L;        /* maximal Links in Level2             */
  143.     Tpar   = defTp;        /* Senderverzoegerung                 */
  144.     Ppar   = DEFPER;        /* Persistance                     */
  145.     Wpar   = DEFSLO;        /* Zeitscheibengroesse                 */
  146.     Fpar   = DEFRAK;        /* Level2 FRACK                     */
  147.     Opar   = DEFMAF;        /* Fenstergroesse in Level2             */
  148.     Npar   = DEFL2T;        /* Versuche in Level2                 */
  149.     T2par  = DEFLT2;        /* Level2 Timer 2                 */
  150.     T3par  = DEFLT3;        /* Level2 Timer 3                 */
  151.     Rpar   = DEFRPA;        /* Level2 Digipeating                 */
  152.     Vpar   = DEFL2L;        /* Level2 Protokollversion             */
  153.     Dpar   = DEFDPA;        /* Full-Duplex                     */
  154.     xFpar  = DEFXFP;        /* Full-Duplex mit Flags             */
  155.     ininat = DEFNOA;        /* no-activity-timeout                 */
  156.     conctl = DEFCON;        /* Frames im Buffer je Link             */
  157.     beacen = DEFBEA;        /* Bakenform                     */
  158.  
  159.     paswle = 0;            /* Passwort aus Eprom kopieren             */
  160.     chaptr = &DEFPWD[0];
  161.     while (*chaptr != 0)
  162.      {
  163.       paswrd[paswle++] = *chaptr++;
  164.      }
  165.  
  166.     infmsg[0] = 0;        /* keine Info-Message                 */
  167.     cpyid(myid, DEFCAL);    /* Call setzen                     */
  168.     cpy6ch(alias, DEFIDE);    /* Ident setzen                     */
  169.     VCpar  = DEFVAL;        /* Call pruefen                     */
  170.     cqen   = DEFCQ;        /* CQ-Ruf erlaubt                 */
  171.     }
  172.   }
  173.  
  174. /*---------------------------------------------------------------------------*/
  175. VOID    timsrv()        /* zeitabhaengige Funktionen             */
  176.   {
  177.   char       *usnxtc;        /* naechstes Zeichen im Frame             */
  178.   char       *cmdnam;        /* Befehlsname                     */
  179.   unsigned zeit;        /* Zeit in 10ms seit letztem Service         */
  180.   unsigned usget;        /* Getcount                     */
  181.   unsigned cnt;            /* Scratch Zaehler                 */
  182.   unsigned zeichen;        /* Scratch fuer gelesene Zeichen         */
  183.   mhtyp       *mhdp;        /* Pointer auf aktuelles Frame             */
  184.   mhtyp       *usrmhd;        /* User MBHD Kopie                 */
  185.   cmdtyp   *cmdpoi;        /* Pointer in Befehlstabelle             */
  186.  
  187.   diinc();            /* Interrupts aus                 */
  188.   zeit = tic10 - lastic;    /* vergangene Zeit seit letztem Service         */
  189.   lastic = tic10;        /* neuen Nullpunkt merken             */
  190.   decei();            /* Interrupts wieder frei             */
  191.  
  192.   if (zeit != 0)        /* nicht zu oft...                 */
  193.     {
  194.       l2timr(zeit);        /* an Level2 melden                 */
  195.       if ((tic1s +=zeit) >= 100)    /* alle Sekunde:             */
  196.         {
  197.           tic1s -=100;        /* Uebertrag merken                 */
  198.           hostim();        /* Hostinterface                 */
  199.           chknoa();        /* Nichtstuer ueberwachen             */
  200.           brosrv();        /* Rundsprueche                     */
  201.           trasrv();        /* Level3 und Level4 Service             */
  202.           beacon();        /* Bake                         */
  203.         }
  204.     }
  205.  
  206. /*=== eingelaufene Info Frames fuer den CCP verarbeiten              ===*/
  207.   while ((mhdp = (mhtyp *) userhd.lnext) != (mhtyp *) &userhd.lnext)
  208.    {                                             /* Info Frames fuer CCP     */
  209.     unlink(mhdp);        /* Info aushaengen                 */
  210.  
  211.     for (userpo = (usrtyp *) usccpl.lnext;    /* User zur Info suchen         */
  212.         (usrtyp *) &usccpl != userpo;            /* gesamte Liste absuchen    */
  213.          userpo = userpo->unext) {
  214.       if ((mhdp->usrtyp == userpo->typ_u) /* Usertyp und Kontrollblock         */
  215.         && (mhdp->l2lnk == userpo->cblk_u)) /* muessen passen             */
  216.           break;        /* dann gefunden                 */
  217.       }
  218.  
  219.     if ((usrtyp *) &usccpl == userpo) {    /* kein User gefunden             */
  220.       userpo = (usrtyp *) allocb();    /* dann ist es ein neuer Teilnehmer  */
  221.       userpo->mbhd = 0;        /* keine Info wartend                 */
  222.       userpo->sysflg = ! (userpo->typ_u = mhdp->usrtyp); /* Typ setzen         */
  223.       userpo->cblk_u = mhdp->l2lnk; /* Kontrollblock setzen             */
  224.       userpo->errcnt = 0;    /* bisher keine Fehler                 */
  225.       userpo->status = 1;    /* am CCP, Befehl kommt                 */
  226.       relink(userpo, usccpl.lprev); /* User in Kette haengen             */
  227.       }
  228. /*=== eingelaufene Info Frames fuer User verarbeiten              ===*/
  229.     if (!(usrmhd = userpo->mbhd))
  230.       userpo->mbhd = mhdp;
  231.     else {
  232.       usnxtc = usrmhd->nxtchr;
  233.       usget = usrmhd->getcnt;
  234.       while (usrmhd->getcnt < usrmhd->putcnt)
  235.         getchr(usrmhd);
  236.       while (mhdp->getcnt < mhdp->putcnt)
  237.         putchr(getchr(mhdp), usrmhd);
  238.       usrmhd->nxtchr = usnxtc;
  239.       usrmhd->getcnt = usget;
  240.       dealmb(mhdp);
  241.       }
  242.     while ((userpo != 0)    /* existiert der User noch?             */
  243.       && ((mhdp = userpo->mbhd) != 0) /* ist Info da?                 */
  244.       && (getlin(mhdp) == 1)) {    /* ist es mindestens eine ganze Zeile?         */
  245.        clipoi = clilin;        /* Zeile als leer definieren             */
  246.        clicnt = 0;
  247.       while ((mhdp->getcnt < mhdp->putcnt) /* so lange Zeichen vorhanden sind*/
  248.         && ((zeichen = getchr(mhdp) & 0x7f) != 0x0d)) { /* und kein <CR>     */
  249.         if ((zeichen == 0x08) || (zeichen == 0x7f)) { /* Backspace         */
  250.           if (clicnt != 0) {    /* und Delete aussortieren             */
  251.             --clipoi;
  252.             --clicnt;
  253.             }
  254.           }
  255.         else {
  256.           if ((zeichen != 0x0a) /* Linefeed zaehlt nicht mit             */
  257.             && (clicnt < 80)) {    /* Zeilenueberlauf beachten             */
  258.             *clipoi++ = zeichen;/* Zeichen merken                 */
  259.             ++clicnt;        /* mitzaehlen                     */
  260.             }
  261.           }
  262.         }
  263.       if (mhdp->getcnt == mhdp->putcnt) { /* wenn nun alle Zeichen verbraucht*/
  264.         dealmb(mhdp);        /* Buffer wieder freigeben             */
  265.         userpo->mbhd = 0;    /* und "keine Info mehr da" markieren         */
  266.         }
  267.  
  268. /*=== Zeile vom User auswerten                          ===*/
  269.       clipoi = clilin;        /* zum Auswerten Pointer nach vorn         */
  270.       if (userpo->status == 3) { /* warten auf Passwort?             */
  271.         for (cnt = 0; cnt < 5; ++cnt) { /* 5 Zeichen als Antwort         */
  272.           if (skipsp(&clicnt, &clipoi) == 0) /* noch was da?             */
  273.             break;        /* nein, dann Ende                 */
  274.           zeichen = *clipoi++;    /* sonst Zeichen holen                 */
  275.           --clicnt;
  276.           if (paswrd[userpo->paswrd[cnt] & 0xff] != zeichen) /* stimmt?      */
  277.             break;
  278.           }
  279.         if (cnt == 5)        /* 5 Richtige?                     */
  280.           userpo->sysflg = 1;
  281.         userpo->status = 1;    /* neuer Status: warten auf Befehl         */
  282.         }
  283.       else {
  284.  
  285.         if (userpo->status == 2) { /* warten auf Connect?             */
  286.           disusr(userpo->cblk_p, userpo->typ_p); /* dann beenden         */
  287.           userpo->status = 1;    /* neuer Status: warten auf Befehl         */
  288.           }
  289.  
  290.         if (skipsp(&clicnt, &clipoi) == 1) { /* noch was in der Zeile?         */
  291.           usnxtc = clipoi;
  292.           usget = clicnt;    /* Position in der Zeile merken             */
  293.           for (cmdpoi = cmdtab;    /* Eingabe mit Tabelle vergleichen         */
  294.                cmdpoi->cmdstr != 0; /* Ende ist NULL                 */
  295.                ++cmdpoi) {
  296.             clipoi = usnxtc;
  297.             clicnt = usget;    /* fuer jeden Test auf Zeilenanfang         */
  298.             cmdnam = cmdpoi->cmdstr;
  299.             while ((clicnt != 0) && (*clipoi != ' ')) {
  300.               if (upcase(*clipoi) != *cmdnam) break; /* Abbruch bei ungleich */
  301.               ++clipoi;
  302.               --clicnt;
  303.               ++cmdnam;
  304.               }
  305.             if ((clicnt == 0) || (*clipoi == ' ')) break; /* passt das Wort? */
  306.             }
  307.           if (cmdpoi->cmdfun != 0) { /* auf Tabellenende gelaufen?         */
  308.             userpo->errcnt = 0;    /* nein, Fehlerzaehler ruecksetzen         */
  309.             skipsp(&clicnt, &clipoi); /* vorruecken auf Argument         */
  310.             (*cmdpoi->cmdfun)(); /* Befehl ausfuehren                 */
  311.             }
  312.           else {
  313.          putmsg("Invalid Command (CONNECT CQ INFO NODES ROUTES USERS)");
  314.             if (++userpo->errcnt == 5) { /* Fehler zaehlen             */
  315.               disusr(userpo->cblk_u, userpo->typ_u);
  316.               kilusr();        /* zuviel Mist? Rauswerfen             */
  317.   } } } } } } }
  318.  
  319. /*---------------------------------------------------------------------------*/
  320. VOID    l2tol7(opcod, link, typ)/* auf S-Frame reagieren             */
  321. unsigned opcod;            /* Frametyp: 1=UA, 2=DISC, 3=DM, 4=?         */
  322. ctyp     *link;            /* Kontrollblock                 */
  323. unsigned typ;            /* User Typ                     */
  324.   {
  325.   unsigned cnt;            /* Scratch Zaehler                 */
  326.  
  327.   if (opcod < 5) {        /* zulaessiger Frametyp?             */
  328.  
  329.     if (opcod == 1) {        /* UA Frame                     */
  330.       for (userpo = (usrtyp *) usccpl.lnext;    /* User in CCP-Liste suchen  */
  331.            (usrtyp *) &usccpl != userpo;
  332.            userpo = userpo->unext) {
  333.         if ((userpo->status == 2) /* Status des Users: "SABM gegeben"?         */
  334.           && (userpo->typ_p == typ) /* Partner muss erwarteter Typ sein         */
  335.           && (userpo->cblk_p == (l2ltyp *) link)){ /* Kontrollblock passt?   */
  336.           msgfrm('D', link, typ, conmsg); /* Erfolg melden             */
  337.           for (ptcrdp = ptcrdl;    /* Platz in Patchcordliste suchen         */
  338.                ptcrdp->luserl != 0;
  339.                ptcrdp += 2);
  340.           ptcrdp->luserl = userpo->cblk_u; /* beide User eintragen         */
  341.           ptcrdp->lusert = userpo->typ_u;  /* Kontrollblock und Typ         */
  342.           (++ptcrdp)->luserl = (l2ltyp *) link;
  343.           ptcrdp->lusert = typ;
  344.           kilusr();        /* User aus Level7 entfernen             */
  345.           break;
  346.           }
  347.         }
  348.       return;            /* fertig                     */
  349.       }
  350.     for (cnt = 0, ptcrdp = ptcrdl; /* DISC oder DM erhalten             */
  351.          cnt < NUMPAT;        /* Patchcordliste nach User absuchen         */
  352.          ++cnt, ++ptcrdp)
  353.      {
  354.       if ((ptcrdp->lusert == typ)
  355.         && (ptcrdp->luserl == (l2ltyp *) link))
  356.        {
  357.         ptcrdp->luserl = 0;    /* Eintrag loeschen                 */
  358.         cnt ^= 1;           /* auf andere Seite der Verbindung         */
  359.         ptcrdp = &ptcrdl[cnt];
  360.         disusr(ptcrdp->luserl, ptcrdp->lusert);    /* Partner             */
  361.         ptcrdp->luserl = 0;            /* Eintrag loeschen         */
  362.         return;                    /* fertig             */
  363.        }
  364.      }
  365.     for (userpo = (usrtyp *) usccpl.lnext;    /* muss CCP User sein         */
  366.          (usrtyp *) &usccpl != userpo;    /* Tabelle absuchen             */
  367.          userpo = userpo->unext) {
  368.       if ((userpo->typ_u == typ)
  369.         && (userpo->cblk_u == (l2ltyp *) link)) {
  370.         if (userpo->status == 2) /* User hat Connect gefordert?             */
  371.           disusr(userpo->cblk_p, userpo->typ_p); /* Partner abwerfen         */
  372.         kilusr();        /* und User selbst abwerfen             */
  373.         return;            /* fertig                     */
  374.         }
  375.       if (userpo->status == 2) { /* User hat Connect gefordert             */
  376.         if ((userpo->typ_p == typ) /* und Antwort kam vom Partner         */
  377.         && (userpo->cblk_p == (l2ltyp *) link)) {
  378.           msgfrm('D', link, typ, ((opcod == 3)? dmmsg : "Failure with "));
  379.           userpo->status = 1;    /* neuer Status ist "warten auf Befehl"         */
  380.           return;
  381.         } }
  382.       }
  383.     }
  384.   }
  385.  
  386. /*---------------------------------------------------------------------------*/
  387. VOID    disusr(link, typ)    /* User abwerfen                 */
  388. ctyp     *link;            /* Kontrollblock                 */
  389. unsigned typ;            /* User Typ                     */
  390.   {
  391.   l2ltyp *cblk2;        /* Kopien der Kontrollblockpointer         */
  392.   cirtyp *cblk4;
  393.   hustyp *cblk0;
  394.  
  395.   switch(typ)
  396.    {
  397.     case 4:            /* Circuit?                     */
  398.      cblk4 = cirpoi;
  399.      cirpoi = (cirtyp *) link;
  400.      discir();
  401.      cirpoi = cblk4;
  402.      break;
  403.  
  404.     case 2:            /* Level2?                     */
  405.      cblk2 = lnkpoi;
  406.      lnkpoi = (l2ltyp *) link;
  407.      dsclnk();
  408.      lnkpoi = cblk2;
  409.      break;
  410.  
  411.  
  412.     default:            /* Host                         */
  413.      cblk0 = hstusr;
  414.      hstusr = (hustyp *) link;
  415.      hstout();
  416.      hstusr = cblk0;
  417.    }
  418.   }
  419.  
  420. /*---------------------------------------------------------------------------*/
  421. BOOLEAN    fmlink(conflg, bufpoi)    /* Frame an User weiterreichen             */
  422. mhtyp    *bufpoi;        /* Info                         */
  423. BOOLEAN    conflg;            /* Congestion Flag                 */
  424.   {
  425.   unsigned cnt;            /* Scratch Zaehler                 */
  426.  
  427.   for (cnt = 0, ptcrdp = ptcrdl; /* Patchcordliste absuchen             */
  428.        cnt < NUMPAT;        /* ob User connected ist zu Partner         */
  429.        ++cnt, ++ptcrdp)
  430.    {
  431.     if ((bufpoi->usrtyp == ptcrdp->lusert) /* Usertyp                 */
  432.      && (bufpoi->l2lnk == ptcrdp->luserl)) /* und Kontrollblock gleich?         */
  433.      {
  434.       cnt ^= 1;           /* auf andere Seite der Verbindung         */
  435.       ptcrdp = &ptcrdl[cnt];
  436.       bufpoi->l2lnk = ptcrdp->luserl; /* Kontrollblock des Pratners eintragen*/
  437.       switch (ptcrdp->lusert)
  438.        {
  439.         case 4:                    /* User ist Circuit?         */
  440.         return(itocir(conflg, bufpoi));
  441.  
  442.         case 2:                    /* User ist Level2?         */
  443.         return(itolnk(conflg, bufpoi));
  444.  
  445.         default:
  446.         return(hstrec(conflg, bufpoi));        /* User ist Host         */
  447.        }
  448.       }
  449.     }
  450.   relink(unlink(bufpoi), userhd.lprev);        /* User ist im CCP         */
  451.   return(TRUE);
  452.   }
  453.  
  454. /*---------------------------------------------------------------------------*/
  455. VOID    seteom(bufpoi)        /* Ende Kennung an Frame anhaengen         */
  456. mhtyp    *bufpoi;
  457.   {
  458.   mhtyp       *mbhd;
  459.  
  460.   putchr('\015', bufpoi);        /* Zeilenende                 */
  461.   rwndmb(bufpoi);            /* alle Pointer auf Null         */
  462.   inithd(&mbhd);
  463.   relink(bufpoi, &mbhd);
  464.   switch (bufpoi->usrtyp)
  465.    {
  466.     case 4:                /* User ist Circuit             */
  467.      itocir(1, bufpoi);
  468.      break;
  469.  
  470.     case 2:                /* User ist Level2             */
  471.      itolnk(1, bufpoi);
  472.      break;
  473.  
  474.     default:                /* User ist Host             */
  475.      hstrec(1, bufpoi);
  476.  
  477.    }
  478.   }
  479.  
  480. /*---------------------------------------------------------------------------*/
  481. VOID    beacon()        /* Bakenservice                     */
  482.   {
  483.   unsigned kanal;        /* Kanal fuer Sendung                 */
  484.   mhtyp       *bufpoi;        /* Buffer fuer Frame                 */
  485.  
  486.   if ((beacen != 0) && (nmbfre > 128)) { /* Bake frei und Platz?         */
  487.     if (++beatim >= 600) {    /* alle 10 min                     */
  488.       beatim = 0;
  489.       (bufpoi = (mhtyp *) allocb())->pid = 0xf0; /* Buffer beschaffen         */
  490.       putstr("TheNet 1.0", bufpoi); /* Meldung in Buffer             */
  491.       if (alias[0] != ' ') {    /* Ident definiert?                 */
  492.         putstr(" (", bufpoi);
  493.         putcal(alias, bufpoi);    /* dann Ident auch in Buffer             */
  494.         putchr(')', bufpoi);
  495.         }
  496.       putchr('\015', bufpoi);    /* Frame schliessen                 */
  497.  
  498.       for (kanal = 0; kanal < 2; ++kanal) /* auf beide Kanaele geben         */
  499.        {
  500.         if ((beacen == 2) || (istraf[kanal] == 1))
  501.          {
  502.           rwndmb(bufpoi);        /* alle Pointer auf Null         */
  503.           sdui(beadil, beades, myid, kanal, bufpoi); /* als UI senden         */
  504.           istraf[kanal] = 0;        /* Bake fuer diesen Kanal erledigt   */
  505.          }
  506.        }
  507.       dealmb(bufpoi);        /* Buffer wieder freigeben             */
  508.       }
  509.     }
  510.   }
  511.  
  512. /*--- Ende Level 7a ---------------------------------------------------------*/
  513.