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

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