home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / ax25user.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  5KB  |  218 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.         free_p(bp);
  94.         return -1;
  95.     }
  96.     if(pid != -1){
  97.         offset = 0;
  98.         len = len_p(bp);
  99.         /* It is important that all the pushdowns be done before
  100.          * any part of the original packet is freed.
  101.          * Otherwise the pushdown might erroneously overwrite
  102.          * a part of the packet that had been duped and freed.
  103.          */
  104.         while(len != 0){
  105.             size = min(len,axp->paclen);
  106.             dup_p(&bp1,bp,offset,size);
  107.             len -= size;
  108.             offset += size;
  109.             bp1 = pushdown(bp1,1);
  110.             bp1->data[0] = pid;
  111.             enqueue(&axp->txq,bp1);
  112.         }
  113.         free_p(bp);
  114.     } else {
  115.         enqueue(&axp->txq,bp);
  116.     }
  117.     return lapb_output(axp);
  118. }
  119.  
  120. /* Receive incoming data on an AX.25 connection */
  121. struct mbuf *
  122. recv_ax25(axp,cnt)
  123. struct ax25_cb *axp;
  124. int16 cnt;
  125. {
  126.     struct mbuf *bp;
  127.  
  128.     if(axp->rxq == NULLBUF)
  129.         return NULLBUF;
  130.  
  131.     if(cnt == 0){
  132.         /* This means we want it all */
  133.         bp = axp->rxq;
  134.         axp->rxq = NULLBUF;
  135.     } else {
  136.         bp = ambufw(cnt);
  137.         bp->cnt = pullup(&axp->rxq,bp->data,cnt);
  138.     }
  139.     /* If this has un-busied us, send a RR to reopen the window */
  140.     if(len_p(axp->rxq) < axp->window
  141.      && (len_p(axp->rxq) + bp->cnt) >= axp->window)
  142.         sendctl(axp,LAPB_RESPONSE,RR);
  143.  
  144.     return bp;
  145. }
  146.  
  147. /* Close an AX.25 connection */
  148. int
  149. disc_ax25(axp)
  150. struct ax25_cb *axp;
  151. {
  152.     if(axp == NULLAX25)
  153.         return -1;
  154.     switch(axp->state){
  155.     case LAPB_DISCONNECTED:
  156.         break;        /* Ignored */
  157.     case LAPB_LISTEN:
  158.         del_ax25(axp);
  159.         break;
  160.     case LAPB_DISCPENDING:
  161.         lapbstate(axp,LAPB_DISCONNECTED);
  162.         break;
  163.     case LAPB_CONNECTED:
  164.     case LAPB_RECOVERY:
  165.         free_q(&axp->txq);
  166.         axp->retries = 0;
  167.         sendctl(axp,LAPB_COMMAND,DISC|PF);
  168.         stop_timer(&axp->t3);
  169.         start_timer(&axp->t1);
  170.         lapbstate(axp,LAPB_DISCPENDING);
  171.         break;
  172.     }
  173.     return 0;
  174. }
  175.  
  176. /* Verify that axp points to a valid ax25 control block */
  177. int
  178. ax25val(axp)
  179. struct ax25_cb *axp;
  180. {
  181.     register struct ax25_cb *axp1;
  182.  
  183.     if(axp == NULLAX25)
  184.         return 0;    /* Null pointer can't be valid */
  185.     for(axp1 = Ax25_cb;axp1 != NULLAX25; axp1 = axp1->next)
  186.         if(axp1 == axp)
  187.             return 1;
  188.     return 0;
  189. }
  190.  
  191. /* Force a retransmission */
  192. int
  193. kick_ax25(axp)
  194. struct ax25_cb *axp;
  195. {
  196.     if(!ax25val(axp))
  197.         return -1;
  198.     recover(axp);
  199.     return 0;
  200. }
  201.  
  202. /* Abruptly terminate an AX.25 connection */
  203. int
  204. reset_ax25(axp)
  205. struct ax25_cb *axp;
  206. {
  207.     void (*upcall)();
  208.  
  209.     if(axp == NULLAX25)
  210.         return -1;
  211.     upcall = axp->s_upcall;
  212.     lapbstate(axp,LAPB_DISCONNECTED);
  213.     /* Clean up if the standard upcall isn't in use */
  214.     if(upcall != s_ascall)
  215.         del_ax25(axp);
  216.     return 0;
  217. }
  218.