home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / nrs.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  6KB  |  259 lines

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  *
  6.  * Copyright 1989 Dan Frank, W9NK
  7.  */
  8. #include <stdio.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "iface.h"
  12. #include "pktdrvr.h"
  13. #include "ax25.h"
  14. #include "nrs.h"
  15. #include "asy.h"
  16. #include "trace.h"
  17. #include "commands.h"
  18.  
  19. static struct mbuf *nrs_encode __ARGS((struct mbuf *bp));
  20. static struct mbuf *nrs_decode __ARGS((int dev,char c));
  21.  
  22. /* control structures, sort of overlayed on async control blocks */
  23. struct nrs Nrs[ASY_MAX];
  24.  
  25. int
  26. nrs_init(ifp,vj)
  27. struct iface *ifp;
  28. int vj;    /* Unused */
  29. {
  30.     int xdev;
  31.     struct nrs *np;
  32.     char *ifn;
  33.  
  34.     /* Set up a net/rom serial iface */
  35.     for(xdev = 0;xdev < NRS_MAX;xdev++){
  36.         np = &Nrs[xdev];
  37.         if(np->iface == NULLIF)
  38.             break;
  39.     }
  40.     if(xdev >= NRS_MAX) {
  41.         tprintf("Too many nrs devices\n");
  42.         return -1;
  43.     }
  44.     /* no call supplied? */
  45.     setencap(ifp,"AX25");
  46.     ifp->ioctl = asy_ioctl;
  47.     ifp->raw = nrs_raw;
  48.  
  49.     ifp->hwaddr = mallocw(AXALEN);
  50.     memcpy(ifp->hwaddr,Mycall,AXALEN);
  51.     ifp->xdev = xdev;
  52.     np->iface = ifp;
  53.     np->send = asy_send;
  54.     np->get = get_asy;
  55.     ifp->rxproc = newproc( ifn = if_name( ifp, " nrs" ),
  56.         256,nrs_recv,xdev,NULL,NULL,0);
  57.     free(ifn);
  58.     return 0;
  59. }
  60. int
  61. nrs_free(ifp)
  62. struct iface *ifp;
  63. {
  64.     if(Nrs[ifp->xdev].iface == ifp)
  65.         Nrs[ifp->xdev].iface = NULLIF;
  66.     return 0;
  67. }
  68. /* Send a raw net/rom serial frame */
  69. int
  70. nrs_raw(iface,bp)
  71. struct iface *iface;
  72. struct mbuf *bp;
  73. {
  74.     struct mbuf *bp1;
  75.  
  76.     dump(iface,IF_TRACE_OUT,CL_AX25,bp);
  77.     iface->rawsndcnt++;
  78.     iface->lastsent = secclock();
  79.  
  80.     if((bp1 = nrs_encode(bp)) == NULLBUF){
  81.         free_p(bp);
  82.         return -1;
  83.     }
  84.     return Nrs[iface->xdev].send(iface->dev,bp1);
  85. }
  86.  
  87. /* Encode a packet in net/rom serial format */
  88. static struct mbuf *
  89. nrs_encode(bp)
  90. struct mbuf *bp;
  91. {
  92.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  93.     register char *cp;
  94.     int c;
  95.     unsigned char csum = 0;
  96.  
  97.     /* Allocate output mbuf that's twice as long as the packet.
  98.      * This is a worst-case guess (consider a packet full of STX's!)
  99.      * Add five bytes for STX, ETX, checksum, and two nulls.
  100.      */
  101.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 5));
  102.     if(lbp == NULLBUF){
  103.         /* No space; drop */
  104.         free_p(bp);
  105.         return NULLBUF;
  106.     }
  107.     cp = lbp->data;
  108.  
  109.     *cp++ = STX;
  110.  
  111.     /* Copy input to output, escaping special characters */
  112.     while((c = PULLCHAR(&bp)) != -1){
  113.         switch(c){
  114.         case STX:
  115.         case ETX:
  116.         case DLE:
  117.             *cp++ = DLE;
  118.             /* notice drop through to default */
  119.         default:
  120.             *cp++ = c;
  121.         }
  122.         csum += c;
  123.     }
  124.     *cp++ = ETX;
  125.     *cp++ = csum;
  126.     *cp++ = NUL;
  127.     *cp++ = NUL;
  128.     
  129.     lbp->cnt = cp - lbp->data;
  130.     return lbp;
  131. }
  132. /* Process incoming bytes in net/rom serial format
  133.  * When a buffer is complete, return it; otherwise NULLBUF
  134.  */
  135. static struct mbuf *
  136. nrs_decode(dev,c)
  137. int dev;    /* net/rom unit number */
  138. char c;        /* Incoming character */
  139. {
  140.     struct mbuf *bp;
  141.     register struct nrs *sp;
  142.  
  143.     sp = &Nrs[dev];
  144.     switch(sp->state) {
  145.         case NRS_INTER:
  146.             if(uchar(c) == STX) {    /* look for start of frame */
  147.                 sp->state = NRS_INPACK;    /* we're in a packet */
  148.                 sp->csum = 0;                /* reset checksum */
  149.             }
  150.             return NULLBUF;
  151.         case NRS_CSUM:
  152.             bp = sp->rbp;
  153.             sp->rbp = NULLBUF;
  154.             sp->rcnt = 0;
  155.             sp->state = NRS_INTER;    /* go back to inter-packet state */
  156.             if(sp->csum == uchar(c)) {
  157.                 sp->packets++;
  158.             } else {
  159.                 free_p(bp);    /* drop packet with bad checksum */
  160.                 bp = NULLBUF;
  161.                 sp->errors++;    /* increment error count */
  162.             }
  163.             return bp;
  164.         case NRS_ESCAPE:
  165.             sp->state = NRS_INPACK;    /* end of escape */
  166.             break;            /* this will drop through to char processing */
  167.         case NRS_INPACK:
  168.             switch (uchar(c)) {
  169.             /* If we see an STX in a packet, assume that previous */
  170.             /* packet was trashed, and start a new packet */
  171.             case STX:
  172.                 free_p(sp->rbp);
  173.                 sp->rbp = NULLBUF;
  174.                 sp->rcnt = 0;
  175.                 sp->csum = 0;
  176.                 sp->errors++;
  177.                 return NULLBUF;
  178.             case ETX:
  179.                 sp->state = NRS_CSUM;    /* look for checksum */
  180.                 return NULLBUF;
  181.             case DLE:
  182.                 sp->state = NRS_ESCAPE;
  183.                 return NULLBUF;
  184.             }
  185.     }
  186.     /* If we get to here, it's with a character that's part of the packet.
  187.      * Make sure there's space for it.
  188.      */
  189.     if(sp->rbp == NULLBUF){
  190.         /* Allocate first mbuf for new packet */
  191.         if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULLBUF) {
  192.             sp->state = NRS_INTER;
  193.             return NULLBUF; /* No memory, drop */
  194.         }
  195.         sp->rcp = sp->rbp->data;
  196.     } else if(sp->rbp1->cnt == NRS_ALLOC){
  197.         /* Current mbuf is full; link in another */
  198.         if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULLBUF){
  199.             /* No memory, drop whole thing */
  200.             free_p(sp->rbp);
  201.             sp->rbp = NULLBUF;
  202.             sp->rcnt = 0;
  203.             sp->state = NRS_INTER;
  204.             return NULLBUF;
  205.         }
  206.         sp->rbp1 = sp->rbp1->next;
  207.         sp->rcp = sp->rbp1->data;
  208.     }
  209.     /* Store the character, increment fragment and total
  210.      * byte counts
  211.      */
  212.     *sp->rcp++ = c;
  213.     sp->rbp1->cnt++;
  214.     sp->rcnt++;
  215.     sp->csum += uchar(c);    /* add to checksum */
  216.     return NULLBUF;
  217. }
  218.  
  219. /* Process net/rom serial line I/O */
  220. void
  221. nrs_recv(dev,v1,v2)
  222. int dev;
  223. void *v1;
  224. void *v2;
  225. {
  226.     char c;
  227.     struct mbuf *bp;
  228.  
  229.     /* Process any pending input */
  230.     for(;;){
  231.         c = Nrs[dev].get(Nrs[dev].iface->dev);
  232.         if((bp = nrs_decode(dev,c)) == NULLBUF)
  233.             continue;
  234.         net_route(Nrs[dev].iface,CL_AX25,bp);
  235.     }
  236.  
  237. }
  238. /* donrstat:  display status of active net/rom serial interfaces */
  239. int
  240. donrstat(argc,argv,p)
  241. int argc;
  242. char *argv[];
  243. void *p;
  244. {
  245.     register struct nrs *np;
  246.     register int i;
  247.  
  248.     tprintf("Interface   RcvB  NumReceived  CSumErrors\n");
  249.  
  250.     for(i = 0, np = Nrs; i < ASY_MAX; i++, np++)
  251.         if(np->iface != NULLIF)
  252.             if(tprintf(" %8s   %4d   %10lu  %10lu\n",
  253.              np->iface->name, np->rcnt,
  254.              np->packets, np->errors) == EOF)
  255.                 break;
  256.  
  257.     return 0;
  258. }
  259.