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

  1. #include <errno.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "netrom.h"
  6. #include "nr4.h"
  7. #include "socket.h"
  8. #include "usock.h"
  9.  
  10. static void autobind __ARGS((struct usock *up));
  11. static void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  12. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  13. static void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  14.  
  15. int
  16. so_n3_sock(up,protocol)
  17. struct usock *up;
  18. int protocol;
  19. {
  20.     up->cb.rnr = raw_nr((char)protocol);    
  21.     return 0;
  22. }
  23. int
  24. so_n4_sock(up,protocol)
  25. struct usock *up;
  26. int protocol;
  27. {
  28.     return 0;
  29. }
  30. int
  31. so_n4_listen(up,backlog)
  32. struct usock *up;
  33. int backlog;
  34. {
  35.     struct sockaddr_nr *local;
  36.     int s;
  37.  
  38.     s = up->index;
  39.     if(up->name == NULLCHAR)
  40.         autobind(up);
  41.     local = (struct sockaddr_nr *)up->name;
  42.     up->cb.nr4 = open_nr4(&local->nr_addr,NULLNRADDR,
  43.      backlog ? AX_SERVER:AX_PASSIVE,s_nrcall,s_ntcall,s_nscall,s);
  44.     return 0;
  45. }
  46. int
  47. so_n3_conn(up)
  48. struct usock *up;
  49. {
  50.     if(up->name != NULLCHAR)
  51.         autobind(up);
  52.     return 0;
  53. }
  54. int
  55. so_n4_conn(up)
  56. struct usock *up;
  57. {
  58.     struct sockaddr_nr *local,*remote;
  59.     struct nr4cb *nr4;
  60.     int s;
  61.     
  62.     s = up->index;
  63.     if(up->name != NULLCHAR)
  64.         autobind(up);
  65.     local = (struct sockaddr_nr *)up->name;
  66.     remote = (struct sockaddr_nr *)up->peername;
  67.     up->cb.nr4 = open_nr4(&local->nr_addr,&remote->nr_addr,
  68.      AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  69.  
  70.     /* Wait for the connection to complete */
  71.     while((nr4 = up->cb.nr4) != NULLNR4CB && nr4->state != NR4STCON){
  72.         if(up->noblock){
  73.             errno = EWOULDBLOCK;
  74.             return -1;
  75.         } else if((errno = pwait(up)) != 0){
  76.             return -1;
  77.         }
  78.     }
  79.     if(nr4 == NULLNR4CB){
  80.         /* Connection probably already exists */
  81.         free(up->peername);
  82.         up->peername = NULLCHAR;
  83.         errno = ECONNREFUSED;
  84.         return -1;
  85.     }
  86.     return 0;
  87. }
  88. int
  89. so_n3_recv(up,bpp,from,fromlen)
  90. struct usock *up;
  91. struct mbuf **bpp;
  92. char *from;
  93. int *fromlen;
  94. {
  95.     int cnt;
  96.     struct raw_nr *rnr;
  97.     struct sockaddr_nr *remote;
  98.     struct nr3hdr n3hdr;
  99.  
  100.     while((rnr = up->cb.rnr) != NULLRNR
  101.      && rnr->rcvq == NULLBUF){
  102.         if(up->noblock){
  103.             errno = EWOULDBLOCK;
  104.             return -1;
  105.         } else if((errno = pwait(up)) != 0){
  106.             return -1;
  107.         }
  108.     }
  109.     if(rnr == NULLRNR){
  110.         /* Connection went away */
  111.         errno = ENOTCONN;
  112.         return -1;
  113.     }
  114.     *bpp = dequeue(&rnr->rcvq);
  115.     ntohnr3(&n3hdr,bpp);
  116.     cnt = len_p(*bpp);
  117.     if(from != NULLCHAR && fromlen != NULLINT
  118.        && *fromlen >= sizeof(struct sockaddr_nr)){
  119.         remote = (struct sockaddr_nr *)from;
  120.         remote->nr_family = AF_NETROM;
  121.         /* The callsign of the local user is not part of
  122.            NET/ROM level 3, so that field is not used here */
  123.         memcpy(remote->nr_addr.node,n3hdr.source,AXALEN);
  124.         *fromlen = sizeof(struct sockaddr_nr);
  125.     }
  126.     return cnt;
  127. }
  128. int
  129. so_n4_recv(up,bpp,from,fromlen)
  130. struct usock *up;
  131. struct mbuf **bpp;
  132. char *from;
  133. int *fromlen;
  134. {
  135.     struct nr4cb *nr4;
  136.  
  137.     while((nr4 = up->cb.nr4) != NULLNR4CB
  138.      && (*bpp = recv_nr4(nr4,(int16)0)) == NULLBUF){
  139.         if(up->noblock){
  140.             errno = EWOULDBLOCK;
  141.             return -1;
  142.         } else if((errno = pwait(up)) != 0){
  143.             return -1;
  144.         }
  145.     }
  146.     if(nr4 == NULLNR4CB){
  147.         /* Connection went away */
  148.         errno = ENOTCONN;
  149.         return -1;
  150.     }
  151.     return (*bpp)->cnt;
  152. }
  153. int
  154. so_n3_send(up,bp,to)
  155. struct usock *up;
  156. struct mbuf *bp;
  157. char *to;
  158. {
  159.     struct sockaddr_nr *remote;
  160.  
  161.     if(len_p(bp) > NR4MAXINFO) {
  162.         free_p(bp);
  163.         errno = EMSGSIZE;
  164.         return -1;
  165.     }
  166.     if(to != NULLCHAR) {
  167.         remote = (struct sockaddr_nr *)to;
  168.     } else if(up->peername != NULLCHAR) {
  169.         remote = (struct sockaddr_nr *)up->peername;
  170.     } else {
  171.         free_p(bp);
  172.         errno = ENOTCONN;
  173.         return -1;
  174.     }    
  175.     /* The NETROM username is always ignored in outgoing traffic */
  176.     nr_sendraw(remote->nr_addr.node,up->cb.rnr->protocol,
  177.      up->cb.rnr->protocol,bp);
  178.     return 0;
  179. }
  180. int
  181. so_n4_send(up,bp,to)
  182. struct usock *up;
  183. struct mbuf *bp;
  184. char *to;
  185. {
  186.     struct nr4cb *nr4;
  187.  
  188.     if((nr4 = up->cb.nr4) == NULLNR4CB) {
  189.         free_p(bp);
  190.         errno = ENOTCONN;
  191.         return -1;
  192.     }
  193.     if(len_p(bp) > NR4MAXINFO){ /* reject big packets */
  194.         free_p(bp);
  195.         errno = EMSGSIZE;
  196.         return -1;
  197.     }
  198.     send_nr4(nr4,bp);
  199.  
  200.     while((nr4 = up->cb.nr4) != NULLNR4CB && nr4->nbuffered >= nr4->window){
  201.         if(up->noblock){
  202.             errno = EWOULDBLOCK;
  203.             return -1;
  204.         } else if((errno = pwait(up)) != 0){
  205.             return -1;
  206.         }
  207.     }
  208.     if(nr4 == NULLNR4CB){
  209.         errno = EBADF;
  210.         return -1;
  211.     }
  212.     return 0;
  213. }
  214.  
  215. int
  216. so_n3_qlen(up,rtx)
  217. struct usock *up;
  218. int rtx;
  219. {
  220.     int len;
  221.  
  222.     switch(rtx){    
  223.     case 0:
  224.         len = len_q(up->cb.rnr->rcvq);
  225.         break;
  226.     case 1:
  227.         len = 0;        
  228.     }
  229.     return len;
  230. }
  231. int
  232. so_n4_qlen(up,rtx)
  233. struct usock *up;
  234. int rtx;
  235. {
  236.     int len;
  237.  
  238.     switch(rtx){
  239.     case 0:
  240.         len = len_p(up->cb.nr4->rxq);
  241.         break;
  242.     case 1:    /* Number of packets, not bytes */
  243.         len = len_q(up->cb.nr4->txq);
  244.         break;
  245.     }
  246.     return len;
  247. }
  248. int
  249. so_n4_kick(up)
  250. struct usock *up;
  251. {
  252.     if(up->cb.nr4 == NULLNR4CB){
  253.         errno = ENOTCONN;
  254.         return -1;
  255.     }
  256.     kick_nr4(up->cb.nr4);
  257.     return 0;
  258. }
  259. int
  260. so_n4_shut(up,how)
  261. struct usock *up;
  262. int how;
  263. {
  264.     switch(how){
  265.     case 0:
  266.     case 1:    /* Attempt regular disconnect */
  267.         disc_nr4(up->cb.nr4);
  268.         break;
  269.     case 2: /* Blow it away */
  270.         reset_nr4(up->cb.nr4);
  271.         up->cb.nr4 = NULLNR4CB;
  272.         break;
  273.     }
  274.     return 0;
  275. }
  276. int
  277. so_n3_close(up)
  278. struct usock *up;
  279. {
  280.     del_rnr(up->cb.rnr);
  281.     return 0;
  282. }
  283. int
  284. so_n4_close(up)
  285. struct usock *up;
  286. {
  287.     if(up->cb.nr4 != NULLNR4CB){
  288.         /* Tell the TCP_CLOSED upcall there's no more socket */
  289.         up->cb.nr4->user = -1;
  290.         disc_nr4(up->cb.nr4);
  291.     }
  292.     return 0;
  293. }
  294.  
  295.  
  296. /* Issue an automatic bind of a local NETROM address */
  297. static void
  298. autobind(up)
  299. struct usock *up;
  300. {
  301.     struct sockaddr_nr local;
  302.     int s;
  303.  
  304.     s = up->index;
  305.     local.nr_family = AF_NETROM;
  306.     memcpy(local.nr_addr.user,Mycall,AXALEN);
  307.     memcpy(local.nr_addr.node,Mycall,AXALEN);
  308.     bind(s,(char *)&local,sizeof(struct sockaddr_nr));
  309. }
  310.  
  311. /* NET/ROM receive upcall routine */
  312. static void
  313. s_nrcall(cb,cnt)
  314. struct nr4cb *cb;
  315. int cnt;
  316. {
  317.     /* Wake up anybody waiting for data, and let them run */
  318.     psignal(itop(cb->user),1);
  319.     pwait(NULL);
  320. }
  321. /* NET/ROM transmit upcall routine */
  322. static void
  323. s_ntcall(cb,cnt)
  324. struct nr4cb *cb;
  325. int cnt;
  326. {
  327.     /* Wake up anybody waiting to send data, and let them run */
  328.     psignal(itop(cb->user),1);
  329.     pwait(NULL);
  330. }
  331. /* NET/ROM state change upcall routine */
  332. static void
  333. s_nscall(cb,old,new)
  334. struct nr4cb *cb;
  335. int old,new;
  336. {
  337.     int s,ns;
  338.     struct usock *up,*nup,*oup;
  339.     union sp sp;
  340.  
  341.     s = cb->user;
  342.     oup = up = itop(s);
  343.  
  344.      if(new == NR4STDISC && up != NULLUSOCK){
  345.         /* Clean up. If the user has already closed the socket,
  346.          * then up will be null (s was set to -1 by the close routine).
  347.          * If not, then this is an abnormal close (e.g., a reset)
  348.          * and clearing out the pointer in the socket structure will
  349.          * prevent any further operations on what will be a freed
  350.          * control block. Also wake up anybody waiting on events
  351.          * related to this cb so they will notice it disappearing.
  352.          */
  353.          up->cb.nr4 = NULLNR4CB;
  354.          up->errcodes[0] = cb->dreason;
  355.      }
  356.      if(new == NR4STCON && old == NR4STDISC){
  357.         /* Handle an incoming connection. If this is a server cb,
  358.          * then we're being handed a "clone" cb and we need to
  359.          * create a new socket structure for it. In either case,
  360.          * find out who we're talking to and wake up the guy waiting
  361.          * for the connection.
  362.          */
  363.         if(cb->clone){
  364.             /* Clone the socket */
  365.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  366.             nup = itop(ns);
  367.             ASSIGN(*nup,*up);
  368.             cb->user = ns;
  369.             nup->cb.nr4 = cb;
  370.             cb->clone = 0; /* to avoid getting here again */
  371.             /* Allocate new memory for the name areas */
  372.             nup->name = mallocw(sizeof(struct sockaddr_nr));
  373.             nup->peername = mallocw(sizeof(struct sockaddr_nr));
  374.             /* Store the new socket # in the old one */
  375.             up->rdysock = ns;
  376.             up = nup;
  377.             s = ns;
  378.         } else {
  379.             /* Allocate space for the peer's name */
  380.             up->peername = mallocw(sizeof(struct sockaddr_nr));
  381.             /* Store the old socket # in the old socket */
  382.             up->rdysock = s;
  383.         }
  384.         /* Load the addresses. Memory for the name has already
  385.          * been allocated, either above or in the original bind.
  386.          */
  387.         sp.p = up->name;
  388.         sp.nr->nr_family = AF_NETROM;
  389.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  390.         up->namelen = sizeof(struct sockaddr_nr);
  391.  
  392.         sp.p = up->peername;
  393.         sp.nr->nr_family = AF_NETROM;
  394.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  395.         up->peernamelen = sizeof(struct sockaddr_nr);
  396.  
  397.         /* Wake up the guy accepting it, and let him run */
  398.         psignal(oup,1);
  399.         pwait(NULL);
  400.     }
  401.      /* Ignore all other state transitions */    
  402.     psignal(up,0);    /* In case anybody's waiting */
  403. }
  404.  
  405. int
  406. checknraddr(name,namelen)
  407. char *name;
  408. int namelen;
  409. {
  410.     struct sockaddr_nr *sock;
  411.  
  412.     sock = (struct sockaddr_nr *)name;
  413.     if(sock->nr_family != AF_NETROM || namelen != sizeof(struct sockaddr_nr))
  414.         return -1;
  415.     return 0;
  416. }
  417. char *
  418. nrpsocket(p)
  419. struct sockaddr *p;
  420. {
  421.     struct sockaddr_nr *nrp;
  422.     static char buf[30];
  423.     char tmp[11];
  424.  
  425.     nrp = (struct sockaddr_nr *)p;
  426.     pax25(tmp,nrp->nr_addr.user);
  427.     sprintf(buf,"%s @ ",tmp);
  428.     pax25(tmp,nrp->nr_addr.node);
  429.     strcat(buf,tmp);
  430.  
  431.     return buf;
  432. }
  433. char *
  434. nrstate(up)
  435. struct usock *up;
  436. {
  437.     return Nr4states[up->cb.nr4->state];
  438. }
  439. int
  440. so_n4_stat(up)
  441. struct usock *up;
  442. {
  443.     donrdump(up->cb.nr4);
  444.     return 0;
  445. }
  446.  
  447.