home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / tcpipsrc / Drivers / c / SLIP < prev   
Text File  |  1995-02-20  |  10KB  |  427 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "iface.h"
  11. #include "ax25.h"
  12. #include "slip.h"
  13. #include "asy.h"
  14. #include "trace.h"
  15. #include "timer.h"
  16. #include "ip.h"
  17. #include "arc.h"
  18. #include "bbc.h"
  19.  
  20. static int  slipq(int, struct mbuf *);
  21. static void asy_start(int);
  22. static struct mbuf *slip_encode(struct mbuf *);
  23. static struct mbuf *slip_decode(int, char);
  24. static struct mbuf *slip_uncompress(int dev, struct mbuf *bp);
  25. static struct mbuf *slip_compress(int dev, struct mbuf *bp);
  26.  
  27. /* Slip level control structure */
  28. struct slip slip[ASY_MAX];
  29.  
  30. int doslipstat(int argc, char**argv)
  31. {
  32.   struct interface *iface;
  33.  
  34.   if (iface = if_lookup(argv[1]), iface!=NULL)
  35.   {
  36.      cwprintf(NULL, "Statistics for %s interface %s:\r\n", (slip[iface->dev].slcomp)?"CSLIP":"SLIP", iface->name);
  37.      cwprintf(NULL, "  IP frames sent               : %d\r\n", slip[iface->dev].stat_ip_sent);
  38.      if (slip[iface->dev].slcomp)
  39.      {
  40.        cwprintf(NULL, "  TCP Compressed frames sent   : %d\r\n", slip[iface->dev].stat_tcp_compressed_sent);
  41.        cwprintf(NULL, "  TCP Uncompressed frames sent : %d\r\n", slip[iface->dev].stat_tcp_uncompressed_sent);
  42.      }
  43.      cwprintf(NULL, "  IP frames recvd              : %d\r\n", slip[iface->dev].stat_ip_recvd);
  44.      if (slip[iface->dev].slcomp)
  45.      {
  46.        cwprintf(NULL, "  TCP Compressed frames recvd  : %d\r\n", slip[iface->dev].stat_tcp_compressed_recvd);
  47.        cwprintf(NULL, "  TCP Uncompressed frames recvd: %d\r\n", slip[iface->dev].stat_tcp_uncompressed_recvd);
  48.      }
  49.      cwprintf(NULL, "  Bad frames recvd             : %d\r\n", slip[iface->dev].stat_bad_recvd);
  50.   }
  51.   else
  52.   {
  53.     cwprintf(NULL, "Interface %s unknown\r\n", argv[1]);
  54.     return 1;
  55.   }
  56.   return 0;
  57. }
  58.  
  59. /* Send routine for point-to-point slip
  60.  * This is a trivial function since there is no slip link-level header
  61.  */
  62. int slip_send(struct mbuf *data, struct interface *interface,
  63. int32 gateway, char precedence, char delay,
  64. char throughput, char reliability)
  65. {
  66.   gateway     = gateway;
  67.   precedence  = precedence;
  68.   delay       = delay;
  69.   throughput  = throughput;
  70.   reliability = reliability;
  71.  
  72.   if (interface == NULLIF)
  73.   {
  74.     free_p(data);
  75.     return -1;
  76.   }
  77.   dump(interface, IF_TRACE_OUT, TRACE_IP, data);
  78.   return (*interface->raw)(interface, data);
  79. }
  80.  
  81. /* Send a raw slip frame -- also trivial */
  82. int slip_raw(struct interface *interface, struct mbuf *data)
  83. {
  84.   /* Queue a frame on the slip output queue and start transmitter */
  85.   return slipq(interface->dev,data);
  86. }
  87.  
  88. /* Encode a raw packet in slip framing, put on link output queue, and kick
  89.  * transmitter */
  90. static int slipq(int dev, struct mbuf *data)
  91. {
  92.   register struct slip *sp;
  93.   struct mbuf *bp;
  94.  
  95.   bp = slip_compress(dev, data);
  96.  
  97.   if((bp = slip_encode(bp)) == NULLBUF)
  98.     return -1;
  99.  
  100.   sp = &slip[dev];
  101.   enqueue(&sp->sndq,bp);
  102.   sp->sndcnt++;
  103.   if(sp->tbp == NULLBUF)
  104.     asy_start(dev);
  105.   return 0;
  106. }
  107.  
  108. /* Start output, if possible, on asynch device dev
  109.    Due to the way that the serial port works on the Arc it is not
  110.    possible to get a serial transmit status. Therefore if asy_output
  111.    fails to complete the job of writing cnt characters, store the
  112.    remainder of the frame temporarily until the next call to asy_start,
  113.    then transmit the rest of the frame. Otherwise take the next packet
  114.    from the queue.
  115.  */
  116. static void asy_start(int dev)
  117. {
  118.   register struct slip *sp;
  119.   static int  asy_failed = 0;
  120.   static char *asy_buffer;
  121.   static int  asy_length;
  122.   char *temp_buffer;
  123.   int  temp_length;
  124.   int n;
  125.  
  126.   if (asy_failed)
  127.   {
  128.     if ((n = asy_output(dev, asy_buffer, asy_length)) < asy_length)
  129.     {
  130.       temp_length = asy_length - n;
  131.       temp_buffer = malloc(temp_length);
  132.       memcpy(temp_buffer, asy_buffer + n, temp_length);
  133.       free(asy_buffer);
  134.       asy_length  = temp_length;
  135.       asy_buffer  = temp_buffer;
  136.     }
  137.     else
  138.     {
  139.       asy_failed = 0;
  140.       free(asy_buffer);
  141.     }
  142.   }
  143.   if (!asy_failed)
  144.   {
  145.     sp = &slip[dev];
  146.     if (sp->tbp != NULLBUF)
  147.     {
  148.       /* transmission just completed */
  149.       free_p(sp->tbp);
  150.       sp->tbp = NULLBUF;
  151.     }
  152.     if (sp->sndq == NULLBUF)
  153.       return; /* No work */
  154.  
  155.     sp->tbp = dequeue(&sp->sndq);
  156.     sp->sndcnt--;
  157.     if ((n = asy_output(dev, sp->tbp->data, sp->tbp->cnt)) < sp->tbp->cnt)
  158.     {
  159.       asy_failed = 1;
  160.       asy_length = sp->tbp->cnt - n;
  161.       asy_buffer = malloc(asy_length);
  162.       memcpy(asy_buffer, sp->tbp->data + n, asy_length);
  163.     }
  164.   }
  165. }
  166.  
  167. /* Encode a packet in SLIP format */
  168. static struct mbuf *slip_encode(struct mbuf *bp)
  169. {
  170.   struct mbuf *lbp;       /* Mbuf containing line-ready packet */
  171.   register char *cp;
  172.   char c;
  173.  
  174.   /* Allocate output mbuf that's twice as long as the packet.
  175.      This is a worst-case guess (consider a packet full of FR_ENDs!) */
  176.   lbp = alloc_mbuf(2 * len_mbuf(bp) + 2);
  177.   if(lbp == NULLBUF)
  178.   {
  179.     /* No space; drop */
  180.     free_p(bp);
  181.     return NULLBUF;
  182.   }
  183.   cp = lbp->data;
  184.  
  185.   /* Flush out any line garbage */
  186.   *cp++ = FR_END;
  187.  
  188.   /* Copy input to output, escaping special characters */
  189.   while (pullone(&bp, &c) == 1)
  190.   {
  191.     switch(uchar(c))
  192.     {
  193.     case FR_ESC:
  194.       *cp++ = FR_ESC;
  195.       *cp++ = T_FR_ESC;
  196.       break;
  197.     case FR_END:
  198.       *cp++ = FR_ESC;
  199.       *cp++ = T_FR_END;
  200.       break;
  201.     default:
  202.       *cp++ = c;
  203.     }
  204.   }
  205.   *cp++ = FR_END;
  206.   lbp->cnt = cp - lbp->data;
  207.   return lbp;
  208. }
  209.  
  210. /* Process incoming bytes in SLIP format
  211.  * When a buffer is complete, return it; otherwise NULLBUF
  212.  */
  213. static struct mbuf *slip_decode(int dev, char c)
  214. {
  215.   struct mbuf *bp;
  216.   register struct slip *sp;
  217.  
  218.   sp = &slip[dev];
  219.   switch(c)
  220.   {
  221.   case FR_END:
  222.     bp = sp->rbp;
  223.     sp->rbp = NULL;
  224.     sp->rcnt = 0;
  225.     return bp;      /* Will be NULLBUF if empty frame */
  226.  
  227.   case FR_ESC:
  228.     sp->escaped = 1;
  229.     return NULL;
  230.   }
  231.   if(sp->escaped)
  232.   {
  233.     /* Translate 2-char escape sequence back to original char */
  234.     sp->escaped = 0;
  235.     switch(c)
  236.     {
  237.     case T_FR_ESC:
  238.       c = FR_ESC;
  239.       break;
  240.  
  241.     case T_FR_END:
  242.       c = FR_END;
  243.       break;
  244.  
  245.     default:
  246.       sp->errors++;
  247.       break;
  248.     }
  249.   }
  250.   /* We reach here with a character for the buffer;
  251.      make sure there's space for it */
  252.   if (sp->rbp == NULL)
  253.   {
  254.     /* Allocate first mbuf for new packet */
  255.     if ((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULL)
  256.       return NULL; /* No memory, drop */
  257.     sp->rcp = sp->rbp->data;
  258.   }
  259.   else if(sp->rbp1->cnt == SLIP_ALLOC)
  260.   {
  261.     /* Current mbuf is full; link in another */
  262.     if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULL)
  263.     {
  264.       /* No memory, drop whole thing */
  265.       free_p(sp->rbp);
  266.       sp->rbp = NULL;
  267.       sp->rcnt = 0;
  268.       return NULL;
  269.     }
  270.     sp->rbp1 = sp->rbp1->next;
  271.     sp->rcp  = sp->rbp1->data;
  272.   }
  273.   /* Store the character, increment fragment and total
  274.      byte counts */
  275.   *sp->rcp++ = c;
  276.   sp->rbp1->cnt++;
  277.   sp->rcnt++;
  278.   return NULL;
  279. }
  280.  
  281. /* Process SLIP line I/O */
  282. void doslip(struct interface *interface)
  283. {
  284.   char c;
  285.   struct mbuf *bp;
  286.   int dev;
  287.  
  288.   dev = interface->dev;
  289.   /* Process any pending input */
  290.   while(asy_recv(dev, &c) != 0)
  291.   {
  292.     if ((bp = slip_decode(dev, c)) != NULLBUF)
  293.     {
  294.       bp = slip_uncompress(dev, bp);
  295.       (*slip[dev].recv)(interface, bp);
  296.     }
  297.   }
  298.   /* Kick the transmitter if it's idle */
  299.   asy_start(dev);
  300. }
  301.  
  302. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  303.  * link level header
  304.  */
  305. void slip_recv(struct interface *interface, struct mbuf *bp)
  306. {
  307.   /* By definition, all incoming packets are "addressed" to us */
  308.   dump(interface, IF_TRACE_IN, TRACE_IP, bp);
  309.   ip_route(bp, 0);
  310. }
  311.  
  312. static struct mbuf *slip_compress(int dev, struct mbuf *bp)
  313. {
  314. /*
  315.   static int line = 0;
  316. */
  317.   int len, lenq;
  318.   char *p, *q;
  319.   struct mbuf *ms = NULL, *mp = NULL, *m = NULL;
  320.  
  321.   if (slip[dev].slcomp==NULL)
  322.   {
  323.     slip[dev].stat_ip_sent += 1;
  324.     return bp;
  325.   }
  326. /*
  327.   bbc_vdu(4);
  328.   bbc_vdu(26);
  329.   bbc_vduq(31, dev*40, line+1);
  330. */
  331.   while (bp)
  332.   {
  333.     len = len_mbuf(bp);
  334.     lenq = len_q(bp);
  335.  
  336.     if (p = (char *)malloc(len), p==NULL)
  337.       return bp;
  338.  
  339.     pullup(&bp, p, len);
  340.     q = p;
  341. /