home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / SLIP.C < prev    next >
C/C++ Source or Header  |  1991-09-17  |  6KB  |  256 lines

  1. /* SLIP (Serial Line IP) encapsulation and control routines.
  2.  * Copyright 1991 Phil Karn
  3.  *
  4.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  5.  *
  6.  *    - Feb 1991    Bill_Simpson@um.cc.umich.edu
  7.  *            reflect changes to header compression calls
  8.  *            revise status display
  9.  */
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "config.h"
  13. #include "mbuf.h"
  14. #include "iface.h"
  15. #include "ip.h"
  16. #include "slhc.h"
  17. #include "asy.h"
  18. #include "slip.h"
  19. #include "trace.h"
  20.  
  21. static struct mbuf *slip_decode __ARGS((struct slip *sp,char c));
  22. static struct mbuf *slip_encode __ARGS((struct mbuf *bp));
  23.  
  24. /* Slip level control structure */
  25. struct slip Slip[ASY_MAX];
  26.  
  27. /* Send routine for point-to-point slip */
  28. int
  29. slip_send(bp,iface,gateway,prec,del,tput,rel)
  30. struct mbuf *bp;    /* Buffer to send */
  31. struct iface *iface;    /* Pointer to interface control block */
  32. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  33. int prec;
  34. int del;
  35. int tput;
  36. int rel;
  37. {
  38. #ifdef VJCOMPRESS
  39.     register struct slip *sp;
  40.     int type;
  41. #endif
  42.     if(iface == NULLIF){
  43.         free_p(bp);
  44.         return -1;
  45.     }
  46. #ifdef VJCOMPRESS
  47.     sp = &Slip[iface->xdev];
  48.     if (sp->escaped & SLIP_VJCOMPR) {
  49.         /* Attempt IP/ICP header compression */
  50.         type = slhc_compress(sp->slcomp,&bp,TRUE);
  51.         bp->data[0] |= type;
  52.     }
  53. #endif
  54.     return (*iface->raw)(iface,bp);
  55. }
  56. /* Send a raw slip frame */
  57. int
  58. slip_raw(iface,bp)
  59. struct iface *iface;
  60. struct mbuf *bp;
  61. {
  62.     struct mbuf *bp1;
  63.  
  64.     dump(iface,IF_TRACE_OUT,Slip[iface->xdev].type,bp);
  65.     iface->rawsndcnt++;
  66.     iface->lastsent = secclock();
  67.     if((bp1 = slip_encode(bp)) == NULLBUF){
  68.         return -1;
  69.     }
  70.     if (iface->trace & IF_TRACE_RAW)
  71.         raw_dump(iface,-1,bp1);
  72.     return Slip[iface->xdev].send(iface->dev,bp1);
  73. }
  74. /* Encode a packet in SLIP format */
  75. static
  76. struct mbuf *
  77. slip_encode(bp)
  78. struct mbuf *bp;
  79. {
  80.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  81.     register char *cp;
  82.     int c;
  83.  
  84.     /* Allocate output mbuf that's twice as long as the packet.
  85.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  86.      */
  87.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 2));
  88.     if(lbp == NULLBUF){
  89.         /* No space; drop */
  90.         free_p(bp);
  91.         return NULLBUF;
  92.     }
  93.     cp = lbp->data;
  94.  
  95.     /* Flush out any line garbage */
  96.     *cp++ = FR_END;
  97.  
  98.     /* Copy input to output, escaping special characters */
  99.     while((c = PULLCHAR(&bp)) != -1){
  100.         switch(c){
  101.         case FR_ESC:
  102.             *cp++ = FR_ESC;
  103.             *cp++ = T_FR_ESC;
  104.             break;
  105.         case FR_END:
  106.             *cp++ = FR_ESC;
  107.             *cp++ = T_FR_END;
  108.             break;
  109.         default:
  110.             *cp++ = c;
  111.         }
  112.     }
  113.     *cp++ = FR_END;
  114.     lbp->cnt = cp - lbp->data;
  115.     return lbp;
  116. }
  117. /* Process incoming bytes in SLIP format
  118.  * When a buffer is complete, return it; otherwise NULLBUF
  119.  */
  120. static
  121. struct mbuf *
  122. slip_decode(sp,c)
  123. register struct slip *sp;
  124. char c;        /* Incoming character */
  125. {
  126.     struct mbuf *bp;
  127.  
  128.     switch(uchar(c)){
  129.     case FR_END:
  130.         bp = sp->rbp_head;
  131.         sp->rbp_head = NULLBUF;
  132.         return bp;    /* Will be NULLBUF if empty frame */
  133.     case FR_ESC:
  134.         sp->escaped |= SLIP_FLAG;
  135.         return NULLBUF;
  136.     }
  137.     if(sp->escaped & SLIP_FLAG){
  138.         /* Translate 2-char escape sequence back to original char */
  139.         sp->escaped &= ~SLIP_FLAG;
  140.         switch(uchar(c)){
  141.         case T_FR_ESC:
  142.             c = FR_ESC;
  143.             break;
  144.         case T_FR_END:
  145.             c = FR_END;
  146.             break;
  147.         default:
  148.             sp->errors++;
  149.             break;
  150.         }
  151.     }
  152.     /* We reach here with a character for the buffer;
  153.      * make sure there's space for it
  154.      */
  155.     if(sp->rbp_head == NULLBUF){
  156.         /* Allocate first mbuf for new packet */
  157.         if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  158.             return NULLBUF; /* No memory, drop */
  159.         sp->rcp = sp->rbp_head->data;
  160.     } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  161.         /* Current mbuf is full; link in another */
  162.         if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  163.             /* No memory, drop whole thing */
  164.             free_p(sp->rbp_head);
  165.             sp->rbp_head = NULLBUF;
  166.             return NULLBUF;
  167.         }
  168.         sp->rbp_tail = sp->rbp_tail->next;
  169.         sp->rcp = sp->rbp_tail->data;
  170.     }
  171.     /* Store the character, increment fragment and total
  172.      * byte counts
  173.      */
  174.     *sp->rcp++ = c;
  175.     sp->rbp_tail->cnt++;
  176.     return NULLBUF;
  177. }
  178.  
  179.  
  180. /* Process SLIP line input */
  181. void
  182. asy_rx(xdev,p1,p2)
  183. int xdev;
  184. void *p1;
  185. void *p2;
  186. {
  187.     int c;
  188.     struct mbuf *bp;
  189.     register struct slip *sp;
  190.     int cdev;
  191.  
  192.     sp = &Slip[xdev];
  193.     cdev = sp->iface->dev;
  194.  
  195.     while ( (c = sp->get(cdev)) != -1 ) {
  196.         if((bp = slip_decode(sp,(char)c)) == NULLBUF)
  197.             continue;    /* More to come */
  198.  
  199. #ifdef VJCOMPRESS
  200.         if (sp->iface->trace & IF_TRACE_RAW)
  201.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  202.  
  203.         if (sp->escaped & SLIP_VJCOMPR) {
  204.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  205.                 if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  206.                     free_p(bp);
  207.                     sp->errors++;
  208.                     continue;
  209.                 }
  210.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  211.                 bp->data[0] &= 0x4f;
  212.                 if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  213.                     free_p(bp);
  214.                     sp->errors++;
  215.                     continue;
  216.                 }
  217.             }
  218.         }
  219. #endif
  220.         if ( net_route( sp->iface, sp->type, bp ) != 0 ) {
  221.             free_p(bp);
  222.         }
  223.     }
  224.     free_p(bp);
  225. }
  226.  
  227.  
  228.  
  229. /* Show serial line status */
  230. void
  231. slip_status(iface)
  232. struct iface *iface;
  233. {
  234.     struct slip *sp;
  235.  
  236.     if (iface->xdev > SLIP_MAX)
  237.         /* Must not be a SLIP device */
  238.         return;
  239.  
  240.     sp = &Slip[iface->xdev];
  241.     if (sp->iface != iface)
  242.         /* Must not be a SLIP device */
  243.         return;
  244.  
  245.     tprintf("  IN:\t%lu pkts\n", iface->rawrecvcnt);
  246. #ifdef VJCOMPRESS
  247.     slhc_i_status(sp->slcomp);
  248. #endif
  249.     tprintf("  OUT:\t%lu pkts\n", iface->rawsndcnt);
  250. #ifdef VJCOMPRESS
  251.     slhc_o_status(sp->slcomp);
  252. #endif
  253. }
  254.  
  255.  
  256.