home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / slip.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  7KB  |  305 lines

  1. /* SLIP (Serial Line IP) encapsulation and control routines.
  2.  * Copyright 1991 Phil Karn
  3.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  4.  */
  5. #include <stdio.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "ax25.h"
  10. #include "slip.h"
  11. #include "asy.h"
  12. #include "trace.h"
  13. #include "config.h"
  14. #include "internet.h"
  15. #include "ip.h"
  16. #include "slcompre.h"
  17.  
  18. static struct mbuf *slip_decode __ARGS((struct slip *sp,char c));
  19. static struct mbuf *slip_encode __ARGS((struct mbuf *bp));
  20.  
  21. /* Slip level control structure */
  22. struct slip Slip[ASY_MAX];
  23.  
  24. /* Send routine for point-to-point slip */
  25. int
  26. slip_send(bp,iface,gateway,prec,del,tput,rel)
  27. struct mbuf *bp;    /* Buffer to send */
  28. struct iface *iface;    /* Pointer to interface control block */
  29. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  30. int prec;
  31. int del;
  32. int tput;
  33. int rel;
  34. {
  35. #ifdef VJCOMPRESS
  36.     register struct slip *sp;
  37.     int type;
  38. #endif
  39.     if(iface == NULLIF){
  40.         free_p(bp);
  41.         return -1;
  42.     }
  43. #ifdef VJCOMPRESS
  44.     sp = &Slip[iface->xdev];
  45.     if (sp->escaped & SLIP_VJCOMPR) {
  46.         /* Attempt IP/ICP header compression */
  47.         type = sl_compress_tcp(&bp,sp->slcomp,1);
  48.         bp->data[0] |= type;
  49.     }
  50. #endif
  51.     return (*iface->raw)(iface,bp);
  52. }
  53. /* Send a raw slip frame */
  54. int
  55. slip_raw(iface,bp)
  56. struct iface *iface;
  57. struct mbuf *bp;
  58. {
  59.     struct mbuf *bp1;
  60.  
  61.     dump(iface,IF_TRACE_OUT,Slip[iface->xdev].type,bp);
  62.     iface->rawsndcnt++;
  63.     iface->lastsent = secclock();
  64.     if((bp1 = slip_encode(bp)) == NULLBUF){
  65.         free_p(bp);
  66.         return -1;
  67.     }
  68.     if (iface->trace & IF_TRACE_RAW)
  69.         raw_dump(iface,-1,bp1);
  70.     return Slip[iface->xdev].send(iface->dev,bp1);
  71. }
  72. /* Encode a packet in SLIP format */
  73. static
  74. struct mbuf *
  75. slip_encode(bp)
  76. struct mbuf *bp;
  77. {
  78.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  79.     register char *cp;
  80.     int c;
  81.  
  82.     /* Allocate output mbuf that's twice as long as the packet.
  83.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  84.      */
  85.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 2));
  86.     if(lbp == NULLBUF){
  87.         /* No space; drop */
  88.         free_p(bp);
  89.         return NULLBUF;
  90.     }
  91.     cp = lbp->data;
  92.  
  93.     /* Flush out any line garbage */
  94.     *cp++ = FR_END;
  95.  
  96.     /* Copy input to output, escaping special characters */
  97.     while((c = PULLCHAR(&bp)) != -1){
  98.         switch(c){
  99.         case FR_ESC:
  100.             *cp++ = FR_ESC;
  101.             *cp++ = T_FR_ESC;
  102.             break;
  103.         case FR_END:
  104.             *cp++ = FR_ESC;
  105.             *cp++ = T_FR_END;
  106.             break;
  107.         default:
  108.             *cp++ = c;
  109.         }
  110.     }
  111.     *cp++ = FR_END;
  112.     lbp->cnt = cp - lbp->data;
  113.     return lbp;
  114. }
  115. /* Process incoming bytes in SLIP format
  116.  * When a buffer is complete, return it; otherwise NULLBUF
  117.  */
  118. static
  119. struct mbuf *
  120. slip_decode(sp,c)
  121. register struct slip *sp;
  122. char c;        /* Incoming character */
  123. {
  124.     struct mbuf *bp;
  125.  
  126.     switch(uchar(c)){
  127.     case FR_END:
  128.         bp = sp->rbp;
  129.         sp->rbp = NULLBUF;
  130.         sp->rcnt = 0;
  131.         return bp;    /* Will be NULLBUF if empty frame */
  132.     case FR_ESC:
  133.         sp->escaped |= SLIP_FLAG;
  134.         return NULLBUF;
  135.     }
  136.     if(sp->escaped & SLIP_FLAG){
  137.         /* Translate 2-char escape sequence back to original char */
  138.         sp->escaped &= ~SLIP_FLAG;
  139.         switch(uchar(c)){
  140.         case T_FR_ESC:
  141.             c = FR_ESC;
  142.             break;
  143.         case T_FR_END:
  144.             c = FR_END;
  145.             break;
  146.         default:
  147.             sp->errors++;
  148.             break;
  149.         }
  150.     }
  151.     /* We reach here with a character for the buffer;
  152.      * make sure there's space for it
  153.      */
  154.     if(sp->rbp == NULLBUF){
  155.         /* Allocate first mbuf for new packet */
  156.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  157.             return NULLBUF; /* No memory, drop */
  158.         sp->rcp = sp->rbp->data;
  159.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  160.         /* Current mbuf is full; link in another */
  161.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  162.             /* No memory, drop whole thing */
  163.             free_p(sp->rbp);
  164.             sp->rbp = NULLBUF;
  165.             sp->rcnt = 0;
  166.             return NULLBUF;
  167.         }
  168.         sp->rbp1 = sp->rbp1->next;
  169.         sp->rcp = sp->rbp1->data;
  170.     }
  171.     /* Store the character, increment fragment and total
  172.      * byte counts
  173.      */
  174.     *sp->rcp++ = c;
  175.     sp->rbp1->cnt++;
  176.     sp->rcnt++;
  177.     return NULLBUF;
  178. }
  179. /* Process SLIP line input */
  180. void
  181. asy_rx(xdev,p1,p2)
  182. int xdev;
  183. void *p1;
  184. void *p2;
  185. {
  186.     int c;
  187.     struct mbuf *bp,*nbp;
  188.     struct phdr phdr;
  189.     register struct slip *sp;
  190. #ifdef VJCOMPRESS
  191.     int16 len;
  192. #endif
  193.     int cdev;
  194.  
  195.     sp = &Slip[xdev];
  196.     cdev = sp->iface->xdev;
  197.  
  198.     for(;;){
  199.         c = sp->get(cdev);
  200.         if((bp = slip_decode(sp,(char)c)) == NULLBUF)
  201.             continue;    /* More to come */
  202.  
  203. #ifdef VJCOMPRESS
  204.         if (sp->iface->trace & IF_TRACE_RAW)
  205.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  206.         if ((len = len_p(bp)) >= 3) {
  207.             /* Got a packet at least minimum length
  208.              * of a compressed packet
  209.              */
  210.             if ((sp->escaped & SLIP_VJCOMPR) &&
  211.                 ((c = (bp->data[0] & 0xf0)) != (IPVERSION << 4))) {
  212.                 /* Got a compressed TCP packet */
  213.                 if (c & 0x80)
  214.                     c = SL_TYPE_COMPRESSED_TCP;
  215.                 else if (c == SL_TYPE_UNCOMPRESSED_TCP)
  216.                     bp->data[0] &= 0x4f;
  217.                 len = sl_uncompress_tcp(&bp, len,
  218.                     (int16)(c & 0x00ff),
  219.                     sp->slcomp);
  220.                 if (len <= 0) {
  221.                     free_p(bp);
  222.                     sp->errors++;
  223.                     continue;
  224.                 }
  225.             }
  226.         }
  227. #endif
  228.  
  229.         if((nbp = pushdown(bp,sizeof(phdr))) == NULLBUF){
  230.             free_p(bp);
  231.             continue;
  232.         }
  233.         phdr.iface = sp->iface;
  234.         phdr.type = sp->type;
  235.         memcpy(&nbp->data[0],(char *)&phdr,sizeof(phdr));
  236.         enqueue(&Hopper,nbp);
  237.         /* Especially on slow machines, serial I/O can be quite
  238.          * compute intensive, so release the machine before we
  239.          * go for the next packet. This will allow this packet to
  240.          * go on to its ultimate destination, helping pipelining
  241.          */
  242.         pwait(NULL);
  243.     }
  244. }
  245. #ifdef VJCOMPRESS
  246. /* Show VJ stats if async interface is SLIP with VJ TCP compression */
  247. void
  248. doslstat(iface)
  249. struct iface *iface;
  250. {
  251.     struct slip *sp;
  252.     struct slcompress *slp;
  253.  
  254.     if (iface->xdev > SLIP_MAX)
  255.         /* Must not be a SLIP device */
  256.         return;
  257.  
  258.     sp = &Slip[iface->xdev];
  259.     if (sp->iface != iface)
  260.         /* Must not be a SLIP device */
  261.         return;
  262.  
  263.     if ((sp->escaped & SLIP_VJCOMPR) == 0)
  264.         /* SLIP device, but not doing VJ TCP header compression */
  265.         return;
  266.  
  267.     slp = sp->slcomp;
  268.     tprintf("  Link encap SLIP::VJ Compress\n");
  269.     tprintf("  IN:  pkt %lu comp %lu",
  270.          iface->rawrecvcnt, slp->sls_compressedin);
  271.     tprintf(" uncomp %lu err %lu toss %lu ip %lu\n",
  272.          slp->sls_uncompressedin, slp->sls_errorin,
  273.          slp->sls_tossed, iface->rawrecvcnt -
  274.          slp->sls_uncompressedin - slp->sls_compressedin);
  275.     tprintf("  OUT: pkt %lu comp %lu uncomp %lu",
  276.          iface->rawsndcnt, slp->sls_compressed,
  277.          slp->sls_uncompressed);
  278.     tprintf(" ip %lu search %lu miss %lu",
  279.          (slp->sls_nontcp + slp->sls_asistcp),
  280.          slp->sls_searches, slp->sls_misses);
  281.     tprintf("\n");
  282. }
  283. #else
  284. void
  285. doslstat(iface)
  286. struct iface *iface;
  287. {
  288.     struct slip *sp;
  289.  
  290.     if (iface->xdev > SLIP_MAX)
  291.         /* Must not be a SLIP device */
  292.         return;
  293.  
  294.     sp = &Slip[iface->xdev];
  295.     if (sp->iface != iface)
  296.         /* Must not be a SLIP device */
  297.         return;
  298.  
  299.     tprintf("  Link encap SLIP\n");
  300.     tprintf("  IN:  pkt %lu", iface->rawrecvcnt);
  301.     tprintf("  OUT: pkt %lu\n", iface->rawsndcnt);
  302. }
  303. #endif
  304.  
  305.