home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff225.lzh / AmigaTCP / src / slip.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  7KB  |  349 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #ifdef    TRACE
  5. #include <stdio.h>
  6. #endif
  7. #include "machdep.h"
  8. #ifdef    TRACE
  9. #include "trace.h"
  10. #endif
  11. #include "mbuf.h"
  12. #include "iface.h"
  13. #include "ax25.h"
  14. #include "slip.h"
  15. #ifdef    AMIGA
  16. #include "amiga.h"
  17. #else
  18. #include "pc.h"
  19. #endif
  20.  
  21. int slip_send();
  22. int doslip();
  23. int asy_output();
  24.  
  25. /* Slip level control structure */
  26. struct slip slip[ASY_MAX];
  27. unsigned nasy;
  28.  
  29. /* Send routine for point-to-point slip
  30.  * This is a trivial function since there is no slip link-level header
  31.  */
  32. int
  33. slip_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  34. struct mbuf *bp;        /* Buffer to send */
  35. struct interface *interface;    /* Pointer to interface control block */
  36. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  37. char precedence;
  38. char delay;
  39. char throughput;
  40. char reliability;
  41. {
  42.     /* Queue a frame on the slip output queue and start transmitter */
  43.  
  44.     if(interface == NULLIF){
  45.         free_p(bp);
  46.         return;
  47.     }
  48. #ifdef    TRACE
  49.     if(trace & TRACE_SLIP){
  50.         printf("%s sent:\r\n",interface->name);
  51.         if((trace & TRACE_HDR) > 2)
  52.             ip_dump(bp);
  53.         if(trace & TRACE_DUMP)
  54.             hexdump(bp);
  55.         if(trace & TRACE_ASCII)
  56.             asciidump(bp);
  57.         fflush(stdout);
  58.     }
  59. #endif
  60.     slipq(interface->dev,bp);
  61. }
  62. /* Encode a packet in slip framing, put on link output queue, and kick
  63.  * transmitter
  64.  */
  65. slipq(dev,bp)
  66. int16 dev;        /* Serial line number */
  67. struct mbuf *bp;    /* Buffer to be sent */
  68. {
  69.     register struct slip *sp;
  70.     struct mbuf *slip_encode();
  71.  
  72.     if((bp = slip_encode(bp)) == NULLBUF)
  73.         return;    
  74.  
  75.     sp = &slip[dev];
  76.     enqueue(&sp->sndq,bp);
  77.     sp->sndcnt++;
  78.     if(sp->tbp == NULLBUF)
  79.         asy_start(dev);
  80. }
  81. /* Start output, if possible, on asynch device dev */
  82. static
  83. asy_start(dev)
  84. int16 dev;
  85. {
  86.     register struct slip *sp;
  87.  
  88.     if(!stxrdy(dev))
  89.         return;        /* Transmitter not ready */
  90.  
  91.     sp = &slip[dev];
  92.     if(sp->tbp != NULLBUF){
  93.         /* transmission just completed */
  94.         free_p(sp->tbp);
  95.         sp->tbp = NULLBUF;
  96.     }
  97.     if(sp->sndq == NULLBUF)
  98.         return;    /* No work */
  99.  
  100.     sp->tbp = dequeue(&sp->sndq);
  101.     sp->sndcnt--;
  102.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  103. }
  104. /* Encode a packet in SLIP format */
  105. static
  106. struct mbuf *
  107. slip_encode(bp)
  108. struct mbuf *bp;
  109. {
  110.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  111.     register char *cp;
  112.     register int cnt;
  113.     char c;
  114.  
  115.     /* Allocate output mbuf that's twice as long as the packet.
  116.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  117.      */
  118.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  119.     if(lbp == NULLBUF){
  120.         /* No space; drop */
  121.         free_p(bp);
  122.         return NULLBUF;
  123.     }
  124.     cp = lbp->data;
  125.     cnt = 0;
  126.  
  127.     /* Flush out any line garbage */
  128.     *cp++ = FR_END;
  129.     cnt++;
  130.  
  131.     /* Copy input to output, escaping special characters */
  132.     while(pullup(&bp,&c,1) == 1){
  133.         switch(c & 0xff){
  134.         case FR_ESC:
  135.             *cp++ = FR_ESC;
  136.             *cp++ = T_FR_ESC;
  137.             cnt += 2;
  138.             break;
  139.         case FR_END:
  140.             *cp++ = FR_ESC;
  141.             *cp++ = T_FR_END;
  142.             cnt += 2;
  143.             break;
  144.         default:
  145.             *cp++ = c;
  146.             cnt++;
  147.         }
  148.     }
  149.     *cp++ = FR_END;
  150.     cnt++;
  151.     lbp->cnt = cnt;
  152.     return lbp;
  153. }
  154. /* Process incoming bytes in SLIP format
  155.  * When a buffer is complete, return it; otherwise NULLBUF
  156.  */
  157. static
  158. struct mbuf *
  159. slip_decode(dev,c)
  160. int dev;    /* Slip unit number */
  161. char c;        /* Incoming character */
  162. {
  163.     struct mbuf *bp,*nbp;
  164.     register struct slip *sp;
  165.  
  166.     sp = &slip[dev];
  167.     switch(c & 0xff){
  168.     case FR_END:
  169.         if(sp->rbp != NULLBUF){
  170.             /* Kick upstairs */
  171.             bp = sp->rbp;
  172.             sp->rbp = NULLBUF;
  173.             sp->rcnt = 0;
  174.             /* Copy into contiguous buffer, if necessary */
  175.             if(bp->next != NULLBUF){
  176.                 nbp = copy_p(bp,len_mbuf(bp));
  177.                 free_p(bp);
  178.                 bp = nbp;
  179.             }
  180.             return bp;
  181.         }
  182.         return NULLBUF;
  183.     case FR_ESC:
  184.         sp->escaped = 1;
  185.         return NULLBUF;
  186.     }
  187.     if(sp->escaped){
  188.         sp->escaped = 0;
  189.         switch(c & 0xff){
  190.         case T_FR_ESC:
  191.             c = FR_ESC;
  192.             break;
  193.         case T_FR_END:
  194.             c = FR_END;
  195.             break;
  196.         default:
  197.             sp->errors++;
  198.         }
  199.     }
  200.     if(sp->rcnt == SLIP_MTU){
  201.         /* Packet is too large, drop it and start over */
  202.         free_p(sp->rbp);
  203.         sp->rbp = NULLBUF;
  204.         sp->rcnt = 0;
  205.         return NULLBUF;
  206.     }
  207.     /* We reach here with a character for the buffer;
  208.      * make sure there's space for it
  209.      */
  210.     if(sp->rbp == NULLBUF){
  211.         /* Allocate first mbuf for new packet */
  212.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  213.             return NULLBUF; /* No memory, drop */
  214.         sp->rcp = sp->rbp->data;
  215.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  216.         /* Current mbuf is full; link in another */
  217.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  218.             /* No memory, drop whole thing */
  219.             free_p(sp->rbp);
  220.             sp->rbp = NULLBUF;
  221.             sp->rcnt = 0;
  222.             return NULLBUF;
  223.         }
  224.         sp->rbp1 = sp->rbp1->next;
  225.         sp->rcp = sp->rbp1->data;
  226.     }
  227.     /* Store the character, increment fragment and total
  228.      * byte counts
  229.      */
  230.     *sp->rcp++ = c;
  231.     sp->rbp1->cnt++;
  232.     sp->rcnt++;
  233.     return NULLBUF;
  234. }
  235. /* Process SLIP line I/O */
  236. int
  237. doslip(interface)
  238. struct interface *interface;
  239. {
  240.     char c;
  241.     struct mbuf *bp;
  242.     int16 dev;
  243.  
  244.     dev = interface->dev;
  245.     /* Process any pending input */
  246.     while(asy_recv(dev,&c,1) != 0)
  247.         if((bp = slip_decode(dev,c)) != NULLBUF)
  248.             (*slip[dev].recv)(interface,bp);
  249.  
  250.     /* Kick the transmitter if it's idle */
  251.     if(stxrdy(dev))
  252.         asy_start(dev);
  253. }
  254. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  255.  * link level header
  256.  */
  257. slip_recv(interface,bp)
  258. struct interface *interface;
  259. struct mbuf *bp;
  260. {
  261. #ifdef    TRACE
  262.     if(trace & TRACE_SLIP){
  263.         printf("%s recv:\r\n",interface->name);
  264.         if((trace & TRACE_HDR) > 2)
  265.             ip_dump(bp);
  266.         if(trace & TRACE_DUMP)
  267.             hexdump(bp);
  268.         if(trace & TRACE_ASCII)
  269.             asciidump(bp);
  270.         fflush(stdout);
  271.     }
  272. #endif
  273.     ip_route(bp,0);
  274. /* Attach a serial interface to the system
  275.  * argv[0]: hardware type, must be "asy"
  276.  * argv[1]: I/O address, e.g., "0x3f8"
  277.  * argv[2]: vector, e.g., "4"
  278.  * argv[3]: mode, may be:
  279.  *        "slip" (point-to-point SLIP)
  280.  *        "ax25" (AX.25 UI frame format in SLIP for raw TNC)
  281.  * argv[4]: interface label, e.g., "sl0"
  282.  * argv[5]: receiver ring buffer size in bytes
  283.  * argv[6]: maximum transmission unit, bytes
  284.  * argv[7]: interface speed, e.g, "9600"
  285.  */
  286. asy_attach(argc,argv)
  287. int argc;
  288. char *argv[];
  289. {
  290.     register struct interface *if_asy;
  291.     extern struct interface *ifaces;
  292.     int dev;
  293.     char *malloc(), *calloc();
  294.     int asy_init();
  295.     int asy_send();
  296.     int doslip();
  297.     int asy_stop();
  298.     int ax_send();
  299.     int kiss_recv();
  300.     int kiss_output();
  301.  
  302.     if(nasy >= ASY_MAX){
  303.         printf("Too many asynch controllers\r\n");
  304.         return -1;
  305.     }
  306.     dev = nasy++;
  307.  
  308.     /* Initialize hardware-level control structure */
  309.     asy[dev].addr = htoi(argv[1]);
  310.     asy[dev].vec = htoi(argv[2]);
  311.  
  312.     /* Create interface structure and fill in details */
  313.     if_asy = (struct interface *)calloc(1, sizeof(struct interface));
  314.  
  315.     if_asy->name = malloc(strlen(argv[4])+1);
  316.     strcpy(if_asy->name,argv[4]);
  317.     if_asy->mtu = atoi(argv[6]);
  318.     if_asy->dev = dev;
  319.     if_asy->recv = doslip;
  320.     if_asy->stop = asy_stop;
  321.  
  322.     if(strcmp(argv[3],"slip") == 0){
  323.         if_asy->send = slip_send;
  324.         if_asy->output = NULLFP;
  325.         if_asy->flags = 0;
  326.         slip[dev].recv = slip_recv;
  327.     }
  328.     else if(strcmp(argv[3],"ax25") == 0){
  329.         if_asy->send = ax_send;
  330.         if_asy->output = kiss_output;
  331.         if_asy->flags = IF_BROADCAST;
  332.         if(if_asy->hwaddr == NULLCHAR)
  333.             if_asy->hwaddr = malloc(AXALEN);
  334.         bcopy((char *)&mycall,if_asy->hwaddr,AXALEN);
  335.         slip[dev].recv = kiss_recv;
  336.     }
  337.     else {
  338.         printf("Mode %s unknown for interface %s\r\n",
  339.             argv[3],argv[4]);
  340.         free((char *)if_asy);
  341.         return -1;
  342.     }
  343.     if_asy->next = ifaces;
  344.     ifaces = if_asy;
  345.     asy_init(dev,(unsigned)atoi(argv[5]));
  346.     asy_speed(dev,atoi(argv[7]));
  347. }
  348.