home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / SLIP.C < prev    next >
C/C++ Source or Header  |  1992-05-03  |  7KB  |  299 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 "mbuf.h"
  13. #include "iface.h"
  14. #include "ip.h"
  15. #include "slhc.h"
  16. #include "asy.h"
  17. #include "slip.h"
  18. #include "trace.h"
  19. #include "pktdrvr.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[SLIP_MAX];
  26.  
  27. int
  28. slip_init(ifp,vj)
  29. struct iface *ifp;
  30. int vj;
  31. {
  32.     int xdev;
  33.     struct slip *sp;
  34.     char *ifn;
  35.  
  36.     for(xdev = 0;xdev < SLIP_MAX;xdev++){
  37.         sp = &Slip[xdev];
  38.         if(sp->iface == NULLIF)
  39.             break;
  40.     }
  41.     if(xdev >= SLIP_MAX) {
  42.         printf("Too many slip devices\n");
  43.         return -1;
  44.     }
  45.     ifp->ioctl = asy_ioctl;
  46.     ifp->raw = slip_raw;
  47.     ifp->show = slip_status;
  48.     ifp->flags = 0;
  49.     ifp->xdev = xdev;
  50.  
  51.     sp->iface = ifp;
  52.     sp->send = asy_send;
  53.     sp->get = get_asy;
  54.     sp->type = CL_SERIAL_LINE;
  55.     if(vj){
  56.         sp->escaped |= SLIP_VJCOMPR;
  57.         sp->slcomp = slhc_init(16,16);
  58.         setencap(ifp,"VJSLIP");
  59.     } else 
  60.         setencap(ifp,"SLIP");
  61.  
  62.     ifp->rxproc = newproc( ifn = if_name( ifp, " rx" ),
  63.         256,slip_rx,xdev,NULL,NULL,0);
  64.     free(ifn);
  65.     return 0;
  66. }
  67. int
  68. slip_free(ifp)
  69. struct iface *ifp;
  70. {
  71.     struct slip *sp;
  72.  
  73.     sp = &Slip[ifp->xdev];
  74.     if(sp->slcomp != NULLSLCOMPR){
  75.         slhc_free(sp->slcomp);
  76.         sp->slcomp = NULLSLCOMPR;
  77.     }
  78.     sp->iface = NULLIF;
  79.     return 0;
  80. }
  81. /* Send routine for point-to-point slip */
  82. int
  83. slip_send(bp,iface,gateway,tos)
  84. struct mbuf *bp;    /* Buffer to send */
  85. struct iface *iface;    /* Pointer to interface control block */
  86. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  87. int tos;
  88. {
  89.     register struct slip *sp;
  90.     int type;
  91.  
  92.     if(iface == NULLIF){
  93.         free_p(bp);
  94.         return -1;
  95.     }
  96.     sp = &Slip[iface->xdev];
  97.     if (sp->escaped & SLIP_VJCOMPR) {
  98.         /* Attempt IP/ICP header compression */
  99.         type = slhc_compress(sp->slcomp,&bp,TRUE);
  100.         bp->data[0] |= type;
  101.     }
  102.     return (*iface->raw)(iface,bp);
  103. }
  104. /* Send a raw slip frame */
  105. int
  106. slip_raw(iface,bp)
  107. struct iface *iface;
  108. struct mbuf *bp;
  109. {
  110.     struct mbuf *bp1;
  111.  
  112.     dump(iface,IF_TRACE_OUT,bp);
  113.     iface->rawsndcnt++;
  114.     iface->lastsent = secclock();
  115.     if((bp1 = slip_encode(bp)) == NULLBUF){
  116.         return -1;
  117.     }
  118.     if (iface->trace & IF_TRACE_RAW)
  119.         raw_dump(iface,-1,bp1);
  120.     return Slip[iface->xdev].send(iface->dev,bp1);
  121. }
  122. /* Encode a packet in SLIP format */
  123. static
  124. struct mbuf *
  125. slip_encode(bp)
  126. struct mbuf *bp;
  127. {
  128.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  129.     register char *cp;
  130.     int c;
  131.  
  132.     /* Allocate output mbuf that's twice as long as the packet.
  133.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  134.      */
  135.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 2));
  136.     if(lbp == NULLBUF){
  137.         /* No space; drop */
  138.         free_p(bp);
  139.         return NULLBUF;
  140.     }
  141.     cp = lbp->data;
  142.  
  143.     /* Flush out any line garbage */
  144.     *cp++ = FR_END;
  145.  
  146.     /* Copy input to output, escaping special characters */
  147.     while((c = PULLCHAR(&bp)) != -1){
  148.         switch(c){
  149.         case FR_ESC:
  150.             *cp++ = FR_ESC;
  151.             *cp++ = T_FR_ESC;
  152.             break;
  153.         case FR_END:
  154.             *cp++ = FR_ESC;
  155.             *cp++ = T_FR_END;
  156.             break;
  157.         default:
  158.             *cp++ = c;
  159.         }
  160.     }
  161.     *cp++ = FR_END;
  162.     lbp->cnt = cp - lbp->data;
  163.     return lbp;
  164. }
  165. /* Process incoming bytes in SLIP format
  166.  * When a buffer is complete, return it; otherwise NULLBUF
  167.  */
  168. static
  169. struct mbuf *
  170. slip_decode(sp,c)
  171. register struct slip *sp;
  172. char c;        /* Incoming character */
  173. {
  174.     struct mbuf *bp;
  175.  
  176.     switch(uchar(c)){
  177.     case FR_END:
  178.         bp = sp->rbp_head;
  179.         sp->rbp_head = NULLBUF;
  180.         return bp;    /* Will be NULLBUF if empty frame */
  181.     case FR_ESC:
  182.         sp->escaped |= SLIP_FLAG;
  183.         return NULLBUF;
  184.     }
  185.     if(sp->escaped & SLIP_FLAG){
  186.         /* Translate 2-char escape sequence back to original char */
  187.         sp->escaped &= ~SLIP_FLAG;
  188.         switch(uchar(c)){
  189.         case T_FR_ESC:
  190.             c = FR_ESC;
  191.             break;
  192.         case T_FR_END:
  193.             c = FR_END;
  194.             break;
  195.         default:
  196.             sp->errors++;
  197.             break;
  198.         }
  199.     }
  200.     /* We reach here with a character for the buffer;
  201.      * make sure there's space for it
  202.      */
  203.     if(sp->rbp_head == NULLBUF){
  204.         /* Allocate first mbuf for new packet */
  205.         if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  206.             return NULLBUF; /* No memory, drop */
  207.         sp->rcp = sp->rbp_head->data;
  208.     } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  209.         /* Current mbuf is full; link in another */
  210.         if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  211.             /* No memory, drop whole thing */
  212.             free_p(sp->rbp_head);
  213.             sp->rbp_head = NULLBUF;
  214.             return NULLBUF;
  215.         }
  216.         sp->rbp_tail = sp->rbp_tail->next;
  217.         sp->rcp = sp->rbp_tail->data;
  218.     }
  219.     /* Store the character, increment fragment and total
  220.      * byte counts
  221.      */
  222.     *sp->rcp++ = c;
  223.     sp->rbp_tail->cnt++;
  224.     return NULLBUF;
  225. }
  226.  
  227.  
  228. /* Process SLIP line input */
  229. void
  230. slip_rx(xdev,p1,p2)
  231. int xdev;
  232. void *p1;
  233. void *p2;
  234. {
  235.     int c;
  236.     struct mbuf *bp;
  237.     register struct slip *sp;
  238.     int cdev;
  239.  
  240.     sp = &Slip[xdev];
  241.     cdev = sp->iface->dev;
  242.  
  243.     while ( (c = sp->get(cdev)) != -1 ) {
  244.         if((bp = slip_decode(sp,(char)c)) == NULLBUF)
  245.             continue;    /* More to come */
  246.  
  247.         if (sp->iface->trace & IF_TRACE_RAW)
  248.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  249.  
  250.         if (sp->escaped & SLIP_VJCOMPR) {
  251.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  252.                 if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  253.                     free_p(bp);
  254.                     sp->errors++;
  255.                     continue;
  256.                 }
  257.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  258.                 bp->data[0] &= 0x4f;
  259.                 if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  260.                     free_p(bp);
  261.                     sp->errors++;
  262.                     continue;
  263.                 }
  264.             }
  265.         }
  266.         net_route( sp->iface, bp);
  267.         /* Especially on slow machines, serial I/O can be quite
  268.          * compute intensive, so release the machine before we
  269.          * do the next packet.  This will allow this packet to
  270.          * go on toward its ultimate destination. [Karn]
  271.          */
  272.         pwait(NULL);
  273.     }
  274.     if(sp->iface->rxproc == Curproc)
  275.         sp->iface->rxproc = NULLPROC;
  276. }
  277.  
  278.  
  279.  
  280. /* Show serial line status */
  281. void
  282. slip_status(iface)
  283. struct iface *iface;
  284. {
  285.     struct slip *sp;
  286.  
  287.     if (iface->xdev > SLIP_MAX)
  288.         /* Must not be a SLIP device */
  289.         return;
  290.  
  291.     sp = &Slip[iface->xdev];
  292.     if (sp->iface != iface)
  293.         /* Must not be a SLIP device */
  294.         return;
  295.  
  296.     slhc_i_status(sp->slcomp);
  297.     slhc_o_status(sp->slcomp);
  298. }
  299.