home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / SLIP.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  8KB  |  307 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 "global.h"
  11. #include "mbuf.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14. #include "slhc.h"
  15. #include "asy.h"
  16. #include "slip.h"
  17. #include "trace.h"
  18.   
  19. static struct mbuf *slip_decode __ARGS((struct slip *sp,char c));
  20. static struct mbuf *slip_encode __ARGS((struct mbuf *bp,int usecrc));
  21.   
  22. /* Slip level control structure */
  23. struct slip Slip[ASY_MAX];
  24.   
  25. /* Send routine for point-to-point slip */
  26. int
  27. slip_send(bp,iface,gateway,prec,del,tput,rel)
  28. struct mbuf *bp;    /* Buffer to send */
  29. struct iface *iface;    /* Pointer to interface control block */
  30. int32 gateway;      /* Ignored (SLIP is point-to-point) */
  31. int prec;
  32. int del;
  33. int tput;
  34. int rel;
  35. {
  36. #ifdef VJCOMPRESS
  37.     register struct slip *sp;
  38.     int type;
  39. #endif
  40.     if(iface == NULLIF){
  41.         free_p(bp);
  42.         return -1;
  43.     }
  44. #ifdef VJCOMPRESS
  45.     sp = &Slip[iface->xdev];
  46.     if (sp->escaped & SLIP_VJCOMPR) {
  47.         /* Attempt IP/ICP header compression */
  48.         type = slhc_compress(sp->slcomp,&bp,TRUE);
  49.         bp->data[0] |= type;
  50.     }
  51. #endif
  52.     return (*iface->raw)(iface,bp);
  53. }
  54. /* Send a raw slip frame */
  55. int
  56. slip_raw(iface,bp)
  57. struct iface *iface;
  58. struct mbuf *bp;
  59. {
  60.     struct mbuf *bp1;
  61.     struct slip *sp;
  62.   
  63.     dump(iface,IF_TRACE_OUT,Slip[iface->xdev].type,bp);
  64.     iface->rawsndcnt++;
  65.     iface->lastsent = secclock();
  66.     sp =&Slip[iface->xdev];
  67.   
  68.     if((bp1 = slip_encode(bp,sp->polled)) == NULLBUF){
  69.         return -1;
  70.     }
  71.     if (iface->trace & IF_TRACE_RAW)
  72.         raw_dump(iface,-1,bp1);
  73.     return sp->send(iface->dev,bp1);
  74. }
  75. /* Encode a packet in SLIP format */
  76. static
  77. struct mbuf *
  78. slip_encode(bp,usecrc)
  79. struct mbuf *bp;
  80. int usecrc;         /* For G8BPQ polled-kiss - WG7J */
  81. {
  82.     struct mbuf *lbp;   /* Mbuf containing line-ready packet */
  83.     register char *cp;
  84.     int c,crc,done;
  85.   
  86.     /* Allocate output mbuf that's twice as long as the packet.
  87.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  88.      */
  89.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 3));
  90.     if(lbp == NULLBUF){
  91.         /* No space; drop */
  92.         free_p(bp);
  93.         return NULLBUF;
  94.     }
  95.     cp = lbp->data;
  96.   
  97.     /* Flush out any line garbage */
  98.     *cp++ = FR_END;
  99.   
  100.     /* Set crc to zero */
  101.     crc = 0;
  102.     done = 0;
  103.   
  104.     /* Copy input to output, escaping special characters */
  105.     while(1) {
  106.         c = PULLCHAR(&bp);
  107.         if(c == -1) {       /* If we reached the end of the data */
  108.             if(!usecrc)     /* and we don't use polled kiss, */
  109.                 break;      /* we're done... */
  110.             c = crc;        /* otherwize, encode the crc as well */
  111.             done = 1;
  112.         } else              /* A regular data char, calculate crc */
  113.             crc ^= c;
  114.         switch(c){
  115.             case FR_ESC:
  116.                 *cp++ = FR_ESC;
  117.                 *cp++ = T_FR_ESC;
  118.                 break;
  119.             case FR_END:
  120.                 *cp++ = FR_ESC;
  121.                 *cp++ = T_FR_END;
  122.                 break;
  123.             default:
  124.                 *cp++ = c;
  125.         }
  126.         if(done)
  127.             break;
  128.     }
  129.     *cp++ = FR_END;
  130.     lbp->cnt = cp - lbp->data;
  131.   
  132.     return lbp;
  133. }
  134. /* Process incoming bytes in SLIP format
  135.  * When a buffer is complete, return it; otherwise NULLBUF
  136.  */
  137. static
  138. struct mbuf *
  139. slip_decode(sp,c)
  140. register struct slip *sp;
  141. char c;     /* Incoming character */
  142. {
  143.     struct mbuf *bp;
  144.   
  145.     switch(uchar(c)){
  146.         case FR_END:
  147.             bp = sp->rbp_head;
  148.             sp->rbp_head = NULLBUF;
  149. #ifdef POLLEDKISS
  150.             if(sp->polled) {
  151.                 sp->rx = 0;
  152.                 psignal(&sp->rx,1); /* tell the poller we're done */
  153.                 if(bp) {
  154.                 /* Check the crc. After an ex-or of data and checksum
  155.                  * the result should be 0 - WG7J
  156.                  */
  157.                     if(sp->rxcrc) {
  158.                         free_p(bp);
  159.                         bp = NULL;
  160.                     }
  161.                 /* If valid, delete the crc byte from the data */
  162.                     sp->rbp_tail->cnt--;
  163.                 }
  164.             }
  165. #endif
  166.             return bp;  /* Will be NULLBUF if empty frame */
  167.         case FR_ESC:
  168.             sp->escaped |= SLIP_FLAG;
  169.             return NULLBUF;
  170.     }
  171.     if(sp->escaped & SLIP_FLAG){
  172.         /* Translate 2-char escape sequence back to original char */
  173.         sp->escaped &= ~SLIP_FLAG;
  174.         switch(uchar(c)){
  175.             case T_FR_ESC:
  176.                 c = FR_ESC;
  177.                 break;
  178.             case T_FR_END:
  179.                 c = FR_END;
  180.                 break;
  181.             default:
  182.                 sp->errors++;
  183.                 break;
  184.         }
  185.     }
  186.     /* We reach here with a character for the buffer;
  187.      * make sure there's space for it
  188.      */
  189.     if(sp->rbp_head == NULLBUF){
  190.         /* Allocate first mbuf for new packet */
  191.         if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  192.             return NULLBUF; /* No memory, drop */
  193.         sp->rcp = sp->rbp_head->data;
  194. #ifdef POLLEDKISS
  195.         /* If polled kiss, clear the crc - WG7J
  196.          * also signal polled that we are receiving a packet
  197.          */
  198.         if(sp->polled) {
  199.             sp->rxcrc = 0;
  200.             sp->rx = 1;
  201.         }
  202. #endif
  203.     } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  204.         /* Current mbuf is full; link in another */
  205.         if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  206.             /* No memory, drop whole thing */
  207.             free_p(sp->rbp_head);
  208.             sp->rbp_head = NULLBUF;
  209.             return NULLBUF;
  210.         }
  211.         sp->rbp_tail = sp->rbp_tail->next;
  212.         sp->rcp = sp->rbp_tail->data;
  213.     }
  214.     /* Store the character, increment fragment and total
  215.      * byte counts
  216.      */
  217.     *sp->rcp++ = c;
  218.     sp->rbp_tail->cnt++;
  219. #ifdef POLLEDKISS
  220.     /* If this is a polled interface, adjust the crc */
  221.     if(sp->polled)
  222.         sp->rxcrc ^= c;
  223. #endif
  224.     return NULLBUF;
  225. }
  226.   
  227.   
  228. /* Process SLIP line input */
  229. void
  230. asy_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.     bp = NULL;
  244.     while ( (c = sp->get(cdev)) != -1 ) {
  245.         if((bp = slip_decode(sp,(char)c)) == NULLBUF)
  246.             continue;   /* More to come */
  247.   
  248. #ifdef VJCOMPRESS
  249.         if (sp->iface->trace & IF_TRACE_RAW)
  250.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  251.   
  252.         if (sp->escaped & SLIP_VJCOMPR) {
  253.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  254.                 if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  255.                     free_p(bp);
  256.                     sp->errors++;
  257.                     continue;
  258.                 }
  259.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  260.                 bp->data[0] &= 0x4f;
  261.                 if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  262.                     free_p(bp);
  263.                     sp->errors++;
  264.                     continue;
  265.                 }
  266.             }
  267.         }
  268. #endif
  269.         if ( net_route( sp->iface, sp->type, bp ) != 0 ) {
  270.             free_p(bp);
  271.             bp = NULL;
  272.         }
  273.     }
  274.     if(bp)
  275.         free_p(bp);
  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.     tprintf("  IN:\t%lu pkts\n", iface->rawrecvcnt);
  297. #ifdef VJCOMPRESS
  298.     slhc_i_status(sp->slcomp);
  299. #endif
  300.     tprintf("  OUT:\t%lu pkts\n", iface->rawsndcnt);
  301. #ifdef VJCOMPRESS
  302.     slhc_o_status(sp->slcomp);
  303. #endif
  304. }
  305.   
  306.   
  307.