home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 524.L2B.C < prev    next >
Text File  |  1988-05-14  |  40KB  |  793 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2B.C   -   Level 2, Teil 2                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:                                                          *
  22. *                                                                          *
  23. \**************************************************************************/
  24.  
  25.  
  26.  
  27.  
  28.  
  29. /*                                                             Includes   */
  30. /**************************************************************************/
  31.  
  32. #include "all.h"         /* allgemeine Festlegungen                       */
  33. #include "l2.h"          /* Festlegungen/Datenstrukturen fuer den Level 2 */
  34. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  35. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  36.  
  37.  
  38.  
  39.  
  40.  
  41. /**************************************************************************\
  42. *                                                                          *
  43. * "check no activity"                                                      *
  44. *                                                                          *
  45. * Alle aktiven Links (lnktbl, Linkstatus "Information Transfer") auf       *
  46. * "keine Aktivitaet" abtesten. Ist der Keine-Aktivitaet-Timer aktiv (!= 0) *
  47. * und nach Dekrementieren abgelaufen, Disconnect einleiten.                *
  48. *                                                                          *
  49. * ACHTUNG: Diese Funktion muss sekuendlich aufgerufen werden,              *
  50. *          wird aber nur fuer TheNet benoetigt.                            *
  51. *                                                                          *
  52. \**************************************************************************/
  53.  
  54. #ifndef FIRMWARE
  55.  
  56. VOID chknoa()
  57.   {
  58.     unsigned n;
  59.     
  60.     for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
  61.       if (lnkpoi->state >= L2SIXFER)
  62.         if (lnkpoi->noatou != 0 && !(--lnkpoi->noatou)) disc();
  63.   }
  64.  
  65. #endif
  66.  
  67.  
  68.  
  69.  
  70.  
  71. /**************************************************************************\
  72. *                                                                          *
  73. * "new link"                                                               *
  74. *                                                                          *
  75. * Link (lnkpoi) neu aufbauen. Wenn Link noch nicht aktiv war, die Anzahl   *
  76. * aktiver Links (nmblks) erhoehen.                                         *
  77. *                                                                          *
  78. \**************************************************************************/
  79.  
  80. VOID newlnk()
  81.   {
  82.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  83.     setiT1();                           /* FRACK-Timer neu starten        */
  84.     txfV2 = lnkpoi->V2link;             /* welche Protokollversion        */
  85.     xsabm();                            /* SABM senden                    */
  86.     if (lnkpoi->state == L2SDSCED)      /* neuer Link ?                   */
  87.       ++nmblks;                         /* ja ...                         */
  88.     lnkpoi->state = L2SLKSUP;           /* Linkstatus "Link Setup"        */
  89.   }
  90.  
  91.  
  92.  
  93.  
  94.  
  95. /**************************************************************************\
  96. *                                                                          *
  97. * "disconnect link"                                                        *
  98. *                                                                          *
  99. * Disconnect-Wunsch an aktuellen Link (lnkpoi) :                           *
  100. *                                                                          *
  101. *   Linkstatus "Disconnected"                                              *
  102. *   -> Ax.25-Parameter "frisch"                                            *
  103. *                                                                          *
  104. *   Linkstatus "Link Setup" oder "Disconnect Request"                      *
  105. *   -> Link aufloesen, neuer Linkstatus "Disconnected"                     *
  106. *                                                                          *
  107. *   sonst                                                                  *
  108. *   -> Empfangsinfoframeliste loeschen, Linkstatus bleibt, Flag "nach      *
  109. *      Loswerden aller zu sendenden Infoframes disconnecten" setzen        *
  110. *                                                                          *
  111. \**************************************************************************/
  112.  
  113. VOID dsclnk()
  114.   {
  115.     unsigned lstate;
  116.  
  117.     if (!(lstate = lnkpoi->state))                     /* Disced, nur     */
  118.       inilbl();                                        /* AX-Pars neu     */
  119.     else
  120.       if (lstate == L2SLKSUP || lstate == L2SDSCRQ)    /* Linksetup oder  */
  121.         {                                              /* Discreq,        */
  122.           clrlnk();                                    /* Link aufloesen  */
  123.           lnkpoi->state = L2SDSCED;                    /* Diconnected !   */
  124.         }
  125.       else
  126.         {                                              /* sonst           */
  127.           dealml(&lnkpoi->rcvdil);                     /* RX-Infoframe-   */
  128.           lnkpoi->rcvd = 0;                            /* loeschen und    */
  129.           lnkpoi->flag |= L2FDSLE;                     /* Flag, s.o.      */
  130.         }
  131.   }
  132.  
  133.  
  134.  
  135.  
  136.  
  137. /**************************************************************************\
  138. *                                                                          *
  139. * "information to link"                                                    *
  140. *                                                                          *
  141. * Infobuffer, auf den imbp zeigt, an in diesem Buffer festgelegten Link    *
  142. * (l2link) zwecks Aussendung als Paket weitergeben. Wenn nocgnc == YES     *
  143. * keine "Erstickungskontrolle", sonst conctl beachten (s.u.).              *
  144. * Der Infobuffer wird bei Weitergabe an den Link mit der normalen Level 2  *
  145. * PID versehen, der Keine-Aktivitaets-Timer wird neu gestartet.            *
  146. *                                                                          *
  147. * Return:  TRUE  - imbp wurde angenommen und an den Link weitergegeben     *
  148. *          FALSE - imbp wurde nicht angenommen wegen Congestion Control    *
  149. *                  = Grenze der pro Link maximal zu speichernden Pakete    *
  150. *                    (conctl) wuerde ueberschritten werden                 *
  151. *                                                                          *
  152. \**************************************************************************/
  153.  
  154. BOOLEAN itolnk(nocgnc,imbp)
  155.  
  156. BOOLEAN    nocgnc;                      /* "no congestion control"        */
  157. MBHEAD    *imbp;                        /* "I message buffer pointer"     */
  158.  
  159.   {
  160.     LNKBLK *linkp;
  161.  
  162.     if ((linkp = imbp->l2link)->tosend < conctl || nocgnc == YES)
  163.       {
  164.         imbp->l2fflg = L2CPID;                    /* Standard-L2-PID      */
  165.         relink(unlink(imbp),linkp->sendil.tail);  /* -> ab in den Link    */
  166.         ++linkp->tosend;                          /* ein Sendepaket mehr  */
  167.         linkp->noatou = ininat;                   /* wieder Aktivitaet    */
  168.         return (TRUE);                            /* ... imbp angenommen  */
  169.       }
  170.     return (FALSE);                               /* ... imbp abgelehnt   */
  171.   }
  172.  
  173.  
  174.  
  175.  
  176.  
  177. /**************************************************************************\
  178. *                                                                          *
  179. * "digipeat"                                                               *
  180. *                                                                          *
  181. * Framebuffer, auf den fbp zeigt, abtesten, ob er ein zu digipeatendes     *
  182. * Paket enthaelt. Wenn ja, Paket an den entsprechenden Port (falls ein     *
  183. * bekannter Nachbarknoten direkt in der Digiliste folgt oder nach          *
  184. * kompletten Digipeaten das Ziel ist, kann das Paket auch auf einem        *
  185. * anderen als dem normalen HDLC-Port digipeatet werden) ausgeben.          *
  186. * Das Paket muss schon durch takfhd() analysiert sein, die rxf...-         *
  187. * Parameter muessen gesetzt sein.                                          *
  188. *                                                                          *
  189. * Return:  YES - das Frame wurde entweder digipeatet, oder der             *
  190. *                Framebuffer wurde deallokiert, weil das Frame noch von    *
  191. *                einer anderen Station digipeatet werden muss oder ich     *
  192. *                nicht digipeaten darf                                     *
  193. *          NO  - das Frame muss nicht mehr digipeated werden, hat alle     *
  194. *                noetigen Digipeater durchlaufen, ist zur Auswertung frei  *
  195. *                                                                          *
  196. \**************************************************************************/
  197.  
  198. BOOLEAN digipt(fbp)
  199.  
  200. MBHEAD *fbp;
  201.  
  202.   {
  203.     char       *viap;                             /* Zeiger in via-Liste  */
  204.     unsigned    n;                                /* Zaehler              */
  205.     
  206.     viap = rxfhdr + L2ILEN;                       /* Anfang via-Liste     */
  207.     while (*viap != '\0')                         /* via-Liste durchgehen */
  208.       {
  209.         if (!(viap[L2IDLEN - 1] & L2CH))          /* zu digipeaten ?      */
  210.           {
  211.             if (Rpar == YES && istome(viap) == TRUE)   /* ja, darf ich    */
  212.               {                                        /* und muss ich :  */
  213.                 rwndmb(fbp);                           /* Zeiger auf Hbit */
  214.                 n = (unsigned)(viap - (rxfhdr+L2ILEN) + (L2ILEN+L2IDLEN));
  215.                 while (n-- != 0) getchr(fbp);          /* berechnen       */
  216.                 *(fbp->mbbp - 1) |= L2CH;              /* Hbit setzen     */
  217.                 viap += L2IDLEN;                       /* Nachbardigi     */
  218.                 fbp->l2port = nbrprt(   *viap != '\0'  /* ich letzter ?   */
  219.                                       ? viap           /* nein, Port Digi */
  220.                                       : rxfhdr);       /* ja, Port Ziel   */
  221.                 fbp->l2fflg = 0;                       /* kein Linkframe  */
  222.                 sdl2fr(fbp);                           /* Frame senden    */
  223.               }
  224.             else              /* Frame ist noch nicht komplett digipeatet */
  225.               dealmb(fbp);    /* und/oder nix fuer mich, Frame wegwerfen  */
  226.             return (YES);     /* fuer aufrufende Funk.: Frame ist weg !   */
  227.           }
  228.         viap += L2IDLEN;      /* naechsten Digi in Digiliste untersuchen  */
  229.       }
  230.     return (NO);              /* fuer aufrufende Funk.: Frame auswerten ! */
  231.   }
  232.  
  233.  
  234.  
  235.  
  236.  
  237. /**************************************************************************\
  238. *                                                                          *
  239. * "to level 3 switch"                                                      *
  240. *                                                                          *
  241. * Aus I- oder UI-Frame (Framekopf fbp, Getzeiger/Zaehler auf 1. Byte       *
  242. * hinter Level-2-Adressfeld) PID holen, falls vorhanden. Falls es nicht    *
  243. * Level-2-PID ist, das Paket an die Level-3-Empfangsframeliste l3rxfl      *
  244. * haengen. Im Framekopf wird in jedem Fall l2fflg auf PID, wenn vorhanden, *
  245. * oder 0 gesetzt, l2link auf den aktuellen Link (lnkpoi).                  *
  246. *                                                                          *
  247. * Return:  YES - das I/UI-Frame hat ein Nicht-Level-2-PID und wurde an die *
  248. *                Level-3-Empfangsframeliste gehaengt                       *
  249. *          NO  - Frame hat Standard-Level-2-PID                            *
  250. *                                                                          *
  251. \**************************************************************************/
  252.  
  253. BOOLEAN tol3sw(fbp)
  254.  
  255. MBHEAD *fbp;
  256.  
  257.   {
  258.     fbp->l2fflg = fbp->mbgc < fbp->mbpc ? getchr(fbp) : 0; /* PID holen   */
  259.     fbp->l2link = lnkpoi;                                  /* Linkzeiger  */
  260.     if ((fbp->l2fflg & 0xFF) != L2CPID)
  261.       {                                 /* wenn nicht L2-Frame, Frame an  */
  262.         relink(fbp,l3rxfl.tail);        /* Level 3 weiterreichen          */
  263.         return (YES);                   /* Meldung, dass weitergereicht   */
  264.       }
  265.     return (NO);                        /* Meldung, dass Level-2-Frame    */
  266.   }
  267.  
  268.  
  269.  
  270.  
  271.  
  272. /**************************************************************************\
  273. *                                                                          *
  274. * "level 2 information to level x"                                         *
  275. *                                                                          *
  276. * Infopakete aus dem aktuellen Link (lnkpoi) an hoehere Level weiter-      *
  277. * reichen. nocgnc gibt an, ob der hoehere Level die "Erstickungskontrolle" *
  278. * (hier = Beruecksichtigung der maximal noch anzunehmenden I-Pakete)       *
  279. * machen soll (NO) oder in jedem Fall alle uebermittelten I-Pakete         *
  280. * annehmen muss (YES). Falls die I-Pakete vom hoeheren Level angenommen    *
  281. * wurden, Empfangszaehler rcvd und Aktivitaetstimer noatou entsprechend    *
  282. * updaten. Es wird l2link in den Framekoepfen der weitergereichten Pakete  *
  283. * auf lnkpoi gesetzt und type auf 2 fuer "Level 2".                        *
  284. *                                                                          *
  285. \**************************************************************************/
  286.  
  287. VOID i2tolx(nocgnc)
  288.  
  289. unsigned nocgnc;
  290.  
  291.   {
  292.     MBHEAD *rcvdip;      /* Zeiger auf Framekopf weiterzureichendes I     */
  293.  
  294.     while (lnkpoi->rcvd != 0)           /* solange I's aus Link vorhanden */
  295.       {
  296.         (rcvdip = lnkpoi->rcvdil.head)->l2link = lnkpoi;    /* Linkzeiger */
  297.         rcvdip->type = 2;                                   /* Level 2 !  */
  298.         if (!fmlink(nocgnc,rcvdip))     /* I an hoeheren Level geben      */
  299.           return;                       /* Abbruch, wenn nicht angenommen */
  300.         lnkpoi->noatou = ininat;        /* angenommen, wieder Aktivitaet  */
  301.         --lnkpoi->rcvd;                 /* Empfangspaketezaehler updaten  */
  302.       }
  303.   }
  304.  
  305.  
  306.  
  307.  
  308.  
  309. /**************************************************************************\
  310. *                                                                          *
  311. * "serve received N(R)"                                                    *
  312. *                                                                          *
  313. * Aktuell empfangenes N(R) (rxfctl) des aktuellen Links (lnkpoi) auswerten *
  314. * und entsprechend verfahren (s.u.).                                       *
  315. *                                                                          *
  316. * Return:  YES - aktuell empfangenes N(R) ist okay oder Linkzustand        *
  317. *                laesst N(R)-Empfang nicht zu                              *
  318. *          NO  - aktuell empfangenes N(R) ist falsch                       *
  319. *                                                                          *
  320. \**************************************************************************/
  321.  
  322. BOOLEAN srxdNR()
  323.   {
  324.     unsigned rxdNR;      /* empfangenes N(R)                              */
  325.     unsigned newok;      /* Anzahl neu bestaetigte I's                    */
  326.     unsigned outstd;     /* Anzahl ausstehende (nicht bestaetigte) I's    */
  327.     unsigned l2state;    /* Linkstatus des aktuellen Links                */
  328.  
  329.     if ((l2state = lnkpoi->state) >= L2SIXFER)    /* darf N(R) kommen ?   */
  330.       {
  331.         if (    ( outstd = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07
  332.                 ) != 0
  333.              && ( newok = ( (rxdNR = (rxfctl >> 5) & 0x07) - lnkpoi->lrxdNR
  334.                           ) & 0x07
  335.                 ) != 0             /* N(R) nur auswerten, wenn I's aus-   */
  336.            )                       /* stehen und neue bestaetigt werden   */
  337.           if (newok <= outstd)     /* N(R) okay ?                         */
  338.             {
  339.               lnkpoi->lrxdNR = rxdNR;   /* ja, N(R) annehmen              */
  340.               clrT1();                  /* T1 stoppen                     */
  341.               if (newok != outstd)      /* wenn immer noch I's ausstehend */
  342.                 setT1();                /* T1 neu starten                 */
  343.               while (newok-- != 0)
  344.                 {                                      /* alle neu        */
  345.                   dealmb(unlink(lnkpoi->sendil.head)); /* bestaetigten    */
  346.                   --lnkpoi->tosend;                    /* I's wegwerfen   */
  347.                 }
  348.             }
  349.           else
  350.             {                           /* nein,                          */
  351.               sdfrmr(0x08);             /* Kontrollfeld hat falsches N(R) */
  352.               return (FALSE);           /* N(R) nicht okay !              */
  353.             }
  354.  
  355.         if (    l2state == L2SWA        /* falls Linkzustand "Warten auf  */
  356.              || l2state == L2SWADBS     /* Bestaetigung" ist,             */
  357.              || l2state == L2SWARBS
  358.              || l2state == L2SWABBS
  359.            )
  360.           if (!rxfCR && rxfPF != 0)          /* wenn empfangenes Frame    */
  361.             {                                /* Response mit Final war,   */
  362.               clrT1();                       /* Timer 1 stoppen und       */
  363.               lnkpoi->VS = lnkpoi->lrxdNR;   /* V(S) updaten              */
  364.             }
  365.           else                               /* sonst Timer 1 neu         */
  366.             if (!lnkpoi->T1) setT1();        /* starten falls inaktiv     */
  367.       }
  368.       
  369.     return (TRUE);                      /* N(R) okay oder nicht benutzt   */
  370.   }
  371.  
  372.  
  373.  
  374.  
  375.  
  376. /**************************************************************************\
  377. *                                                                          *
  378. * "is next I"                                                              *
  379. *                                                                          *
  380. * Testen, ob das aktuell empfangene I-Frame (rxf...) das naechste fuer den *
  381. * aktuellen Linkblock (lnkpoi) erwartete I-Frame ist, wenn der Linkzustand *
  382. * Informationstransfer zulaesst. Bei nicht erwarteter Sequenznummer        *
  383. * entsprechende Statetable abarbeiten.                                     *
  384. *                                                                          *
  385. * Return :  YES - I-Frame ist das naechste erwartete oder Linkzustand      *
  386. *                 laesst keinen Informationstransfer zu                    *
  387. *           NO  - sonst                                                    *
  388. *                                                                          *
  389. \**************************************************************************/
  390.  
  391. BOOLEAN isnxti()
  392.   {
  393.     unsigned iseqno;                              /* I Sequence Number    */
  394.  
  395.     if (lnkpoi->state >= L2SIXFER)                        /* I-Transfer ? */
  396.       if ((iseqno = (rxfctl >> 1) & 0x07) == lnkpoi->VR)  /* I erwartet ? */
  397.         if (((lnkpoi->ltxdNR + 7) & 0x07) != iseqno)      /* kein Ueber-  */
  398.           {                                               /* lauf ?       */
  399.             if (!(lnkpoi->flag & L2FBUSY))       /* wenn nicht busy, neue */
  400.               lnkpoi->VR = (iseqno + 1) & 0x07;  /* V(R) setzen           */
  401.           }
  402.         else
  403.           {
  404.             sdfrmr(0x01);      /* Kontrollfeld falsch/nicht implementiert */
  405.             return (FALSE);
  406.           }
  407.       else                                       /* unerwartetes I (nicht */
  408.         {                                        /* naechstes in Reihe)   */
  409.           l2stma(!rxfPF ? stbl26 : stb26b);      /* INVALID N(S) RECEIVED */
  410.           return (FALSE);                        /* unerwartetes I !      */
  411.         }
  412.         
  413.     return (TRUE);       /* I richtig oder Linkzustand ohne I-Transfer    */
  414.   }
  415.  
  416.  
  417.  
  418.  
  419.  
  420. /**************************************************************************\
  421. *                                                                          *
  422. * "initialize link"                                                        *
  423. *                                                                          *
  424. * Aktuellen Linkblock (lnkpoi) initialisieren. Sequenzvariablen und Timer  *
  425. * initialisieren, Quellcall/Zielcall/via-Liste/ Port setzen aus der        *
  426. * txf...-Liste.                                                            *
  427. *                                                                          *
  428. \**************************************************************************/
  429.  
  430. VOID inilnk()
  431.   {
  432.     reslnk();                                /* Sequenzvars/Timer init.   */
  433.     cpyid(lnkpoi->srcid,txfhdr + L2IDLEN);   /* Quellcall                 */
  434.     cpyid(lnkpoi->dstid,txfhdr);             /* Zielcall                  */
  435.     cpyidl(lnkpoi->viaidl,txfhdr + L2ILEN);  /* via-Liste                 */
  436.     lnkpoi->liport = txfprt;                 /* Port                      */
  437.     setiT1();                                /* initial Timer 1           */
  438.   }
  439.  
  440.  
  441.  
  442.  
  443.  
  444. /**************************************************************************\
  445. *                                                                          *
  446. * "set initial T1"                                                         *
  447. *                                                                          *
  448. * Den initialen Timer-1-Zaehlerstand des aktuellen Linkblocks (lnkpoi)     *
  449. * (= derjenige Zaehlerstand, der bei Start des Timer 1 immer gesetzt wird) *
  450. * berechnen nach der Formel :                                              *
  451. *                                                                          *
  452. *                                                                          *
  453. *     initT1 [1/100 sec]                                                   *
  454. *                                                                          *
  455. *   = (Anzahl der Digipeater * 2 + 1) * FRACK [sec] * 100                  *
  456. *                                         |                                *
  457. *                                         +---> fuer jeden Linkblock       *
  458. * und im Linkblock setzen (initT1).             einzeln, snglT1            *
  459. *                                                                          *
  460. \**************************************************************************/
  461.  
  462. VOID setiT1()
  463.   {
  464.     char       *viap;                   /* Zeiger in via-Liste            */
  465.     unsigned    n;                      /* Digizaehler                    */
  466.     
  467.     viap = lnkpoi->viaidl;              /* Anfang via-Liste               */
  468.     n = 0;                              /* noch kein Digi gezaehlt        */
  469.     while (*viap != '\0')               /* Digianzahl ermitteln           */
  470.       {
  471.         ++n;
  472.         viap += L2IDLEN;
  473.       }
  474.     n *= 2;                                       /* Digianzahl * 2 + 1   */
  475.     ++n;
  476.     lnkpoi->initT1 = lnkpoi->snglT1 * n * 100;    /* " * FRACK * 100      */
  477.   }
  478.  
  479.  
  480.  
  481.  
  482.  
  483. /**************************************************************************\
  484. *                                                                          *
  485. * "messaged clear link"                                                    *
  486. *                                                                          *
  487. * Aktuellen Link aufloesen (siehe clrlnk()) und entsprechende Meldung an   *
  488. * hoehere Level geben ("Disconnected from").                               *
  489. *                                                                          *
  490. \**************************************************************************/
  491.  
  492. VOID mclrlk()
  493.   {
  494.     clrlnk();                           /* Link aufloesen                 */
  495.     l2tolx(L2MDISCF);                   /* und hoehere Level informieren  */
  496.   }
  497.  
  498.  
  499.  
  500.  
  501.  
  502. /**************************************************************************\
  503. *                                                                          *
  504. * "clear link"                                                             *
  505. *                                                                          *
  506. * Aktuellen Link (lnkpoi) aufloesen. Alle Sequenzvariablen und Timer       *
  507. * zuruecksetzen, Sende- und Empfangsinfoframelise loeschen, Linkblock neu  *
  508. * mit AX.25-Parametern besetzen, Anzahl der aktiven Links (nmblks) um 1    *
  509. * erniedrigen.                                                             *
  510. *                                                                          *
  511. \**************************************************************************/
  512.  
  513. VOID clrlnk()
  514.   {
  515.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  516.     dealml(&lnkpoi->rcvdil);            /* Empfangsinfoliste loeschen     */
  517.     dealml(&lnkpoi->sendil);            /* Sendeinfoliste loeschen        */
  518.     lnkpoi->rcvd = lnkpoi->tosend = 0;  /* entsprechende Zaehler loeschen */
  519.     --nmblks;                           /* nun ein aktiver Link weniger   */
  520.     inilbl();                           /* Linkblock "frisch"             */
  521.   }
  522.  
  523.  
  524.  
  525.  
  526.  
  527. /**************************************************************************\
  528. *                                                                          *
  529. * "disconnect"                                                             *
  530. *                                                                          *
  531. * Disconnect des aktuellen Links (lnkpoi) einleiten. Alle Sequenzvariablen *
  532. * und Timer zuruecksetzen, DISC senden, neuer Status "Disconnect request". *
  533. *                                                                          *
  534. \**************************************************************************/
  535.  
  536. VOID disc()
  537.   {
  538.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  539.     xdisc();                            /* DISC senden                    */
  540.     lnkpoi->state = L2SDSCRQ;           /* Linkstatus "Disc Request"      */
  541.   }
  542.  
  543.  
  544.  
  545.  
  546.  
  547. /**************************************************************************\
  548. *                                                                          *
  549. * "reset link"                                                             *
  550. *                                                                          *
  551. * Aktuellen Link (lnkpoi) zuruecksetzen. Alle Sequenzvariablen und Timer   *
  552. * initialisieren.                                                          *
  553. *                                                                          *
  554. \**************************************************************************/
  555.  
  556. VOID reslnk()
  557.   {
  558.        lnkpoi->VS
  559.      = lnkpoi->VR
  560.      = lnkpoi->ltxdNR
  561.      = lnkpoi->lrxdNR
  562.      = lnkpoi->flag
  563.      = 0;
  564.      clrT1();
  565.      clrT2();
  566.   }
  567.  
  568.  
  569.  
  570.  
  571.  
  572. /**************************************************************************\
  573. *                                                                          *
  574. * "initialize link block"                                                  *
  575. *                                                                          *
  576. * Aktuellen Linkblock (lnkpoi) mit AX.25-Parametern initialisieren.        *
  577. * Loeschen des Quellrufzeichens, Setzen von FRACK, MAXFRAME, RETRY,        *
  578. * AX25V2.                                                                  *
  579. *                                                                          *
  580. \**************************************************************************/
  581.  
  582. VOID inilbl()
  583.   {
  584.     *lnkpoi->srcid  = '\0';
  585.     lnkpoi->snglT1  = Fpar;
  586.     lnkpoi->k       = Opar;
  587.     lnkpoi->N2      = Npar;
  588.     lnkpoi->V2link  = Vpar;
  589.   }
  590.  
  591.  
  592.  
  593.  
  594.  
  595. /**************************************************************************\
  596. *                                                                          *
  597. * "send outstanding I's"                                                   *
  598. *                                                                          *
  599. * Aus dem aktuellen Linkblock (lnkpoi) soviele I-Frames senden, wie im     *
  600. * Moment unbestaetigt ausstehen.                                           *
  601. *                                                                          *
  602. \**************************************************************************/
  603.  
  604. VOID sdoi()
  605.   {
  606.     unsigned nmbtos;                    /* Anzahl I's zu senden           */
  607.     
  608.     if (nmbtos = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07) /* wieviel darf    */
  609.       {                                                /* ich ?           */
  610.         lnkpoi->VS = lnkpoi->lrxdNR;                   /* V(S) resetten   */
  611.         sdi(nmbtos);                                   /* I's senden      */
  612.       }
  613.   }
  614.  
  615.  
  616.  
  617.  
  618.  
  619. /**************************************************************************\
  620. *                                                                          *
  621. * "send I"                                                                 *
  622. *                                                                          *
  623. * Aus dem aktuellen Linkblock (lnkpoi) maximal max I-Frames aus der        *
  624. * Infomessageliste aufbauen und senden. Infos ueber 256 Bytes werden       *
  625. * gesplittet und dann gesendet. Die Frames werden als Commandframes ohne   *
  626. * Poll/Final-Bit gesendet. V(S) wird fuer jedes gesendete Frame erhoeht    *
  627. * modulo 7. Timer 2 und Timer 3 werden abgeschaltet.                       *
  628. *                                                                          *
  629. \**************************************************************************/
  630.  
  631. VOID sdi(max)
  632.  
  633. unsigned max;
  634.  
  635.   {
  636.     unsigned    n;                           /* Zaehler zu sendende Infos */
  637.     MBHEAD     *sendip;                      /* Kopfzeiger Infobuffer     */
  638.     MBHEAD     *fbp;                         /* Kopfzeiger Framebuffer    */
  639.  
  640.     for ( n = 0, sendip = lnkpoi->sendil.head;    /* maximal max I-Frames */
  641.           n < lnkpoi->tosend && n < max;          /* aus der Linkblock-   */
  642.           ++n, sendip = sendip->nextmh            /* infoliste senden     */
  643.         )                                         /* wenn vorhanden       */
  644.       {
  645.         stxfad();                            /* Frameadresse aufbauen     */
  646.         txfV2 = lnkpoi->V2link;              /* Version                   */
  647.         txfCR = L2CCR;                       /* Command !                 */
  648.         txfPF = 0;                           /* kein Poll/Final           */
  649.         txfctl = setNR(lnkpoi->VS << 1);     /* Controlbyte I setzen      */
  650.         ++lnkpoi->VS;                        /* V(S) erhoehen             */
  651.         lnkpoi->VS &= 0x07;                  /* modulo 7                  */
  652.         putchr(sendip->l2fflg,               /* Frame aufbauen, PID       */
  653.                fbp = makfhd(L2FT1ST));
  654.         if (splcpy(256,fbp,sendip) == YES)   /* Message hineinkopieren    */
  655.           ++lnkpoi->tosend;                  /* falls Split eine mehr     */
  656.         sdl2fr(fbp);                         /* Frame senden              */
  657.         clrT2();                             /* Timer 2 abschalten        */
  658.         clrT3();                             /* Timer 3 abschalten        */
  659.       }
  660.   }
  661.  
  662.  
  663.  
  664.  
  665.  
  666. /**************************************************************************\
  667. *                                                                          *
  668. * "split copy"                                                             *
  669. *                                                                          *
  670. * Die Bytes aus dem Messagebuffer, auf dessen Kopf mbhd zeigt, in den      *
  671. * Framebuffer, auf dessen Kopf fbp zeigt, kopieren. Es werden hoechstens   *
  672. * max Bytes kopiert, hat die Message mehr Bytes, so wird ein neuer         *
  673. * Messagebuffer angelegt, die restlichen Messagebytes werden in diesen     *
  674. * Buffer kopiert, der neue Buffer wird hinter den alten Messagebuffer      *
  675. * gehaengt, der Putcount des alten Buffers wird auf max gestellt, das      *
  676. * "more follows"-Flag morflg des neuen Buffers wird geloescht, l2fflg wird *
  677. * uebertragen.                                                             *
  678. *                                                                          *
  679. * Return :  YES - der Messagebuffer wurde aufgesplittet                    *
  680. *           NO  - sonst                                                    *
  681. *                                                                          *
  682. \**************************************************************************/
  683.  
  684. BOOLEAN splcpy(max,fbp,mbhd)
  685.  
  686. unsigned    max;
  687. MBHEAD     *fbp;
  688. MBHEAD     *mbhd;
  689.  
  690.   {
  691.     char       *mbbpsa;                 /* Sicherung mbbp                 */
  692.     BOOLEAN     split;                  /* TRUE: Split erfolgt            */
  693.     unsigned    mbgcsa;                 /* Sicherung mbgc                 */
  694.     unsigned    mbgc2;                  /* mbgc alt -> mbpc alt           */
  695.     unsigned    n;                      /* Zaehler                        */
  696.     MBHEAD     *mbhd2;                  /* Kopfzeiger neuer Messagebuffer */
  697.     
  698.     split = NO;                         /* zunaechst nichts gesplittet    */
  699.     mbbpsa = mbhd->mbbp;                /* Bufferpointer sichern          */
  700.     mbgcsa = mbhd->mbgc;                /* Getcounter sichern             */
  701.     for (n = 0; mbhd->mbgc < mbhd->mbpc && n < max; ++n)
  702.       putchr(getchr(mbhd),fbp);         /* maximal max Bytes kopieren     */
  703.     if (mbhd->mbgc < mbhd->mbpc)        /* noch Bytes ueber -> Split !    */
  704.       {
  705.         mbgc2 = mbhd->mbgc;             /* Getcount fuer spaeter merken   */
  706.         mbhd2 = allocb();               /* neuen Buffer erzeugen          */
  707.         while (mbhd->mbgc < mbhd->mbpc) /* die restlichen Bytes in diesen */
  708.           putchr(getchr(mbhd),mbhd2);   /* Buffer kopieren                */
  709.         rwndmb(mbhd2);                  /* neuen Buffer rewinden          */
  710.         mbhd2->morflg = NO;             /* noch dem neuen folgt keiner    */
  711.         mbhd2->l2fflg = mbhd->l2fflg;   /* Frameflag uebertragen          */
  712.         relink(mbhd2,mbhd);             /* neu. Buf. hinter alten haengen */
  713.         mbhd->mbpc = mbgc2;             /* alter Buffer nur max Zeichen ! */
  714.         split = YES;                    /* wir mussten splitten           */
  715.       }
  716.     mbhd->mbbp = mbbpsa;                /* Bufferpointer restaurieren     */
  717.     mbhd->mbgc = mbgcsa;                /* Getcount restaurieren          */
  718.     return (split);                     /* Split oder nicht               */
  719.   }
  720.  
  721.  
  722.  
  723.  
  724.  
  725. /**************************************************************************\
  726. *                                                                          *
  727. * "send UI"                                                                *
  728. *                                                                          *
  729. * UI-Frame aufbauen und senden. Das UI-Frame wird an ID dest geschickt     *
  730. * ueber den Port port und die via-Liste (nullterminiert) vial, als Quelle  *
  731. * wird source genommen, die Infobytes des Frames stehen im Messagebuffer,  *
  732. * auf dessen Kopf mbhd zeigt, die PID wird aus l2fflg dieses Buffers       *
  733. * genommen.                                                                *
  734. *                                                                          *
  735. \**************************************************************************/
  736.  
  737. VOID sdui(vial,dest,source,port,mbhd)
  738.  
  739. char     *vial;
  740. char     *dest;
  741. char     *source;
  742. unsigned  port;
  743. MBHEAD   *mbhd;
  744.  
  745.   {
  746.     MBHEAD        *fbp;                           /* Zeiger auf Framekopf */
  747.  
  748.     cpyid(txfhdr + L2IDLEN,source);               /* Quelle setzen        */
  749.     cpyid(txfhdr,dest);                           /* Ziel setzen          */
  750.     cpyidl(txfhdr + L2ILEN,vial);                 /* via-Liste setzen     */
  751.     txfprt = port;                                /* Port setzen          */
  752.     txfV2 = Vpar;                                 /* Protokollversion     */
  753.     txfCR = L2CCR;                                /* Command !            */
  754.     txfPF = 0;                                    /* kein Poll/Final      */
  755.     txfctl = L2CUI;                               /* UI-Frame !           */
  756.     putchr(mbhd->l2fflg,fbp = makfhd(0));         /* Frame aufbauen, PID  */
  757.     while (mbhd->mbgc < mbhd->mbpc)               /* Message -> Frame     */
  758.       putchr(getchr(mbhd),fbp);
  759.     sdl2fr(fbp);                                  /* Frame senden         */
  760.   }
  761.  
  762.  
  763.  
  764.  
  765.  
  766. /**************************************************************************\
  767. *                                                                          *
  768. * "level 2 state machine"                                                  *
  769. *                                                                          *
  770. * Ausfuehren der Zustandsuebergangsfunktion des Linkstatus (state) des     *
  771. * aktuellen Linkblocks (lnkpoi) in der Statetable stbl, danach einnehmen   *
  772. * des durch die Statetable gegebenen neuen Zustands.                       *
  773. *                                                                          *
  774. * In der Protokollversion 1 (dort gibt es nur 5 Zustaende), alle Zustaende *
  775. * oberhalb Informationstransfer auf Informationstransfer setzen.           *
  776. *                                                                          *
  777. \**************************************************************************/
  778.  
  779. VOID l2stma(stbl)
  780.  
  781. STENTRY stbl[];
  782.  
  783.   {
  784.     (*stbl[lnkpoi->state].func)();                     /* Funktion ...    */
  785.     lnkpoi->state = stbl[lnkpoi->state].newstate;      /* neuer Zustand   */
  786.     if (!lnkpoi->V2link && lnkpoi->state > L2SIXFER)   /* Version 1       */
  787.       lnkpoi->state = L2SIXFER;                        /* Stutzung        */
  788.   }
  789.  
  790.  
  791.  
  792. /* Ende von L2B.C */
  793.