ax25user.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:5k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

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