home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / AXSOCK.C < prev    next >
C/C++ Source or Header  |  1992-05-11  |  11KB  |  517 lines

  1. #include <errno.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "socket.h"
  6. #include "usock.h"
  7.  
  8. char Ax25_eol[] = "\r";
  9.  
  10. static void autobind __ARGS((struct usock *up));
  11.  
  12. /* The following two variables are needed because there can be only one
  13.  * socket listening on each of the AX.25 modes (I and UI)
  14.  */
  15. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  16. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  17. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  18.  
  19. /* Function that handles incoming UI frames from lapb.c */
  20. void
  21. beac_input(iface,src,bp)
  22. struct iface *iface;
  23. char *src;
  24. struct mbuf *bp;
  25. {
  26.     struct mbuf *hdr;
  27.     struct sockaddr_ax *sax;
  28.  
  29.     if(Axui_sock == -1){
  30.         /* Nobody there to read it */
  31.         free_p(bp);
  32.     } else {
  33.         hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax));
  34.         sax = (struct sockaddr_ax *)hdr->data;
  35.         sax->sax_family = AF_AX25;
  36.         memcpy(sax->ax25_addr,src,AXALEN);
  37.         strncpy(sax->iface,iface->name,ILEN);
  38.         hdr->next = bp;
  39.         enqueue(&Bcq,hdr);
  40.     }
  41. }
  42. int
  43. so_ax_sock(up,protocol)
  44. struct usock *up;
  45. int protocol;
  46. {
  47.     return 0;
  48. }
  49. int
  50. so_axui_sock(up,protocol)
  51. struct usock *up;
  52. int protocol;
  53. {
  54.     return 0;
  55. }
  56.  
  57. int
  58. so_axui_bind(up)
  59. struct usock *up;
  60. {
  61.     if(Axui_sock != -1){
  62.         errno = EADDRINUSE;
  63.         return -1;
  64.     }
  65.     Axui_sock = up->index;
  66.     return 0;
  67. }
  68. int
  69. so_ax_listen(up,backlog)
  70. struct usock *up;
  71. int backlog;
  72. {
  73.     struct sockaddr_ax *local;
  74.  
  75.     if(up->name == NULLCHAR)
  76.         autobind(up);
  77.     if(up != itop(Axi_sock)){
  78.         errno = EOPNOTSUPP;
  79.         return -1;
  80.     }
  81.     local = (struct sockaddr_ax *)up->name;
  82.     up->cb.ax25 = open_ax25(NULLIF,local->ax25_addr,NULLCHAR,
  83.      backlog ? AX_SERVER:AX_PASSIVE,0,
  84.      s_arcall,s_atcall,s_ascall,Axi_sock);
  85.     return 0;
  86. }
  87. int
  88. so_ax_conn(up)
  89. struct usock *up;
  90. {
  91.     struct sockaddr_ax *local,*remote,localtmp;
  92.     struct ax25_cb *ax25;
  93.     struct iface *iface;
  94.     int s;
  95.  
  96.     s = up->index;
  97.     remote = (struct sockaddr_ax *)up->peername;
  98.     if((iface = if_lookup(remote->iface)) == NULLIF){
  99.         errno = EINVAL;
  100.         return -1;
  101.     }
  102.     local = (struct sockaddr_ax *)up->name;
  103.     if(local == NULL){
  104.         /* The local address was unspecified; set it from
  105.          * the interface we'll use
  106.          */
  107.         localtmp.sax_family = AF_AX25;
  108.         memcpy(localtmp.ax25_addr,iface->hwaddr,AXALEN);
  109.         memcpy(localtmp.iface,remote->iface,ILEN);
  110.         bind(s,(char *)&localtmp,sizeof(localtmp));
  111.         local = (struct sockaddr_ax *)up->name;
  112.     }
  113.     /* If we already have an AX25 link we can use it */
  114.     if((up->cb.ax25 = find_ax25(remote->ax25_addr)) != NULLAX25
  115.        && up->cb.ax25->state != LAPB_DISCONNECTED &&
  116.        up->cb.ax25->user == -1) {
  117.         up->cb.ax25->user = s;
  118.         up->cb.ax25->r_upcall = s_arcall;
  119.         up->cb.ax25->t_upcall = s_atcall;
  120.         up->cb.ax25->s_upcall = s_ascall;
  121.         if(up->cb.ax25->state == LAPB_CONNECTED
  122.            || up->cb.ax25->state == LAPB_RECOVERY)
  123.                 return 0;
  124.     } else {
  125.         up->cb.ax25 = open_ax25(iface,local->ax25_addr,
  126.          remote->ax25_addr,AX_ACTIVE,
  127.          Axwindow,s_arcall,s_atcall,s_ascall,s);
  128.     }
  129.     /* Wait for the connection to complete */
  130.     while((ax25 = up->cb.ax25) != NULLAX25 && ax25->state != LAPB_CONNECTED){
  131.         if(up->noblock){
  132.             errno = EWOULDBLOCK;
  133.             return -1;
  134.         } else if((errno = pwait(up)) != 0){
  135.             return -1;
  136.         }
  137.     }
  138.     if(ax25 == NULLAX25){
  139.         /* Connection probably already exists */
  140.         free(up->peername);
  141.         up->peername = NULLCHAR;
  142.         errno = ECONNREFUSED;
  143.         return -1;
  144.     }
  145.     return 0;
  146. }
  147. int
  148. so_axui_conn(up)
  149. struct usock *up;
  150. {
  151.     if(up->name == NULLCHAR)
  152.         autobind(up);
  153.     return 0;
  154. }
  155.  
  156. int
  157. so_ax_recv(up,bpp,from,fromlen)
  158. struct usock *up;
  159. struct mbuf **bpp;
  160. char *from;
  161. int *fromlen;
  162. {
  163.     struct ax25_cb *ax25;
  164.     int cnt;
  165.     
  166.     while((ax25 = up->cb.ax25) != NULLAX25
  167.      && (*bpp = recv_ax25(ax25,(int16)0)) == NULLBUF){
  168.         if(up->noblock){
  169.             errno = EWOULDBLOCK;
  170.             return -1;
  171.         } else if((errno = pwait(up)) != 0){
  172.             return -1;
  173.         }
  174.     }
  175.     if(ax25 == NULLAX25){
  176.         /* Connection went away */
  177.         errno = ENOTCONN;
  178.         return -1;
  179.     }
  180.     cnt = (*bpp)->cnt;
  181.     return cnt;
  182. }
  183. int
  184. so_axui_recv(up,bpp,from,fromlen)
  185. struct usock *up;
  186. struct mbuf **bpp;
  187. char *from;
  188. int *fromlen;
  189. {
  190.     int s;
  191.  
  192.     s = up->index;
  193.  
  194.     while(s == Axui_sock && Bcq == NULLBUF){
  195.         if(up->noblock){
  196.             errno = EWOULDBLOCK;
  197.             return -1;
  198.         } else if((errno = pwait(&Bcq)) != 0){
  199.             return -1;
  200.         }
  201.     }
  202.     if(s != Axui_sock){
  203.         errno = ENOTCONN;
  204.         return -1;
  205.     }
  206.     *bpp = dequeue(&Bcq);
  207.  
  208.     if(from != NULLCHAR && fromlen != NULLINT
  209.        && *fromlen >= sizeof(struct sockaddr_ax)){
  210.         pullup(bpp,from,sizeof(struct sockaddr_ax));
  211.         *fromlen = sizeof(struct sockaddr_ax);
  212.     } else {
  213.         pullup(bpp,NULLCHAR,sizeof(struct sockaddr_ax));
  214.     }
  215.     return len_p(*bpp);
  216. }
  217. int    
  218. so_ax_send(up,bp,to)
  219. struct usock *up;
  220. struct mbuf *bp;
  221. char *to;
  222. {
  223.     struct ax25_cb *ax25;
  224.  
  225.     if((ax25 = up->cb.ax25) == NULLAX25){
  226.         free_p(bp);
  227.         errno = ENOTCONN;
  228.         return -1;
  229.     }
  230.     send_ax25(ax25,bp,PID_NO_L3);
  231.  
  232.     while((ax25 = up->cb.ax25) != NULLAX25 &&
  233.      len_q(ax25->txq) * ax25->paclen > ax25->window){
  234.         if(up->noblock){
  235.             errno = EWOULDBLOCK;
  236.             return -1;
  237.         } else if((errno = pwait(up)) != 0){
  238.             return -1;
  239.         }
  240.     }
  241.     if(ax25 == NULLAX25){
  242.         errno = EBADF;
  243.         return -1;
  244.     }
  245.     return 0;
  246. }
  247. int    
  248. so_axui_send(up,bp,to)
  249. struct usock *up;
  250. struct mbuf *bp;
  251. char *to;
  252. {
  253.     struct sockaddr_ax *local,*remote;
  254.  
  255.     local = (struct sockaddr_ax *)up->name;
  256.     if(to != NULLCHAR)
  257.         remote = (struct sockaddr_ax *)to;
  258.     else if(up->peername != NULLCHAR){
  259.         remote = (struct sockaddr_ax *)up->peername;
  260.     } else {
  261.         free_p(bp);
  262.         errno = ENOTCONN;
  263.         return -1;
  264.     }
  265.     ax_output(if_lookup(remote->iface),remote->ax25_addr,
  266.       local->ax25_addr,PID_NO_L3,bp);
  267.     return 0;
  268. }
  269.  
  270. int
  271. so_ax_qlen(up,rtx)
  272. struct usock *up;
  273. int rtx;
  274. {
  275.     int len;
  276.  
  277.     if(up->cb.ax25 == NULLAX25){
  278.         errno = ENOTCONN;
  279.         return -1;
  280.     }
  281.     switch(rtx){
  282.     case 0:
  283.         len = len_p(up->cb.ax25->rxq);
  284.         break;
  285.     case 1:    /* Number of packets, not bytes */
  286.         len = len_q(up->cb.ax25->txq);
  287.     }
  288.     return len;
  289. }
  290. int
  291. so_axui_qlen(up,rtx)
  292. struct usock *up;
  293. int rtx;
  294. {
  295.     int len;
  296.  
  297.     switch(rtx){    
  298.     case 0:
  299.         len = len_q(Bcq);
  300.         break;
  301.     case 1:
  302.         len = 0;        
  303.         break;
  304.     }
  305.     return len;
  306. }
  307. int
  308. so_ax_kick(up)
  309. struct usock *up;
  310. {
  311.     if(up->cb.ax25 != NULLAX25)
  312.         kick_ax25(up->cb.ax25);
  313.     return 0;
  314. }
  315. int
  316. so_ax_shut(up,how)
  317. struct usock *up;
  318. int how;
  319. {
  320.     if(up->cb.ax25 == NULLAX25)
  321.         return 0;
  322.     switch(how){
  323.     case 0:
  324.     case 1:    /* Attempt regular disconnect */
  325.         disc_ax25(up->cb.ax25);
  326.         break;
  327.     case 2: /* Blow it away */
  328.         reset_ax25(up->cb.ax25);
  329.         up->cb.ax25 = NULLAX25;
  330.         break;
  331.     }
  332.     return 0;    
  333. }
  334. int
  335. so_ax_close(up)
  336. struct usock *up;
  337. {
  338.     if(up->cb.ax25 != NULLAX25){
  339.         /* Tell the CLOSED upcall there's no more socket */
  340.         up->cb.ax25->user = -1;
  341.         disc_ax25(up->cb.ax25);
  342.     }
  343.     return 0;
  344. }
  345. int
  346. so_axui_close(up)
  347. struct usock *up;
  348. {
  349.     Axui_sock = -1;
  350.     free_q(&Bcq);
  351.     psignal(&Bcq,0);    /* Unblock any reads */
  352.     return 0;
  353. }
  354. /* AX.25 receive upcall */
  355. void
  356. s_arcall(axp,cnt)
  357. struct ax25_cb *axp;
  358. int cnt;
  359. {
  360.     int ns;
  361.     struct usock *up,*nup,*oup;
  362.     union sp sp;
  363.  
  364.     up = itop(axp->user);
  365.     /* When AX.25 data arrives for the first time the AX.25 listener
  366.        is notified, if active. If the AX.25 listener is a server its
  367.        socket is duplicated in the same manner as in s_tscall().
  368.      */
  369.     if (Axi_sock != -1 && axp->user == -1) {
  370.         oup = up = itop(Axi_sock);
  371.         /* From now on, use the same upcalls as the listener */
  372.         axp->t_upcall = up->cb.ax25->t_upcall;
  373.         axp->r_upcall = up->cb.ax25->r_upcall;
  374.         axp->s_upcall = up->cb.ax25->s_upcall;
  375.         if (up->cb.ax25->flags.clone) {
  376.             /* Clone the socket */
  377.             ns = socket(AF_AX25,SOCK_STREAM,0);
  378.             nup = itop(ns);
  379.             ASSIGN(*nup,*up);
  380.             axp->user = ns;
  381.             nup->cb.ax25 = axp;
  382.             /* Allocate new memory for the name areas */
  383.             nup->name = mallocw(sizeof(struct sockaddr_ax));
  384.             nup->peername = mallocw(sizeof(struct sockaddr_ax));
  385.             /* Store the new socket # in the old one */
  386.             up->rdysock = ns;
  387.             up = nup;
  388.         } else {
  389.             axp->user = Axi_sock;
  390.             del_ax25(up->cb.ax25);
  391.             up->cb.ax25 = axp;
  392.             /* Allocate space for the peer's name */
  393.             up->peername = mallocw(sizeof(struct sockaddr_ax));
  394.             /* Store the old socket # in the old socket */
  395.             up->rdysock = Axi_sock;
  396.         }
  397.         /* Load the addresses. Memory for the name has already
  398.          * been allocated, either above or in the original bind.
  399.          */
  400.         sp.p = up->name;
  401.         sp.ax->sax_family = AF_AX25;
  402.         memcpy(sp.ax->ax25_addr,axp->local,AXALEN);
  403.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  404.         up->namelen = sizeof(struct sockaddr_ax);
  405.  
  406.         sp.p = up->peername;
  407.         sp.ax->sax_family = AF_AX25;
  408.         memcpy(sp.ax->ax25_addr,axp->remote,AXALEN);
  409.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  410.         up->peernamelen = sizeof(struct sockaddr_ax);
  411.         /* Wake up the guy accepting it, and let him run */
  412.         psignal(oup,1);
  413.         pwait(NULL);
  414.         return;
  415.     }
  416.     /* Wake up anyone waiting, and let them run */
  417.     psignal(up,1);
  418.     pwait(NULL);
  419. }
  420. /* AX.25 transmit upcall */
  421. void
  422. s_atcall(axp,cnt)
  423. struct ax25_cb *axp;
  424. int cnt;
  425. {
  426.     /* Wake up anyone waiting, and let them run */
  427.     psignal(itop(axp->user),1);
  428.     pwait(NULL);
  429. }
  430. /* AX25 state change upcall routine */
  431. void
  432. s_ascall(axp,old,new)
  433. register struct ax25_cb *axp;
  434. int old,new;
  435. {
  436.     int s;
  437.     struct usock *up;
  438.  
  439.     s = axp->user;
  440.     up = itop(s);
  441.  
  442.     switch(new){
  443.     case LAPB_DISCONNECTED:
  444.         /* Clean up. If the user has already closed the socket,
  445.          * then up will be null (s was set to -1 by the close routine).
  446.          * If not, then this is an abnormal close (e.g., a reset)
  447.          * and clearing out the pointer in the socket structure will
  448.          * prevent any further operations on what will be a freed
  449.          * control block. Also wake up anybody waiting on events
  450.          * related to this block so they will notice it disappearing.
  451.          */
  452.         if(up != NULLUSOCK){
  453.             up->errcodes[0] = axp->reason;
  454.             up->cb.ax25 = NULLAX25;
  455.         }
  456.         del_ax25(axp);
  457.         break;
  458.     default:    /* Other transitions are ignored */
  459.         break;
  460.     }
  461.     psignal(up,0);    /* In case anybody's waiting */
  462. }
  463.  
  464. /* Issue an automatic bind of a local AX25 address */
  465. static void
  466. autobind(up)
  467. struct usock *up;
  468. {
  469.     struct sockaddr_ax local;
  470.     int s;
  471.  
  472.     s = up->index;
  473.     local.sax_family = AF_AX25;
  474.     memcpy(local.ax25_addr,Mycall,AXALEN);
  475.     bind(s,(char *)&local,sizeof(struct sockaddr_ax));
  476. }
  477. int
  478. checkaxaddr(name,namelen)
  479. char *name;
  480. int namelen;
  481. {
  482.     struct sockaddr_ax *sock;
  483.  
  484.     sock = (struct sockaddr_ax *)name;
  485.     if(sock->sax_family != AF_AX25 || namelen != sizeof(struct sockaddr_ax))
  486.         return -1;
  487.     return 0;
  488. }
  489. char *
  490. axpsocket(p)
  491. struct sockaddr *p;
  492. {
  493.     struct sockaddr_ax *axp;
  494.     static char buf[30];
  495.     char tmp[11];
  496.  
  497.     axp = (struct sockaddr_ax *)p;
  498.     pax25(tmp,axp->ax25_addr);
  499.     if(strlen(axp->iface) != 0)
  500.         sprintf(buf,"%s on %s",tmp,axp->iface);
  501.     else
  502.         strcpy(buf,tmp);
  503.     return buf;
  504. }
  505. char *
  506. axstate(up)
  507. struct usock *up;
  508. {
  509.     return Ax25states[up->cb.ax25->state];    
  510. }
  511. so_ax_stat(up)
  512. struct usock *up;
  513. {
  514.     st_ax25(up->cb.ax25);
  515.     return 0;
  516. }
  517.