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

  1. /* User interface subroutines for AX.25
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "iface.h"
  8. #include "lapb.h"
  9. #include "ax25.h"
  10. #include "lapb.h"
  11. #include <ctype.h>
  12.  
  13. /* Open an AX.25 connection */
  14. struct ax25_cb *
  15. open_ax25(iface,local,remote,mode,window,r_upcall,t_upcall,s_upcall,user)
  16. struct iface *iface;    /* Interface */
  17. char *local;        /* Local address */
  18. char *remote;        /* Remote address */
  19. int mode;        /* active/passive/server */
  20. int16 window;        /* Window size in bytes */
  21. void (*r_upcall)();    /* Receiver upcall handler */
  22. void (*t_upcall)();    /* Transmitter upcall handler */
  23. void (*s_upcall)();    /* State-change upcall handler */
  24. int user;        /* User linkage area */
  25. {
  26.     struct ax25_cb *axp;
  27.     char remtmp[AXALEN];
  28.  
  29.     if(remote == NULLCHAR){
  30.         remote = remtmp;
  31.         setcall(remote," ");
  32.     }
  33.     if((axp = find_ax25(remote)) != NULLAX25 && axp->state != LAPB_DISCONNECTED)
  34.         return NULLAX25;    /* Only one to a customer */
  35.     if(axp == NULLAX25 && (axp = cr_ax25(remote)) == NULLAX25)
  36.         return NULLAX25;
  37.     memcpy(axp->remote,remote,AXALEN);
  38.     memcpy(axp->local,local,AXALEN);
  39.     axp->iface = iface;
  40.     axp->window = window;
  41.     axp->r_upcall = r_upcall;
  42.     axp->t_upcall = t_upcall;
  43.     axp->s_upcall = s_upcall;
  44.     axp->user = user;
  45.  
  46.     switch(mode){
  47.     case AX_SERVER:
  48.         axp->flags.clone = 1;
  49.     case AX_PASSIVE:    /* Note fall-thru */
  50.         axp->state = LAPB_LISTEN;
  51.         return axp;
  52.     case AX_ACTIVE:
  53.         break;
  54.     }    
  55.     switch(axp->state){
  56.     case LAPB_DISCONNECTED:
  57.         est_link(axp);
  58.         lapbstate(axp,LAPB_SETUP);
  59.         break;
  60.     case LAPB_SETUP:
  61.         free_q(&axp->txq);
  62.         break;
  63.     case LAPB_DISCPENDING:    /* Ignore */
  64.         break;
  65.     case LAPB_RECOVERY:
  66.     case LAPB_CONNECTED:
  67.         free_q(&axp->txq);
  68.         est_link(axp);
  69.         lapbstate(axp,LAPB_SETUP);
  70.         break;
  71.     }
  72.     return axp;
  73. }
  74.  
  75. /* Send data on an AX.25 connection. Caller provides optional PID. If
  76.  * a PID is provided, then operate in stream mode, i.e., a large packet
  77.  * is automatically packetized into a series of paclen-sized data fields.
  78.  *
  79.  * If pid == -1, it is assumed the packet (which may actually be a queue
  80.  * of distinct packets) already has a PID on the front and it is passed
  81.  * through directly even if it is very large.
  82.  */
  83. int
  84. send_ax25(axp,bp,pid)
  85. struct ax25_cb *axp;
  86. struct mbuf *bp;
  87. int pid;
  88. {
  89.     struct mbuf *bp1;
  90.     int16 offset,len,size;
  91.  
  92.     if(axp == NULLAX25 || bp == NULLBUF)
  93.         return -1;
  94.  
  95.     if(pid != -1){
  96.         offset = 0;
  97.         len = len_p(bp);
  98.         /* It is important that all the pushdowns be done before
  99.          * any part of the original packet is freed.
  100.          * Otherwise the pushdown might erroneously overwrite
  101.          * a part of the packet that had been duped and freed.
  102.          */
  103.         while(len != 0){
  104.             size = min(len,axp->paclen);
  105.             dup_p(&bp1,bp,offset,size);
  106.             len -= size;
  107.             offset += size;
  108.             bp1 = pushdown(bp1,1);
  109.             bp1->data[0] = pid;
  110.             enqueue(&axp->txq,bp1);
  111.         }
  112.         free_p(bp);
  113.     } else {
  114.         enqueue(&axp->txq,bp);
  115.     }
  116.     return lapb_output(axp);
  117. }
  118.  
  119. /* Receive incoming data on an AX.25 connection */
  120. struct mbuf *
  121. recv_ax25(axp,cnt)
  122. struct ax25_cb *axp;
  123. int16 cnt;
  124. {
  125.     struct mbuf *bp;
  126.  
  127.     if(axp->rxq == NULLBUF)
  128.         return NULLBUF;
  129.  
  130.     if(cnt == 0){
  131.         /* This means we want it all */
  132.         bp = axp->rxq;
  133.         axp->rxq = NULLBUF;
  134.     } else {
  135.         bp = ambufw(cnt);
  136.         bp->cnt = pullup(&axp->rxq,bp->data,cnt);
  137.     }
  138.     /* If this has un-busied us, send a RR to reopen the window */
  139.     if(len_p(axp->rxq) < axp->window
  140.      && (len_p(axp->rxq) + bp->cnt) >= axp->window)
  141.         sendctl(axp,LAPB_RESPONSE,RR);
  142.  
  143.     return bp;
  144. }
  145.  
  146. /* Close an AX.25 connection */
  147. int
  148. disc_ax25(axp)
  149. struct ax25_cb *axp;
  150. {
  151.     if(axp == NULLAX25)
  152.         return -1;
  153.     switch(axp->state){
  154.     case LAPB_DISCONNECTED:
  155.         break;        /* Ignored */
  156.     case LAPB_LISTEN:
  157.         del_ax25(axp);
  158.         break;
  159.     case LAPB_DISCPENDING:
  160.         lapbstate(axp,LAPB_DISCONNECTED);
  161.         break;
  162.     case LAPB_CONNECTED:
  163.     case LAPB_RECOVERY:
  164.         free_q(&axp->txq);
  165.         axp->retries = 0;
  166.         sendctl(axp,LAPB_COMMAND,DISC|PF);
  167.         stop_timer(&axp->t3);
  168.         start_timer(&axp->t1);
  169.         lapbstate(axp,LAPB_DISCPENDING);
  170.         break;
  171.     }
  172.     return 0;
  173. }
  174.  
  175. /* Verify that axp points to a valid ax25 control block */
  176. int
  177. ax25val(axp)
  178. struct ax25_cb *axp;
  179. {
  180.     register struct ax25_cb *axp1;
  181.     register int i;
  182.  
  183.     if(axp == NULLAX25)
  184.         return 0;    /* Null pointer can't be valid */
  185.     for(i=0; i < NHASH; i++)
  186.         for(axp1 = Ax25_cb[i];axp1 != NULLAX25; axp1 = axp1->next)
  187.             if(axp1 == axp)
  188.                 return 1;
  189.     return 0;
  190. }
  191.  
  192. /* Force a retransmission */
  193. int
  194. kick_ax25(axp)
  195. struct ax25_cb *axp;
  196. {
  197.     if(!ax25val(axp))
  198.         return -1;
  199.     recover(axp);
  200.     return 0;
  201. }
  202.  
  203. /* Abruptly terminate an AX.25 connection */
  204. int
  205. reset_ax25(axp)
  206. struct ax25_cb *axp;
  207. {
  208.     void (*upcall)();
  209.  
  210.     if(axp == NULLAX25)
  211.         return -1;
  212.     upcall = axp->s_upcall;
  213.     lapbstate(axp,LAPB_DISCONNECTED);
  214.     /* Clean up if the standard upcall isn't in use */
  215.     if(upcall != s_ascall)
  216.         del_ax25(axp);
  217.     return 0;
  218. }
  219.