home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / axsock.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  11KB  |  516 lines

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