home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / SOCKET.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  67KB  |  2,270 lines

  1. /* Application programming interface routines - based loosely on the
  2.  * "socket" model in Berkeley UNIX.
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <time.h>
  7. #ifdef  __STDC__
  8. #include <stdarg.h>
  9. #endif
  10. #include "global.h"
  11. #include "mbuf.h"
  12. #include "netuser.h"
  13. #include "timer.h"
  14. #include "iface.h"
  15. #include "ip.h"
  16. #include "tcp.h"
  17. #include "udp.h"
  18. #include "ax25.h"
  19. #include "lapb.h"
  20. #include "netrom.h"
  21. #include "nr4.h"
  22. #include "proc.h"
  23. #include "lzw.h"
  24. #include "usock.h"
  25. #include "socket.h"
  26.   
  27. /* In connect(), accept() and recv_mbuf()
  28.  * the noblock options have been removed, since they never occur anyway.
  29.  * If you want then back, do a '#define useblock 1'
  30.  * The socket's 'noblock' parameter is now only effective for sending
  31.  * data; ie if set, only sending data will not block. - WG7J
  32.  */
  33.   
  34.   
  35. static void autobind __ARGS((int s,int af));
  36. static int checkaddr __ARGS((int type,char *name,int namelen));
  37. static void rip_recv __ARGS((struct raw_ip *rp));
  38. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  39. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  40. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  41. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  42. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  43. #ifdef  NETROM
  44. static void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  45. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  46. static void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  47. #endif
  48. static struct usock *addsocket(void);
  49. static void deletesocket(int s);
  50.   
  51. static int16 Lport = 1024;
  52.   
  53. char *Socktypes[] = {
  54.     "Not Used",
  55.     "TCP",
  56.     "UDP",
  57.     "AX25 I",
  58.     "AX25 UI",
  59.     "Raw IP",
  60.     "NETROM3",
  61.     "NETROM",
  62.     "Loc St",
  63.     "Loc Dg"
  64. };
  65. char Badsocket[] = "Bad socket";
  66.   
  67. /* The following two variables are needed because there can be only one
  68.  * socket listening on each of the AX.25 modes (I and UI)
  69.  */
  70. #ifdef  AX25
  71. int Axi_sock = -1;  /* Socket number listening for AX25 connections */
  72.   
  73. #ifdef notdef
  74. static int Axui_sock = -1;  /* Socket number listening for AX25 UI frames */
  75. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  76.   
  77. /* Function that handles incoming UI frames from lapb.c */
  78. void
  79. beac_input(iface,src,bp)
  80. struct iface *iface;
  81. char *src;
  82. struct mbuf *bp;
  83. {
  84.     struct mbuf *hdr;
  85.     struct sockaddr_ax *sax;
  86.   
  87.     if(Axui_sock == -1){
  88.         /* Nobody there to read it */
  89.         free_p(bp);
  90.     } else {
  91.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  92.             free_p(bp);
  93.             return;
  94.         }
  95.         sax = (struct sockaddr_ax *)hdr->data;
  96.         sax->sax_family = AF_AX25;
  97.         memcpy(sax->ax25_addr,src,AXALEN);
  98.         strncpy(sax->iface,iface->name,ILEN);
  99.         hdr->next = bp;
  100.         enqueue(&Bcq,hdr);
  101.     }
  102. }
  103. #endif
  104. #endif /* AX.25 */
  105.   
  106. /* Create a user socket, return socket index
  107.  * The mapping to actual protocols is as follows:
  108.  *
  109.  *
  110.  * ADDRESS FAMILY   Stream      Datagram    Raw     Seq. Packet
  111.  *
  112.  * AF_INET      TCP     UDP     IP
  113.  * AF_AX25      I-frames    UI-frames
  114.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  115.  * AF_LOCAL     stream loopback packet loopback
  116.  */
  117. int
  118. socket(af,type,protocol)
  119. int af;     /* Address family */
  120. int type;   /* Stream or datagram */
  121. int protocol;   /* Used for raw IP sockets */
  122. {
  123.     struct usock *up;
  124.     int s;
  125.   
  126.     if((up=addsocket()) == NULLUSOCK) {
  127.         errno = EMFILE;
  128.         return -1;  /* Can't add a socket */
  129.     }
  130.   
  131.     /* set the time the socket was created - WG7J */
  132.     up->created = time(NULL);
  133.     up->refcnt = 1;
  134.     s = up->number;
  135.     errno = 0;
  136.     up->look = NULLPROC;
  137.     up->noblock = 0;
  138.     up->rdysock = -1;
  139.     up->cb.p = NULLCHAR;
  140.     up->peername = up->name = NULLCHAR;
  141.     up->namelen = up->peernamelen = 0;
  142.     up->owner = Curproc;
  143.     up->obuf = NULLBUF;
  144.     memset(up->errcodes,0,sizeof(up->errcodes));
  145.     memset(up->eol,0,sizeof(up->eol));
  146.     up->flush = '\n';   /* default is line buffered */
  147.     switch(af){
  148.         case AF_LOCAL:
  149.             up->cb.local = (struct loc *) callocw(1,sizeof(struct loc));
  150.             up->cb.local->peer = up;    /* connect to self */
  151.         switch(type){
  152.             case SOCK_STREAM:
  153.                 up->type = TYPE_LOCAL_STREAM;
  154.                 up->cb.local->hiwat = LOCSFLOW;
  155.                 break;
  156.             case SOCK_DGRAM:
  157.                 up->type = TYPE_LOCAL_DGRAM;
  158.                 up->cb.local->hiwat = LOCDFLOW;
  159.                 break;
  160.             default:
  161.                 free(up->cb.local);
  162.                 errno = ESOCKTNOSUPPORT;
  163.                 break;
  164.         }
  165.             break;
  166. #ifdef  AX25
  167.         case AF_AX25:
  168.         switch(type){
  169.             case SOCK_STREAM:
  170.                 up->type = TYPE_AX25I;
  171.                 break;
  172.             case SOCK_DGRAM:
  173.                 up->type = TYPE_AX25UI;
  174.                 break;
  175.             default:
  176.                 errno = ESOCKTNOSUPPORT;
  177.                 break;
  178.         }
  179.             strcpy(up->eol,AX_EOL);
  180.             break;
  181. #endif
  182. #ifdef NETROM
  183.         case AF_NETROM:
  184.         switch(type){
  185. #ifdef NRRAW
  186.             case SOCK_RAW:
  187.                 up->type = TYPE_NETROML3;
  188.                 up->cb.rnr = raw_nr((char)protocol);
  189.                 break;
  190. #endif
  191.             case SOCK_SEQPACKET:
  192.                 up->type = TYPE_NETROML4;
  193.                 break;
  194.             default:
  195.                 errno = ESOCKTNOSUPPORT;
  196.                 break;
  197.         }
  198.             strcpy(up->eol,AX_EOL);
  199.             break;
  200. #endif
  201.         case AF_INET:
  202.         switch(type){
  203.             case SOCK_STREAM:
  204.                 up->type = TYPE_TCP;
  205.                 strcpy(up->eol,INET_EOL);
  206.                 break;
  207.             case SOCK_DGRAM:
  208.                 up->type = TYPE_UDP;
  209.                 break;
  210.             case SOCK_RAW:
  211.                 up->type = TYPE_RAW;
  212.                 up->cb.rip = raw_ip(protocol,rip_recv);
  213.                 up->cb.rip->user = s;
  214.                 break;
  215.             default:
  216.                 errno = ESOCKTNOSUPPORT;
  217.                 break;
  218.         }
  219.             break;
  220.         default:
  221.             errno = EAFNOSUPPORT;
  222.             break;
  223.     }
  224.     if(errno)
  225.         return -1;
  226.   
  227.     return s;
  228. }
  229.   
  230. /* Attach a local address/port to a socket. If not issued before a connect
  231.  * or listen, will be issued automatically
  232.  */
  233. int
  234. bind(s,name,namelen)
  235. int s;      /* Socket index */
  236. char *name; /* Local name */
  237. int namelen;    /* Length of name */
  238. {
  239.     register struct usock *up;
  240.     union sp local;
  241.     struct socket lsock;
  242.   
  243.     if((up = itop(s)) == NULLUSOCK){
  244.         errno = EBADF;
  245.         return -1;
  246.     }
  247.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  248.         errno = EINVAL;
  249.         return -1;
  250.     }
  251.     if(name == NULLCHAR){
  252.         errno = EFAULT;
  253.         return -1;
  254.     }
  255.     if(up->name != NULLCHAR){
  256.         /* Bind has already been issued */
  257.         errno = EINVAL;
  258.         return -1;
  259.     }
  260.     if(checkaddr(up->type,name,namelen) == -1){
  261.         /* Incorrect length or family for chosen protocol */
  262.         errno = EAFNOSUPPORT;
  263.         return -1;
  264.     }
  265.     /* Stash name in an allocated block */
  266.     up->namelen = namelen;
  267.     up->name = mallocw(namelen);
  268.     memcpy(up->name,name,namelen);
  269.     /* Create control block for datagram sockets */
  270.     switch(up->type){
  271.         case TYPE_UDP:
  272.             local.in = (struct sockaddr_in *)up->name;
  273.             lsock.address = local.in->sin_addr.s_addr;
  274.             lsock.port = local.in->sin_port;
  275.             up->cb.udp = open_udp(&lsock,s_urcall);
  276.             up->cb.udp->user = s;
  277.             break;
  278. #ifdef  notdef
  279.         case TYPE_AX25UI:
  280.             if(Axui_sock != -1){
  281.                 errno = EADDRINUSE;
  282.                 return -1;
  283.             }
  284.             Axui_sock = s;
  285.             break;
  286. #endif
  287.     }
  288.     return 0;
  289. }
  290. /* Post a listen on a socket */
  291. int
  292. listen(s,backlog)
  293. int s;      /* Socket index */
  294. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  295. {
  296.     register struct usock *up;
  297.     union sp local;
  298.     struct socket lsock;
  299.   
  300.     if((up = itop(s)) == NULLUSOCK){
  301.         errno = EBADF;
  302.         return -1;
  303.     }
  304.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  305.         errno = EINVAL;
  306.         return -1;
  307.     }
  308.     if(up->cb.p != NULLCHAR){
  309.         errno = EISCONN;
  310.         return -1;
  311.     }
  312.     switch(up->type){
  313.         case TYPE_TCP:
  314.             if(up->name == NULLCHAR)
  315.                 autobind(s,AF_INET);
  316.   
  317.             local.in = (struct sockaddr_in *)up->name;
  318.             lsock.address = local.in->sin_addr.s_addr;
  319.             lsock.port = local.in->sin_port;
  320.             up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  321.             backlog ? TCP_SERVER:TCP_PASSIVE,0,
  322.             s_trcall,s_ttcall,s_tscall,0,s);
  323.             break;
  324. #ifdef AX25
  325.         case TYPE_AX25I:
  326.             if(up->name == NULLCHAR)
  327.                 autobind(s,AF_AX25);
  328.             if(s != Axi_sock){
  329.                 errno = EOPNOTSUPP;
  330.                 return -1;
  331.             }
  332.             local.ax = (struct sockaddr_ax *)up->name;
  333.             up->cb.ax25 = open_ax25(NULLIF,local.ax->ax25_addr,NULLCHAR,
  334.             backlog ? AX_SERVER:AX_PASSIVE,0,
  335.             s_arcall,s_atcall,s_ascall,s);
  336.             break;
  337. #endif
  338. #ifdef NETROM
  339.         case TYPE_NETROML4:
  340.             if(up->name == NULLCHAR)
  341.                 autobind(s,AF_NETROM);
  342.             local.nr = (struct sockaddr_nr *)up->name;
  343.             up->cb.nr4 = open_nr4(&local.nr->nr_addr,NULLNRADDR,
  344.             backlog ? AX_SERVER:AX_PASSIVE,
  345.             s_nrcall,s_ntcall,s_nscall,s);
  346.             break;
  347. #endif
  348.         default:
  349.         /* Listen not supported on datagram sockets */
  350.             errno = EOPNOTSUPP;
  351.             return -1;
  352.     }
  353.     return 0;
  354. }
  355.   
  356. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  357. int
  358. connect(s,peername,peernamelen)
  359. int s;          /* Socket index */
  360. char *peername;     /* Peer name */
  361. int peernamelen;    /* Length of peer name */
  362. {
  363.     struct usock *up;
  364.     union cb cb;
  365.     union sp local,remote;
  366.     struct socket lsock,fsock;
  367. #ifdef  AX25
  368.     struct iface *iface;
  369. #endif
  370.   
  371.     if(availmem() < Memthresh){  /* Not enough resources - WG7J */
  372.         errno = ENOMEM;
  373.         return -1;
  374.     }
  375.     if((up = itop(s)) == NULLUSOCK){
  376.         errno = EBADF;
  377.         return -1;
  378.     }
  379.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  380.         errno = EINVAL;
  381.         return -1;
  382.     }
  383.     if(peername == NULLCHAR){
  384.         /* Connect must specify a remote address */
  385.         errno = EFAULT;
  386.         return -1;
  387.     }
  388.     if(checkaddr(up->type,peername,peernamelen) == -1){
  389.         errno = EAFNOSUPPORT;
  390.         return -1;
  391.     }
  392.     /* Raw socket control blocks are created in socket() */
  393.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  394.     up->cb.p != NULLCHAR){
  395.         errno = EISCONN;
  396.         return -1;
  397.     }
  398.     up->peername = mallocw(peernamelen);
  399.     memcpy(up->peername,peername,peernamelen);
  400.     up->peernamelen = peernamelen;
  401.   
  402.     /* Set up the local socket structures */
  403.     if(up->name == NULLCHAR){
  404.         switch(up->type){
  405.             case TYPE_TCP:
  406.             case TYPE_UDP:
  407.             case TYPE_RAW:
  408.                 autobind(s,AF_INET);
  409.                 break;
  410. #ifdef  AX25
  411.             case TYPE_AX25I:
  412.             case TYPE_AX25UI:
  413.                 autobind(s,AF_AX25);
  414.                 break;
  415. #endif
  416. #ifdef  NETROM
  417.             case TYPE_NETROML3:
  418.             case TYPE_NETROML4:
  419.                 autobind(s,AF_NETROM);
  420.                 break;
  421. #endif
  422.         }
  423.     }
  424.     switch(up->type){
  425.         case TYPE_TCP:
  426.         /* Construct the TCP-style ports from the sockaddr structs */
  427.             local.in = (struct sockaddr_in *)up->name;
  428.             remote.in = (struct sockaddr_in *)up->peername;
  429.   
  430.             if(local.in->sin_addr.s_addr == INADDR_ANY)
  431.             /* Choose a local address */
  432.                 local.in->sin_addr.s_addr =
  433.                 locaddr(remote.in->sin_addr.s_addr);
  434.   
  435.             lsock.address = local.in->sin_addr.s_addr;
  436.             lsock.port = local.in->sin_port;
  437.             fsock.address = remote.in->sin_addr.s_addr;
  438.             fsock.port = remote.in->sin_port;
  439.   
  440.         /* Open the TCB in active mode */
  441.             up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  442.             s_trcall,s_ttcall,s_tscall,0,s);
  443.   
  444.         /* Wait for the connection to complete */
  445.             while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  446. #ifdef useblock
  447.                 if(up->noblock){
  448.                     errno = EWOULDBLOCK;
  449.                     return -1;
  450.                 } else
  451. #endif
  452.                     if((errno = pwait(up)) != 0){
  453.                         return -1;
  454.                     }
  455.             }
  456.             if(cb.tcb == NULLTCB){
  457.             /* Probably got refused */
  458.                 free(up->peername);
  459.                 up->peername = NULLCHAR;
  460.                 if(Net_error == NOROUTE)
  461.                     errno = ECONNNOROUTE;
  462.                 else
  463.                     errno = ECONNREFUSED;
  464.                 return -1;
  465.             }
  466.             break;
  467.         case TYPE_UDP:
  468. #ifdef  AX25
  469.         case TYPE_AX25UI:
  470. #endif
  471. #ifdef  NETROM
  472.         case TYPE_NETROML3:
  473. #endif
  474.         case TYPE_RAW:
  475.         /* Control block already created by bind() */
  476.             break;
  477. #ifdef  AX25
  478.         case TYPE_AX25I:
  479.             local.ax = (struct sockaddr_ax *)up->name;
  480.             remote.ax = (struct sockaddr_ax *)up->peername;
  481.             if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  482.                 errno = EINVAL;
  483.                 return -1;
  484.             }
  485.             if(local.ax->ax25_addr[0] == '\0'){
  486.             /* The local address was unspecified; set it from
  487.              * the interface address
  488.              */
  489.                 memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  490.             }
  491.         /* If we already have an AX25 link we can use it */
  492.             if((up->cb.ax25 = find_ax25(local.ax->ax25_addr, \
  493.                 remote.ax->ax25_addr,iface)) != NULLAX25
  494.                 && up->cb.ax25->state != LAPB_DISCONNECTED &&
  495.             up->cb.ax25->user == -1) {
  496.                 up->cb.ax25->user = s;
  497.                 up->cb.ax25->r_upcall = s_arcall;
  498.                 up->cb.ax25->t_upcall = s_atcall;
  499.                 up->cb.ax25->s_upcall = s_ascall;
  500.                 if(up->cb.ax25->state == LAPB_CONNECTED
  501.                     || up->cb.ax25->state == LAPB_RECOVERY)
  502.                     return 0;
  503.             } else
  504.                 up->cb.ax25 = open_ax25(iface,local.ax->ax25_addr,
  505.                 remote.ax->ax25_addr,AX_ACTIVE,
  506.                 0,s_arcall,s_atcall,s_ascall,s);
  507.   
  508.         /* Wait for the connection to complete */
  509.             while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != LAPB_CONNECTED){
  510. #ifdef useblock
  511.                 if(up->noblock){
  512.                     errno = EWOULDBLOCK;
  513.                     return -1;
  514.                 } else
  515. #endif
  516.                     if((errno = pwait(up)) != 0){
  517.                         return -1;
  518.                     }
  519.             }
  520.             if(cb.ax25 == NULLAX25){
  521.             /* Connection probably already exists */
  522.                 free(up->peername);
  523.                 up->peername = NULLCHAR;
  524.                 errno = ECONNREFUSED;
  525.                 return -1;
  526.             }
  527.             break;
  528. #endif
  529. #ifdef  NETROM
  530.         case TYPE_NETROML4:
  531.             local.nr = (struct sockaddr_nr *)up->name;
  532.             remote.nr = (struct sockaddr_nr *)up->peername;
  533.             up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  534.             AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  535.   
  536.         /* Wait for the connection to complete */
  537.             while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  538. #ifdef useblock
  539.                 if(up->noblock){
  540.                     errno = EWOULDBLOCK;
  541.                     return -1;
  542.                 } else
  543. #endif
  544.                     if((errno = pwait(up)) != 0){
  545.                         return -1;
  546.                     }
  547.             }
  548.             if(cb.nr4 == NULLNR4CB){
  549.             /* Connection probably already exists */
  550.                 free(up->peername);
  551.                 up->peername = NULLCHAR;
  552.                 errno = ECONNREFUSED;
  553.                 return -1;
  554.             }
  555.             break;
  556. #endif
  557.     }
  558.     return 0;
  559. }
  560. /* Wait for a connection. Valid only for connection-oriented sockets. */
  561. int
  562. accept(s,peername,peernamelen)
  563. int s;          /* Socket index */
  564. char *peername;     /* Peer name */
  565. int *peernamelen;   /* Length of peer name */
  566. {
  567.     int i;
  568.     register struct usock *up;
  569.   
  570.     if((up = itop(s)) == NULLUSOCK){
  571.         errno = EBADF;
  572.         return -1;
  573.     }
  574.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  575.         errno = EINVAL;
  576.         return -1;
  577.     }
  578.     if(up->cb.p == NULLCHAR){
  579.         errno = EOPNOTSUPP;
  580.         return -1;
  581.     }
  582.     /* Accept is valid only for stream sockets */
  583.     switch(up->type){
  584.         case TYPE_TCP:
  585. #ifdef  AX25
  586.         case TYPE_AX25I:
  587. #endif
  588. #ifdef  NETROM
  589.         case TYPE_NETROML4:
  590. #endif
  591.             break;
  592.         default:
  593.             errno = EOPNOTSUPP;
  594.             return -1;
  595.     }
  596.     /* Wait for the state-change upcall routine to signal us */
  597.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  598. #ifdef useblock
  599.         if(up->noblock){
  600.             errno = EWOULDBLOCK;
  601.             return -1;
  602.         } else
  603. #endif
  604.             if((errno = pwait(up)) != 0){
  605.                 return -1;
  606.             }
  607.     }
  608.     if(up->cb.p == NULLCHAR){
  609.         /* Blown away */
  610.         errno = EBADF;
  611.         return -1;
  612.     }
  613.     i = up->rdysock;
  614.     up->rdysock = -1;
  615.   
  616.     up = itop(i);
  617.     if(peername != NULLCHAR && peernamelen != NULL){
  618.         *peernamelen = min(up->peernamelen,*peernamelen);
  619.         memcpy(peername,up->peername,*peernamelen);
  620.     }
  621.     /* set the time this was created - WG7J */
  622.     up->created = time(NULL);
  623.     return i;
  624. }
  625. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  626.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  627.  * the len parameter.
  628.  */
  629. int
  630. recv_mbuf(s,bpp,flags,from,fromlen)
  631. int s;          /* Socket index */
  632. struct mbuf **bpp;  /* Place to stash receive buffer */
  633. int flags;      /* Unused; will control out-of-band data, etc */
  634. char *from;     /* Peer address (only for datagrams) */
  635. int *fromlen;       /* Length of peer address */
  636. {
  637.     register struct usock *up;
  638.     int cnt;
  639.     union cb cb;
  640.     struct socket fsocket;
  641. #ifdef  NETROM
  642.     struct nr3hdr n3hdr;
  643. #endif
  644.     union sp remote;
  645.     struct ip ip;
  646.     struct mbuf *bp;
  647.   
  648.     if((up = itop(s)) == NULLUSOCK){
  649.         errno = EBADF;
  650.         return -1;
  651.     }
  652.     if(up->ibuf != NULLBUF){
  653.         /* Return input buffer */
  654.         cnt = len_p(up->ibuf);
  655.         if(bpp != NULLBUFP)
  656.             *bpp = up->ibuf;
  657.         else
  658.             free_p(up->ibuf);
  659.         up->ibuf = NULLBUF;
  660.         return cnt;
  661.     }
  662.     switch(up->type){
  663.         case TYPE_LOCAL_STREAM:
  664.         case TYPE_LOCAL_DGRAM:
  665.             while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  666.             && up->cb.local->peer != NULLUSOCK){
  667. #ifdef useblock
  668.                 if(up->noblock){
  669.                     errno = EWOULDBLOCK;
  670.                     return -1;
  671.                 } else
  672. #endif
  673.                     if((errno = pwait(up)) != 0){
  674.                         return -1;
  675.                     }
  676.             }
  677.             if(up->cb.local == NULLLOC){
  678.                 errno = EBADF;
  679.                 return -1;
  680.             }
  681.             if(up->cb.local->q == NULLBUF &&
  682.             up->cb.local->peer == NULLUSOCK){
  683.                 errno = ENOTCONN;
  684.                 return -1;
  685.             }
  686.         /* For datagram sockets, this will return the
  687.          * first packet on the queue. For stream sockets,
  688.          * this will return everything.
  689.          */
  690.             bp = dequeue(&up->cb.local->q);
  691.             if(up->cb.local->q == NULLBUF
  692.                 && (up->cb.local->flags & LOC_SHUTDOWN))
  693.                 close_s(s);
  694.             psignal(up,0);
  695.             cnt = len_p(bp);
  696.             break;
  697.         case TYPE_TCP:
  698.             while((cb.tcb = up->cb.tcb) != NULLTCB
  699.                 && cb.tcb->r_upcall != trdiscard
  700.             && (cnt = recv_tcp(cb.tcb,&bp,(int16)0)) == -1){
  701. #ifdef useblock
  702.                 if(up->noblock){
  703.                     errno = EWOULDBLOCK;
  704.                     return -1;
  705.                 } else
  706. #endif
  707.                     if((errno = pwait(up)) != 0){
  708.                         return -1;
  709.                     }
  710.             }
  711.             if(cb.tcb == NULLTCB){
  712.             /* Connection went away */
  713.                 errno = ENOTCONN;
  714.                 return -1;
  715.             } else if(cb.tcb->r_upcall == trdiscard){
  716.             /* Receive shutdown has been done */
  717.                 errno = ENOTCONN;   /* CHANGE */
  718.                 return -1;
  719.             }
  720.             break;
  721.         case TYPE_UDP:
  722.             while((cb.udp = up->cb.udp) != NULLUDP
  723.             && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  724. #ifdef useblock
  725.                 if(up->noblock){
  726.                     errno = EWOULDBLOCK;
  727.                     return -1;
  728.                 } else
  729. #endif
  730.                     if((errno = pwait(up)) != 0){
  731.                         return -1;
  732.                     }
  733.             }
  734.             if(cb.udp == NULLUDP){
  735.             /* Connection went away */
  736.                 errno = ENOTCONN;
  737.                 return -1;
  738.             }
  739.             if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  740.                 remote.in = (struct sockaddr_in *)from;
  741.                 remote.in->sin_family = AF_INET;
  742.                 remote.in->sin_addr.s_addr = fsocket.address;
  743.                 remote.in->sin_port = fsocket.port;
  744.                 *fromlen = SOCKSIZE;
  745.             }
  746.             break;
  747.         case TYPE_RAW:
  748.             while((cb.rip = up->cb.rip) != NULLRIP
  749.             && cb.rip->rcvq == NULLBUF){
  750. #ifdef useblock
  751.                 if(up->noblock){
  752.                     errno = EWOULDBLOCK;
  753.                     return -1;
  754.                 } else
  755. #endif
  756.                     if((errno = pwait(up)) != 0){
  757.                         return -1;
  758.                     }
  759.             }
  760.             if(cb.rip == NULLRIP){
  761.             /* Connection went away */
  762.                 errno = ENOTCONN;
  763.                 return -1;
  764.             }
  765.             bp = dequeue(&cb.rip->rcvq);
  766.             ntohip(&ip,&bp);
  767.   
  768.             cnt = len_p(bp);
  769.             if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  770.                 remote.in = (struct sockaddr_in *)from;
  771.                 remote.in->sin_family = AF_INET;
  772.                 remote.in->sin_addr.s_addr = ip.source;
  773.                 remote.in->sin_port = 0;
  774.                 *fromlen = SOCKSIZE;
  775.             }
  776.             break;
  777. #ifdef  AX25
  778.         case TYPE_AX25I:
  779.             while((cb.ax25 = up->cb.ax25) != NULLAX25
  780.             && (bp = recv_ax25(cb.ax25,(int16)0)) == NULLBUF){
  781. #ifdef useblock
  782.                 if(up->noblock){
  783.                     errno = EWOULDBLOCK;
  784.                     return -1;
  785.                 } else
  786. #endif
  787.                     if((errno = pwait(up)) != 0){
  788.                         return -1;
  789.                     }
  790.             }
  791.             if(cb.ax25 == NULLAX25){
  792.             /* Connection went away */
  793.                 errno = ENOTCONN;
  794.                 return -1;
  795.             }
  796.             cnt = bp->cnt;
  797.             break;
  798. #ifdef notdef
  799.         case TYPE_AX25UI:
  800.             while(s == Axui_sock && Bcq == NULLBUF){
  801. #ifdef useblock
  802.                 if(up->noblock){
  803.                     errno = EWOULDBLOCK;
  804.                     return -1;
  805.                 } else
  806. #endif
  807.                     if((errno = pwait(&Bcq)) != 0){
  808.                         return -1;
  809.                     }
  810.             }
  811.             if(s != Axui_sock){
  812.                 errno = ENOTCONN;
  813.                 return -1;
  814.             }
  815.             bp = dequeue(&Bcq);
  816.   
  817.             if(from != NULLCHAR && fromlen != NULLINT
  818.             && *fromlen >= sizeof(struct sockaddr_ax)){
  819.                 pullup(&bp,from,sizeof(struct sockaddr_ax));
  820.                 *fromlen = sizeof(struct sockaddr_ax);
  821.             } else {
  822.                 pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  823.             }
  824.             cnt = len_p(bp);
  825.             break;
  826. #endif /* notdef */
  827. #endif /* ax25 */
  828. #ifdef NETROM
  829.         case TYPE_NETROML3:
  830.             while((cb.rnr = up->cb.rnr) != NULLRNR
  831.             && cb.rnr->rcvq == NULLBUF){
  832. #ifdef useblock
  833.                 if(up->noblock){
  834.                     errno = EWOULDBLOCK;
  835.                     return -1;
  836.                 } else
  837. #endif
  838.                     if((errno = pwait(up)) != 0){
  839.                         return -1;
  840.                     }
  841.             }
  842.             if(cb.rnr == NULLRNR){
  843.             /* Connection went away */
  844.                 errno = ENOTCONN;
  845.                 return -1;
  846.             }
  847.             bp = dequeue(&cb.rnr->rcvq);
  848.             ntohnr3(&n3hdr,&bp);
  849.             cnt = len_p(bp);
  850.             if(from != NULLCHAR && fromlen != NULLINT
  851.             && *fromlen >= sizeof(struct sockaddr_nr)){
  852.                 remote.nr = (struct sockaddr_nr *)from;
  853.                 remote.nr->nr_family = AF_NETROM;
  854.             /* The callsign of the local user is not part of
  855.                NET/ROM level 3, so that field is not used here */
  856.                 memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  857.                 *fromlen = sizeof(struct sockaddr_nr);
  858.             }
  859.             break;
  860.         case TYPE_NETROML4:
  861.             while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  862.             && (bp = recv_nr4(cb.nr4,(int16)0)) == NULLBUF){
  863. #ifdef useblock
  864.                 if(up->noblock){
  865.                     errno = EWOULDBLOCK;
  866.                     return -1;
  867.                 } else
  868. #endif
  869.                     if((errno = pwait(up)) != 0){
  870.                         return -1;
  871.                     }
  872.             }
  873.             if(cb.nr4 == NULLNR4CB){
  874.             /* Connection went away */
  875.                 errno = ENOTCONN;
  876.                 return -1;
  877.             }
  878.             cnt = bp->cnt;
  879.             break;
  880. #endif
  881.     }
  882.     if(bpp != NULLBUFP)
  883.         *bpp = bp;
  884.     else
  885.         free_p(bp);
  886.     return cnt;
  887. }
  888. /* Low level send routine; user supplies mbuf for transmission. More
  889.  * efficient than send() or sendto(), the higher level interfaces.
  890.  * The "to" and "tolen" parameters are ignored on connection-oriented
  891.  * sockets.
  892.  *
  893.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  894.  */
  895. int
  896. send_mbuf(s,bp,flags,to,tolen)
  897. int s;          /* Socket index */
  898. struct mbuf *bp;    /* Buffer to send */
  899. int flags;      /* not currently used */
  900. char *to;       /* Destination, only for datagrams */
  901. int tolen;      /* Length of destination */
  902. {
  903.     register struct usock *up;
  904.     union cb cb;
  905.     union sp local,remote;
  906.     struct socket lsock,fsock;
  907.     int cnt;
  908.   
  909.     if((up = itop(s)) == NULLUSOCK){
  910.         free_p(bp);
  911.         errno = EBADF;
  912.         return -1;
  913.     }
  914. #ifndef notdef
  915.     if(up->obuf != NULLBUF){
  916.         /* If there's unflushed output, send it.
  917.          * Note the importance of clearing up->obuf
  918.          * before the recursive call!
  919.          */
  920.         struct mbuf *bp1;
  921.   
  922.         bp1 = up->obuf;
  923.         up->obuf = NULLBUF;
  924.         send_mbuf(s,bp1,flags,to,tolen);
  925.     }
  926. #endif
  927.     if(up->name == NULLCHAR){
  928.         /* Automatic local name assignment for datagram sockets */
  929.         switch(up->type){
  930.             case TYPE_LOCAL_STREAM:
  931.             case TYPE_LOCAL_DGRAM:
  932.                 break;  /* no op */
  933.             case TYPE_UDP:
  934.             case TYPE_RAW:
  935.                 autobind(s,AF_INET);
  936.                 break;
  937. #ifdef  AX25
  938.             case TYPE_AX25UI:
  939.                 autobind(s,AF_AX25);
  940.                 break;
  941. #endif
  942. #ifdef  NETROM
  943.             case TYPE_NETROML3:
  944.             case TYPE_NETROML4:
  945.                 autobind(s,AF_NETROM);
  946.                 break;
  947. #endif
  948.             default:
  949.                 free_p(bp);
  950.                 errno = ENOTCONN;
  951.                 return -1;
  952.         }
  953.     }
  954.     cnt = len_p(bp);
  955.     switch(up->type){
  956.         case TYPE_LOCAL_DGRAM:
  957.             if(up->cb.local->peer == NULLUSOCK){
  958.                 free_p(bp);
  959.                 errno = ENOTCONN;
  960.                 return -1;
  961.             }
  962.             enqueue(&up->cb.local->peer->cb.local->q,bp);
  963.             psignal(up->cb.local->peer,0);
  964.         /* If high water mark has been reached, block */
  965.             while(up->cb.local->peer != NULLUSOCK &&
  966.                 len_q(up->cb.local->peer->cb.local->q) >=
  967.             up->cb.local->peer->cb.local->hiwat){
  968.                 if(up->noblock){
  969.                     errno = EWOULDBLOCK;
  970.                     return -1;
  971.                 } else if((errno = pwait(up->cb.local->peer)) != 0){
  972.                     return -1;
  973.                 }
  974.             }
  975.             if(up->cb.local->peer == NULLUSOCK){
  976.                 errno = ENOTCONN;
  977.                 return -1;
  978.             }
  979.             break;
  980.         case TYPE_LOCAL_STREAM:
  981.             if(up->cb.local->peer == NULLUSOCK){
  982.                 free_p(bp);
  983.                 errno = ENOTCONN;
  984.                 return -1;
  985.             }
  986.             append(&up->cb.local->peer->cb.local->q,bp);
  987.             psignal(up->cb.local->peer,0);
  988.         /* If high water mark has been reached, block */
  989.             while(up->cb.local->peer != NULLUSOCK &&
  990.                 len_p(up->cb.local->peer->cb.local->q) >=
  991.             up->cb.local->peer->cb.local->hiwat){
  992.                 if(up->noblock){
  993.                     errno = EWOULDBLOCK;
  994.                     return -1;
  995.                 } else if((errno = pwait(up->cb.local->peer)) != 0){
  996.                     return -1;
  997.                 }
  998.             }
  999.             if(up->cb.local->peer == NULLUSOCK){
  1000.                 errno = ENOTCONN;
  1001.                 return -1;
  1002.             }
  1003.             break;
  1004.         case TYPE_TCP:
  1005.             if((cb.tcb = up->cb.tcb) == NULLTCB){
  1006.                 free_p(bp);
  1007.                 errno = ENOTCONN;
  1008.                 return -1;
  1009.             }
  1010.             cnt = send_tcp(cb.tcb,bp);
  1011.   
  1012.             while((cb.tcb = up->cb.tcb) != NULLTCB &&
  1013.             cb.tcb->sndcnt > cb.tcb->window){
  1014.             /* Send queue is full */
  1015.                 if(up->noblock){
  1016.                     errno = EWOULDBLOCK;
  1017.                     return -1;
  1018.                 } else if((errno = pwait(up)) != 0){
  1019.                     return -1;
  1020.                 }
  1021.             }
  1022.             if(cb.tcb == NULLTCB){
  1023.                 errno = ENOTCONN;
  1024.                 return -1;
  1025.             }
  1026.             break;
  1027.         case TYPE_UDP:
  1028.             local.in = (struct sockaddr_in *)up->name;
  1029.             lsock.address = local.in->sin_addr.s_addr;
  1030.             lsock.port = local.in->sin_port;
  1031.             if(to != NULLCHAR)
  1032.                 remote.in = (struct sockaddr_in *)to;
  1033.             else if(up->peername != NULLCHAR)
  1034.                 remote.in = (struct sockaddr_in *)up->peername;
  1035.             else {
  1036.                 errno = ENOTCONN;
  1037.                 return -1;
  1038.             }
  1039.             fsock.address = remote.in->sin_addr.s_addr;
  1040.             fsock.port = remote.in->sin_port;
  1041.             send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  1042.             break;
  1043.         case TYPE_RAW:
  1044.             local.in = (struct sockaddr_in *)up->name;
  1045.             if(to != NULLCHAR)
  1046.                 remote.in = (struct sockaddr_in *)to;
  1047.             else if(up->peername != NULLCHAR)
  1048.                 remote.in = (struct sockaddr_in *)up->peername;
  1049.             else {
  1050.                 errno = ENOTCONN;
  1051.                 return -1;
  1052.             }
  1053.             ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  1054.             (char)up->cb.rip->protocol,0,0,bp,0,0,0);
  1055.             break;
  1056. #ifdef  AX25
  1057.         case TYPE_AX25I:
  1058.             if((cb.ax25 = up->cb.ax25) == NULLAX25){
  1059.                 free_p(bp);
  1060.                 errno = ENOTCONN;
  1061.                 return -1;
  1062.             }
  1063.             send_ax25(cb.ax25,bp,PID_NO_L3);
  1064.   
  1065.             while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1066.             len_q(cb.ax25->txq) * cb.ax25->paclen > cb.ax25->window){
  1067.                 if(up->noblock){
  1068.                     errno = EWOULDBLOCK;
  1069.                     return -1;
  1070.                 } else if((errno = pwait(up)) != 0){
  1071.                     return -1;
  1072.                 }
  1073.             }
  1074.             if(cb.ax25 == NULLAX25){
  1075.                 errno = EBADF;
  1076.                 return -1;
  1077.             }
  1078.             break;
  1079.         case TYPE_AX25UI:
  1080.             local.ax = (struct sockaddr_ax *)up->name;
  1081.             if(to != NULLCHAR)
  1082.                 remote.ax = (struct sockaddr_ax *)to;
  1083.             else if(up->peername != NULLCHAR)
  1084.                 remote.ax = (struct sockaddr_ax *)up->peername;
  1085.             else {
  1086.                 errno = ENOTCONN;
  1087.                 return -1;
  1088.             }
  1089.             ax_output(if_lookup(remote.ax->iface),
  1090.             remote.ax->ax25_addr,
  1091.             local.ax->ax25_addr,PID_NO_L3,bp);
  1092.             break;
  1093. #endif
  1094. #ifdef NETROM
  1095.         case TYPE_NETROML3:
  1096.         /* This should never happen, since the TCP code will peek at the
  1097.          * interface mtu ! - WG7J
  1098.          */
  1099.             if(len_p(bp) > NR4MAXINFO) {
  1100.                 free_p(bp);
  1101.                 errno = EMSGSIZE;
  1102.                 return -1;
  1103.             }
  1104.             local.nr = (struct sockaddr_nr *)up->name;
  1105.             if(to != NULLCHAR)
  1106.                 remote.nr = (struct sockaddr_nr *)to;
  1107.             else if(up->peername != NULLCHAR)
  1108.                 remote.nr = (struct sockaddr_nr *)up->peername;
  1109.             else {
  1110.                 errno = ENOTCONN;
  1111.                 return -1;
  1112.             }
  1113.         /* The NETROM username is always ignored in outgoing traffic */
  1114.             nr_sendraw(remote.nr->nr_addr.node,
  1115.             up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  1116.             break;
  1117.         case TYPE_NETROML4:
  1118.             if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1119.                 free_p(bp);
  1120.                 errno = ENOTCONN;
  1121.                 return -1;
  1122.             }
  1123. #ifdef notdef
  1124.         /* since I now fragment nr4 packets in send_nr4(),
  1125.          * don't worry, be happy :-) - WG7J
  1126.          */
  1127.             if(len_p(bp) > NR4MAXINFO){ /* reject big packets */
  1128.                 free_p(bp);
  1129.                 errno = EMSGSIZE;
  1130.                 return -1;
  1131.             }
  1132. #endif
  1133.             send_nr4(cb.nr4,bp);
  1134.   
  1135.             while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1136.             cb.nr4->nbuffered >= cb.nr4->window){
  1137.                 if(up->noblock){
  1138.                     errno = EWOULDBLOCK;
  1139.                     return -1;
  1140.                 } else if((errno = pwait(up)) != 0){
  1141.                     errno = EINTR;
  1142.                     return -1;
  1143.                 }
  1144.             }
  1145.             if(cb.nr4 == NULLNR4CB){
  1146.                 errno = EBADF;
  1147.                 return -1;
  1148.             }
  1149.             break;
  1150. #endif
  1151.     }
  1152.     return cnt;
  1153. }
  1154. /* Return local name passed in an earlier bind() call */
  1155. int
  1156. getsockname(s,name,namelen)
  1157. int s;      /* Socket index */
  1158. char *name; /* Place to stash name */
  1159. int *namelen;   /* Length of same */
  1160. {
  1161.     register struct usock *up;
  1162.   
  1163.     if((up = itop(s)) == NULLUSOCK){
  1164.         errno = EBADF;
  1165.         return -1;
  1166.     }
  1167.     if(name == NULLCHAR || namelen == (int *)NULL){
  1168.         errno = EFAULT;
  1169.         return -1;
  1170.     }
  1171.     if(up->name == NULLCHAR){
  1172.         /* Not bound yet */
  1173.         *namelen = 0;
  1174.         return 0;
  1175.     }
  1176.     if(up->name != NULLCHAR){
  1177.         *namelen = min(*namelen,up->namelen);
  1178.         memcpy(name,up->name,*namelen);
  1179.     }
  1180.     return 0;
  1181. }
  1182. /* Get remote name, returning result of earlier connect() call. */
  1183. int
  1184. getpeername(s,peername,peernamelen)
  1185. int s;          /* Socket index */
  1186. char *peername;     /* Place to stash name */
  1187. int *peernamelen;   /* Length of same */
  1188. {
  1189.     register struct usock *up;
  1190.   
  1191.     if((up = itop(s)) == NULLUSOCK){
  1192.         errno = EBADF;
  1193.         return -1;
  1194.     }
  1195.     if(up->peername == NULLCHAR){
  1196.         errno = ENOTCONN;
  1197.         return -1;
  1198.     }
  1199.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1200.         errno = EFAULT;
  1201.         return -1;
  1202.     }
  1203.     *peernamelen = min(*peernamelen,up->peernamelen);
  1204.     memcpy(peername,up->peername,*peernamelen);
  1205.     return 0;
  1206. }
  1207. /* Return length of protocol queue, either send or receive. */
  1208. int
  1209. socklen(s,rtx)
  1210. int s;      /* Socket index */
  1211. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1212. {
  1213.     register struct usock *up;
  1214.     int len = -1;
  1215.   
  1216.     if((up = itop(s)) == NULLUSOCK){
  1217.         errno = EBADF;
  1218.         return -1;
  1219.     }
  1220.     if(up->cb.p == NULLCHAR){
  1221.         errno = ENOTCONN;
  1222.         return -1;
  1223.     }
  1224.     if(rtx < 0 || rtx > 1){
  1225.         errno = EINVAL;
  1226.         return -1;
  1227.     }
  1228.     switch(up->type){
  1229.         case TYPE_LOCAL_DGRAM:
  1230.         switch(rtx){
  1231.             case 0:
  1232.                 len = len_q(up->cb.local->q);
  1233.                 break;
  1234.             case 1:
  1235.                 if(up->cb.local->peer != NULLUSOCK)
  1236.                     len = len_q(up->cb.local->peer->cb.local->q);
  1237.                 break;
  1238.         }
  1239.             break;
  1240.         case TYPE_LOCAL_STREAM:
  1241.         switch(rtx){
  1242.             case 0:
  1243.                 len = len_p(up->cb.local->q) + len_p(up->ibuf);
  1244.                 break;
  1245.             case 1:
  1246.                 if(up->cb.local->peer != NULLUSOCK)
  1247.                     len = len_p(up->cb.local->peer->cb.local->q)
  1248.                     + len_p(up->obuf);
  1249.                 break;
  1250.         }
  1251.             break;
  1252.         case TYPE_TCP:
  1253.         switch(rtx){
  1254.             case 0:
  1255.                 len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1256.                 break;
  1257.             case 1:
  1258.                 len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1259.                 break;
  1260.         }
  1261.             break;
  1262.         case TYPE_UDP:
  1263.         switch(rtx){
  1264.             case 0:
  1265.                 len = up->cb.udp->rcvcnt;
  1266.                 break;
  1267.             case 1:
  1268.                 len = 0;
  1269.                 break;
  1270.         }
  1271.             break;
  1272. #ifdef  AX25
  1273.         case TYPE_AX25I:
  1274.         switch(rtx){
  1275.             case 0:
  1276.                 len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1277.                 break;
  1278.             case 1: /* Number of packets, not bytes */
  1279.                 len = len_q(up->cb.ax25->txq);
  1280.                 if(up->obuf != NULLBUF)
  1281.                     len++;
  1282.         }
  1283.             break;
  1284. #ifdef notdef
  1285.         case TYPE_AX25UI:
  1286.         switch(rtx){
  1287.             case 0:
  1288.                 len = len_q(Bcq);
  1289.                 break;
  1290.             case 1:
  1291.                 len = 0;
  1292.                 break;
  1293.         }
  1294.             break;
  1295. #endif /* notdef */
  1296. #endif
  1297. #ifdef NETROM
  1298.         case TYPE_NETROML3:
  1299.         switch(rtx){
  1300.             case 0:
  1301.                 len = len_q(up->cb.rnr->rcvq);
  1302.                 break;
  1303.             case 1:
  1304.                 len = 0;
  1305.         }
  1306.             break;
  1307.         case TYPE_NETROML4:
  1308.         switch(rtx){
  1309.             case 0:
  1310.                 len = len_p(up->cb.nr4->rxq) + len_p(up->ibuf);
  1311.                 break;
  1312.             case 1: /* Number of packets, not bytes */
  1313.                 len = len_q(up->cb.nr4->txq);
  1314.                 if(up->obuf != NULLBUF)
  1315.                     len++;
  1316.                 break;
  1317.         }
  1318.             break;
  1319. #endif
  1320.         case TYPE_RAW:
  1321.         switch(rtx){
  1322.             case 0:
  1323.                 len = len_q(up->cb.rip->rcvq);
  1324.                 break;
  1325.             case 1:
  1326.                 len = 0;
  1327.                 break;
  1328.         }
  1329.             break;
  1330.     }
  1331.     return len;
  1332. }
  1333. /* Force retransmission. Valid only for connection-oriented sockets. */
  1334. int
  1335. sockkick(s)
  1336. int s;  /* Socket index */
  1337. {
  1338.     register struct usock *up;
  1339.   
  1340.     if((up = itop(s)) == NULLUSOCK){
  1341.         errno = EBADF;
  1342.         return -1;
  1343.     }
  1344.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1345.         errno = EINVAL;
  1346.         return -1;
  1347.     }
  1348.     if(up->cb.p == NULLCHAR){
  1349.         errno = ENOTCONN;
  1350.         return -1;
  1351.     }
  1352.     switch(up->type){
  1353.         case TYPE_TCP:
  1354.             kick_tcp(up->cb.tcb);
  1355.             break;
  1356. #ifdef  AX25
  1357.         case TYPE_AX25I:
  1358.             kick_ax25(up->cb.ax25);
  1359.             break;
  1360. #endif
  1361. #ifdef NETROM
  1362.         case TYPE_NETROML4:
  1363.             kick_nr4(up->cb.nr4);
  1364.             break;
  1365. #endif
  1366.         default:
  1367.         /* Datagram sockets can't be kicked */
  1368.             errno = EOPNOTSUPP;
  1369.             return -1;
  1370.     }
  1371.     return 0;
  1372. }
  1373.   
  1374. /* Change owner of socket, return previous owner */
  1375. struct proc *
  1376. sockowner(s,newowner)
  1377. int s;          /* Socket index */
  1378. struct proc *newowner;  /* Process table address of new owner */
  1379. {
  1380.     register struct usock *up;
  1381.     struct proc *pp;
  1382.   
  1383.     if((up = itop(s)) == NULLUSOCK){
  1384.         errno = EBADF;
  1385.         return NULLPROC;
  1386.     }
  1387.     pp = up->owner;
  1388.     if(newowner != NULLPROC)
  1389.         up->owner = newowner;
  1390.     return pp;
  1391. }
  1392. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1393.  * replaces the incoming data upcall with a routine that discards further
  1394.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1395.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1396.  * as "abort the connection".
  1397.  */
  1398. int
  1399. shutdown(s,how)
  1400. int s;      /* Socket index */
  1401. int how;    /* (see above) */
  1402. {
  1403.     register struct usock *up;
  1404.   
  1405.     if((up = itop(s)) == NULLUSOCK){
  1406.         errno = EBADF;
  1407.         return -1;
  1408.     }
  1409.     if(up->cb.p == NULLCHAR){
  1410.         errno = ENOTCONN;
  1411.         return -1;
  1412.     }
  1413.     switch(up->type){
  1414.         case TYPE_LOCAL_DGRAM:
  1415.         case TYPE_LOCAL_STREAM:
  1416.             if(up->cb.local->q == NULLBUF)
  1417.                 close_s(s);
  1418.             else
  1419.                 up->cb.local->flags = LOC_SHUTDOWN;
  1420.             break;
  1421.         case TYPE_TCP:
  1422.         switch(how){
  1423.             case 0: /* No more receives -- replace upcall */
  1424.                 up->cb.tcb->r_upcall = trdiscard;
  1425.                 break;
  1426.             case 1: /* Send EOF */
  1427.                 close_tcp(up->cb.tcb);
  1428.                 break;
  1429.             case 2: /* Blow away TCB */
  1430.                 reset_tcp(up->cb.tcb);
  1431.                 up->cb.tcb = NULLTCB;
  1432.                 break;
  1433.         }
  1434.             break;
  1435. #ifdef  AX25
  1436. #ifdef notdef
  1437.         case TYPE_AX25UI:
  1438.             close_s(s);
  1439.             break;
  1440. #endif
  1441.         case TYPE_AX25I:
  1442.         switch(how){
  1443.             case 0:
  1444.             case 1: /* Attempt regular disconnect */
  1445.                 disc_ax25(up->cb.ax25);
  1446.                 break;
  1447.             case 2: /* Blow it away */
  1448.                 reset_ax25(up->cb.ax25);
  1449.                 up->cb.ax25 = NULLAX25;
  1450.                 break;
  1451.         }
  1452.             break;
  1453. #endif
  1454. #ifdef  NETROM
  1455.         case TYPE_NETROML3:
  1456.             close_s(s);
  1457.             break;
  1458.         case TYPE_NETROML4:
  1459.         switch(how){
  1460.             case 0:
  1461.             case 1: /* Attempt regular disconnect */
  1462.                 disc_nr4(up->cb.nr4);
  1463.                 break;
  1464.             case 2: /* Blow it away */
  1465.                 reset_nr4(up->cb.nr4);
  1466.                 up->cb.nr4 = NULLNR4CB;
  1467.                 break;
  1468.         }
  1469.             break;
  1470. #endif
  1471.         case TYPE_RAW:
  1472.         case TYPE_UDP:
  1473.             close_s(s);
  1474.             break;
  1475.         default:
  1476.             errno = EOPNOTSUPP;
  1477.             return -1;
  1478.     }
  1479.     psignal(up,0);
  1480.     return 0;
  1481. }
  1482. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1483.  * TCP socket, if possible
  1484.  */
  1485. int
  1486. close_s(s)
  1487. int s;      /* Socket index */
  1488. {
  1489.     struct usock *up;
  1490.   
  1491.     if((up = itop(s)) == NULLUSOCK){
  1492.         errno = EBADF;
  1493.         return -1;
  1494.     }
  1495.     if(--up->refcnt > 0)
  1496.         return 0;   /* Others are still using it */
  1497.     usflush(s);
  1498.     if(up->ibuf != NULLBUF){
  1499.         free_p(up->ibuf);
  1500.         up->ibuf = NULLBUF;
  1501.     }
  1502.     switch(up->type){
  1503.         case TYPE_LOCAL_STREAM:
  1504.         case TYPE_LOCAL_DGRAM:
  1505.             if(up->cb.local->peer != NULLUSOCK){
  1506.                 up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1507.                 psignal(up->cb.local->peer,0);
  1508.             }
  1509.             free_q(&up->cb.local->q);
  1510.             free(up->cb.local);
  1511.             break;
  1512.         case TYPE_TCP:
  1513.             if(up->cb.tcb != NULLTCB){  /* In case it's been reset */
  1514.                 up->cb.tcb->r_upcall = trdiscard;
  1515.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1516.                 up->cb.tcb->user = -1;
  1517.                 close_tcp(up->cb.tcb);
  1518.             }
  1519.             break;
  1520.         case TYPE_UDP:
  1521.             if(up->cb.udp != NULLUDP){
  1522.                 del_udp(up->cb.udp);
  1523.             }
  1524.             break;
  1525. #ifdef  AX25
  1526.         case TYPE_AX25I:
  1527.             if(up->cb.ax25 != NULLAX25){
  1528.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1529.                 up->cb.ax25->user = -1;
  1530.                 disc_ax25(up->cb.ax25);
  1531.             }
  1532.             break;
  1533. #ifdef notdef
  1534.         case TYPE_AX25UI:
  1535.             Axui_sock = -1;
  1536.             free_q(&Bcq);
  1537.             psignal(&Bcq,0);    /* Unblock any reads */
  1538.             break;
  1539. #endif /* notdef */
  1540. #endif
  1541. #ifdef  NETROM
  1542. #ifdef NRRAW
  1543.         case TYPE_NETROML3:
  1544.             del_rnr(up->cb.rnr);
  1545.             break;
  1546. #endif
  1547.         case TYPE_NETROML4:
  1548.             if(up->cb.nr4 != NULLNR4CB){
  1549.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1550.                 up->cb.nr4->user = -1;
  1551.                 disc_nr4(up->cb.nr4);
  1552.             }
  1553.             break;
  1554. #endif
  1555.         case TYPE_RAW:
  1556.             del_ip(up->cb.rip);
  1557.             break;
  1558.         default:
  1559.             errno = EOPNOTSUPP;
  1560.             return -1;
  1561.     }
  1562. #ifdef  LZW
  1563.     if(up->zout != NULLLZW || up->zin != NULLLZW)
  1564.         lzwfree(up);
  1565. #endif
  1566.     free(up->name);
  1567.     free(up->peername);
  1568.   
  1569.     psignal(up,0);  /* Wake up anybody doing an accept() or recv() */
  1570. #ifdef LOOKSESSION
  1571.     if(up->look)    /* Alert the process looking at us */
  1572.         alert(up->look,ENOTCONN);
  1573. #endif
  1574.     deletesocket(s);
  1575.     return 0;
  1576. }
  1577.   
  1578. /* Increment reference count for specified socket */
  1579. int
  1580. usesock(s)
  1581. int s;
  1582. {
  1583.     struct usock *up;
  1584.   
  1585.     if((up = itop(s)) == NULLUSOCK){
  1586.         errno = EBADF;
  1587.         return -1;
  1588.     }
  1589.     up->refcnt++;
  1590.     return 0;
  1591. }
  1592.   
  1593. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1594. void
  1595. freesock(pp)
  1596. struct proc *pp;
  1597. {
  1598.     struct usock *up;
  1599.     int s;
  1600.   
  1601.     s = 0;
  1602.     while((s=getnextsocket(s)) != -1) {
  1603.         up = itop(s);
  1604.         if(up != NULLUSOCK && up->owner == pp) {
  1605.             shutdown(s,2);
  1606.         }
  1607.     }
  1608. }
  1609.   
  1610. /* Start of internal subroutines */
  1611.   
  1612. /* Raw IP receive upcall routine */
  1613. static void
  1614. rip_recv(rp)
  1615. struct raw_ip *rp;
  1616. {
  1617.     psignal(itop(rp->user),1);
  1618.     pwait(NULL);
  1619. }
  1620.   
  1621. /* UDP receive upcall routine */
  1622. static void
  1623. s_urcall(iface,udp,cnt)
  1624. struct iface *iface;
  1625. struct udp_cb *udp;
  1626. int cnt;
  1627. {
  1628.     psignal(itop(udp->user),1);
  1629.     pwait(NULL);
  1630. }
  1631. /* TCP receive upcall routine */
  1632. static void
  1633. s_trcall(tcb,cnt)
  1634. struct tcb *tcb;
  1635. int cnt;
  1636. {
  1637.     /* Wake up anybody waiting for data, and let them run */
  1638.     psignal(itop(tcb->user),1);
  1639.     pwait(NULL);
  1640. }
  1641. /* TCP transmit upcall routine */
  1642. static void
  1643. s_ttcall(tcb,cnt)
  1644. struct tcb *tcb;
  1645. int cnt;
  1646. {
  1647.     /* Wake up anybody waiting to send data, and let them run */
  1648.     psignal(itop(tcb->user),1);
  1649.     pwait(NULL);
  1650. }
  1651. /* TCP state change upcall routine */
  1652. static void
  1653. s_tscall(tcb,old,new)
  1654. struct tcb *tcb;
  1655. int old,new;
  1656. {
  1657.     int s,ns;
  1658.     struct usock *up,*nup,*oup,*next;
  1659.     union sp sp;
  1660.   
  1661.     s = tcb->user;
  1662.     oup = up = itop(s);
  1663.   
  1664.     switch(new){
  1665.         case TCP_CLOSED:
  1666.         /* Clean up. If the user has already closed the socket,
  1667.          * then up will be null (s was set to -1 by the close routine).
  1668.          * If not, then this is an abnormal close (e.g., a reset)
  1669.          * and clearing out the pointer in the socket structure will
  1670.          * prevent any further operations on what will be a freed
  1671.          * control block. Also wake up anybody waiting on events
  1672.          * related to this tcb so they will notice it disappearing.
  1673.          */
  1674.             if(up != NULLUSOCK){
  1675.                 up->cb.tcb = NULLTCB;
  1676.                 up->errcodes[0] = tcb->reason;
  1677.                 up->errcodes[1] = tcb->type;
  1678.                 up->errcodes[2] = tcb->code;
  1679.             }
  1680.             del_tcp(tcb);
  1681.             break;
  1682.         case TCP_SYN_RECEIVED:
  1683.         /* Handle an incoming connection. If this is a server TCB,
  1684.          * then we're being handed a "clone" TCB and we need to
  1685.          * create a new socket structure for it. In either case,
  1686.          * find out who we're talking to and wake up the guy waiting
  1687.          * for the connection.
  1688.          */
  1689.             if(tcb->flags.clone){
  1690.             /* Clone the socket */
  1691.                 ns = socket(AF_INET,SOCK_STREAM,0);
  1692.                 nup = itop(ns);
  1693.                 next = nup->next;
  1694.                 ASSIGN(*nup,*up);
  1695.                 nup->next = next;
  1696.                 nup->number = ns;
  1697.                 tcb->user = ns;
  1698.                 nup->cb.tcb = tcb;
  1699.             /* Allocate new memory for the name areas */
  1700.                 nup->name = mallocw(SOCKSIZE);
  1701.                 nup->peername = mallocw(SOCKSIZE);
  1702.             /* Store the new socket # in the old one */
  1703.                 up->rdysock = ns;
  1704.                 up = nup;
  1705.                 s = ns;
  1706.             } else {
  1707.             /* Allocate space for the peer's name */
  1708.                 up->peername = mallocw(SOCKSIZE);
  1709.             /* Store the old socket # in the old socket */
  1710.                 up->rdysock = s;
  1711.             }
  1712.         /* Load the addresses. Memory for the name has already
  1713.          * been allocated, either above or in the original bind.
  1714.          */
  1715.             sp.p = up->name;
  1716.             sp.in->sin_family = AF_INET;
  1717.             sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1718.             sp.in->sin_port = up->cb.tcb->conn.local.port;
  1719.             up->namelen = SOCKSIZE;
  1720.   
  1721.             sp.p = up->peername;
  1722.             sp.in->sin_family = AF_INET;
  1723.             sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1724.             sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1725.             up->peernamelen = SOCKSIZE;
  1726.   
  1727.         /* Wake up the guy accepting it, and let him run */
  1728.             psignal(oup,1);
  1729.             pwait(NULL);
  1730.             break;
  1731.         default:    /* Ignore all other state transitions */
  1732.             break;
  1733.     }
  1734.     psignal(up,0);  /* In case anybody's waiting */
  1735. }
  1736. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1737.  * close_s until the TCB disappears.
  1738.  */
  1739. static void
  1740. trdiscard(tcb,cnt)
  1741. struct tcb *tcb;
  1742. int cnt;
  1743. {
  1744.     struct mbuf *bp;
  1745.   
  1746.     recv_tcp(tcb,&bp,(int16)cnt);
  1747.     free_p(bp);
  1748. }
  1749. #ifdef  AX25
  1750. /* AX.25 receive upcall */
  1751. void
  1752. s_arcall(axp,cnt)
  1753. struct ax25_cb *axp;
  1754. int cnt;
  1755. {
  1756.     int ns;
  1757.     struct usock *up,*nup,*oup,*next;
  1758.     union sp sp;
  1759.   
  1760.     up = itop(axp->user);
  1761.     /* When AX.25 data arrives for the first time the AX.25 listener
  1762.        is notified, if active. If the AX.25 listener is a server its
  1763.        socket is duplicated in the same manner as in s_tscall().
  1764.      */
  1765.     if (Axi_sock != -1 && axp->user == -1) {
  1766.         oup = up = itop(Axi_sock);
  1767.         /* From now on, use the same upcalls as the listener */
  1768.         axp->t_upcall = up->cb.ax25->t_upcall;
  1769.         axp->r_upcall = up->cb.ax25->r_upcall;
  1770.         axp->s_upcall = up->cb.ax25->s_upcall;
  1771.         if (up->cb.ax25->flags.clone) {
  1772.             /* Clone the socket */
  1773.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1774.             nup = itop(ns);
  1775.             next = nup->next;
  1776.             ASSIGN(*nup,*up);
  1777.             nup->next = next;
  1778.             nup->number = ns;
  1779.             axp->user = ns;
  1780.             nup->cb.ax25 = axp;
  1781.             /* Allocate new memory for the name areas */
  1782.             nup->name = mallocw(sizeof(struct sockaddr_ax));
  1783.             nup->peername = mallocw(sizeof(struct sockaddr_ax));
  1784.             /* Store the new socket # in the old one */
  1785.             up->rdysock = ns;
  1786.             up = nup;
  1787.         } else {
  1788.             axp->user = Axi_sock;
  1789.             del_ax25(up->cb.ax25);
  1790.             up->cb.ax25 = axp;
  1791.             /* Allocate space for the peer's name */
  1792.             up->peername = mallocw(sizeof(struct sockaddr_ax));
  1793.             /* Store the old socket # in the old socket */
  1794.             up->rdysock = Axi_sock;
  1795.         }
  1796.         /* Load the addresses. Memory for the name has already
  1797.          * been allocated, either above or in the original bind.
  1798.          */
  1799.         sp.p = up->name;
  1800.         sp.ax->sax_family = AF_AX25;
  1801.         memcpy(sp.ax->ax25_addr,axp->local,AXALEN);
  1802.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1803.         up->namelen = sizeof(struct sockaddr_ax);
  1804.   
  1805.         sp.p = up->peername;
  1806.         sp.ax->sax_family = AF_AX25;
  1807.         memcpy(sp.ax->ax25_addr,axp->remote,AXALEN);
  1808.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1809.         up->peernamelen = sizeof(struct sockaddr_ax);
  1810.         /* Wake up the guy accepting it, and let him run */
  1811.         psignal(oup,1);
  1812.         pwait(NULL);
  1813.         return;
  1814.     }
  1815.     /* Wake up anyone waiting, and let them run */
  1816.     psignal(up,1);
  1817.     pwait(NULL);
  1818. }
  1819. /* AX.25 transmit upcall */
  1820. void
  1821. s_atcall(axp,cnt)
  1822. struct ax25_cb *axp;
  1823. int cnt;
  1824. {
  1825.     /* Wake up anyone waiting, and let them run */
  1826.     psignal(itop(axp->user),1);
  1827.     pwait(NULL);
  1828. }
  1829. /* AX25 state change upcall routine */
  1830. void
  1831. s_ascall(axp,old,new)
  1832. register struct ax25_cb *axp;
  1833. int old,new;
  1834. {
  1835.     int s;
  1836.     struct usock *up;
  1837.   
  1838.     s = axp->user;
  1839.     up = itop(s);
  1840.   
  1841.     switch(new){
  1842.         case LAPB_DISCONNECTED:
  1843.         /* Clean up. If the user has already closed the socket,
  1844.          * then up will be null (s was set to -1 by the close routine).
  1845.          * If not, then this is an abnormal close (e.g., a reset)
  1846.          * and clearing out the pointer in the socket structure will
  1847.          * prevent any further operations on what will be a freed
  1848.          * control block. Also wake up anybody waiting on events
  1849.          * related to this block so they will notice it disappearing.
  1850.          */
  1851.             if(up != NULLUSOCK){
  1852.                 up->errcodes[0] = axp->reason;
  1853.                 up->cb.ax25 = NULLAX25;
  1854.             }
  1855.             del_ax25(axp);
  1856.             break;
  1857.         default:    /* Other transitions are ignored */
  1858.             break;
  1859.     }
  1860.     psignal(up,0);  /* In case anybody's waiting */
  1861. }
  1862. #endif
  1863. #ifdef NETROM
  1864. /* NET/ROM receive upcall routine */
  1865. static void
  1866. s_nrcall(cb,cnt)
  1867. struct nr4cb *cb;
  1868. int cnt;
  1869. {
  1870.     /* Wake up anybody waiting for data, and let them run */
  1871.     psignal(itop(cb->user),1);
  1872.     pwait(NULL);
  1873. }
  1874. /* NET/ROM transmit upcall routine */
  1875. static void
  1876. s_ntcall(cb,cnt)
  1877. struct nr4cb *cb;
  1878. int cnt;
  1879. {
  1880.     /* Wake up anybody waiting to send data, and let them run */
  1881. /*    psignal(itop(cb->user),1); */
  1882. /* Quick-fix for sending wait problem - Dave Perry, VE3IFB */
  1883.     psignal(itop(cb->user),0);
  1884.     pwait(NULL);
  1885. }
  1886. /* NET/ROM state change upcall routine */
  1887. static void
  1888. s_nscall(cb,old,new)
  1889. struct nr4cb *cb;
  1890. int old,new;
  1891. {
  1892.     int s,ns;
  1893.     struct usock *up,*nup,*oup,*next;
  1894.     union sp sp;
  1895.   
  1896.     s = cb->user;
  1897.     oup = up = itop(s);
  1898.   
  1899.     if(new == NR4STDISC && up != NULLUSOCK){
  1900.         /* Clean up. If the user has already closed the socket,
  1901.          * then up will be null (s was set to -1 by the close routine).
  1902.          * If not, then this is an abnormal close (e.g., a reset)
  1903.          * and clearing out the pointer in the socket structure will
  1904.          * prevent any further operations on what will be a freed
  1905.          * control block. Also wake up anybody waiting on events
  1906.          * related to this cb so they will notice it disappearing.
  1907.          */
  1908.         up->cb.nr4 = NULLNR4CB;
  1909.         up->errcodes[0] = cb->dreason;
  1910.     }
  1911.     if(new == NR4STCON && old == NR4STDISC){
  1912.         /* Handle an incoming connection. If this is a server cb,
  1913.          * then we're being handed a "clone" cb and we need to
  1914.          * create a new socket structure for it. In either case,
  1915.          * find out who we're talking to and wake up the guy waiting
  1916.          * for the connection.
  1917.          */
  1918.         if(cb->clone){
  1919.             /* Clone the socket */
  1920.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1921.             nup = itop(ns);
  1922.             next = nup->next;
  1923.             ASSIGN(*nup,*up);
  1924.             nup->next = next;
  1925.             nup->number = ns;
  1926.             cb->user = ns;
  1927.             nup->cb.nr4 = cb;
  1928.             cb->clone = 0; /* to avoid getting here again */
  1929.             /* Allocate new memory for the name areas */
  1930.             nup->name = mallocw(sizeof(struct sockaddr_nr));
  1931.             nup->peername = mallocw(sizeof(struct sockaddr_nr));
  1932.             /* Store the new socket # in the old one */
  1933.             up->rdysock = ns;
  1934.             up = nup;
  1935.             s = ns;
  1936.         } else {
  1937.             /* Allocate space for the peer's name */
  1938.             up->peername = mallocw(sizeof(struct sockaddr_nr));
  1939.             /* Store the old socket # in the old socket */
  1940.             up->rdysock = s;
  1941.         }
  1942.         /* Load the addresses. Memory for the name has already
  1943.          * been allocated, either above or in the original bind.
  1944.          */
  1945.         sp.p = up->name;
  1946.         sp.nr->nr_family = AF_NETROM;
  1947.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1948.         up->namelen = sizeof(struct sockaddr_nr);
  1949.   
  1950.         sp.p = up->peername;
  1951.         sp.nr->nr_family = AF_NETROM;
  1952.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1953.         up->peernamelen = sizeof(struct sockaddr_nr);
  1954.   
  1955.         /* Wake up the guy accepting it, and let him run */
  1956.         psignal(oup,1);
  1957.         pwait(NULL);
  1958.     }
  1959.     /* Ignore all other state transitions */
  1960.     psignal(up,0);  /* In case anybody's waiting */
  1961. }
  1962. #endif
  1963.   
  1964. /* Verify address family and length according to the socket type */
  1965. static int
  1966. checkaddr(type,name,namelen)
  1967. int type;
  1968. char *name;
  1969. int namelen;
  1970. {
  1971.     union sp sp;
  1972.   
  1973.     sp.p = name;
  1974.     /* Verify length and address family according to protocol */
  1975.     switch(type){
  1976.         case TYPE_TCP:
  1977.         case TYPE_UDP:
  1978.             if(sp.in->sin_family != AF_INET
  1979.                 || namelen != sizeof(struct sockaddr_in))
  1980.                 return -1;
  1981.             break;
  1982. #ifdef  AX25
  1983.         case TYPE_AX25I:
  1984. #ifdef notdef
  1985.         case TYPE_AX25UI:
  1986. #endif
  1987.             if(sp.ax->sax_family != AF_AX25
  1988.                 || namelen != sizeof(struct sockaddr_ax))
  1989.                 return -1;
  1990.             break;
  1991. #endif
  1992. #ifdef  NETROM
  1993.         case TYPE_NETROML3:
  1994.         case TYPE_NETROML4:
  1995.             if(sp.nr->nr_family != AF_NETROM
  1996.                 || namelen != sizeof(struct sockaddr_nr))
  1997.                 return -1;
  1998.             break;
  1999. #endif
  2000.     }
  2001.     return 0;
  2002. }
  2003. /* Issue an automatic bind of a local address */
  2004. static void
  2005. autobind(s,af)
  2006. int s,af;
  2007. {
  2008.     char buf[MAXSOCKSIZE];
  2009.     union sp sp;
  2010.   
  2011.     sp.p = buf;
  2012.     switch(af){
  2013.         case AF_INET:
  2014.             sp.in->sin_family = AF_INET;
  2015.             sp.in->sin_addr.s_addr = INADDR_ANY;
  2016.             sp.in->sin_port = Lport++;
  2017.             bind(s,sp.p,sizeof(struct sockaddr_in));
  2018.             break;
  2019. #ifdef  AX25
  2020.         case AF_AX25:
  2021.             sp.ax->sax_family = AF_AX25;
  2022.             memset(sp.ax->ax25_addr,'\0',AXALEN);
  2023.             memset(sp.ax->iface,'\0',ILEN);
  2024.             bind(s,sp.p,sizeof(struct sockaddr_ax));
  2025.             break;
  2026. #endif
  2027. #ifdef  NETROM
  2028.         case AF_NETROM:
  2029.             sp.nr->nr_family = AF_NETROM;
  2030.             memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  2031.             memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  2032.             bind(s,sp.p,sizeof(struct sockaddr_nr));
  2033.             break;
  2034. #endif
  2035.     }
  2036. }
  2037.   
  2038. /* this is called by tipmail only ! - WG7J */
  2039. #ifdef TIPSERVER
  2040.   
  2041. /* Return a pair of mutually connected sockets in sv[0] and sv[1] */
  2042. int
  2043. socketpair(af,type,protocol,sv)
  2044. int af;
  2045. int type;
  2046. int protocol;
  2047. int sv[];
  2048. {
  2049.     struct usock *up0, *up1;
  2050.     if(sv == NULLINT){
  2051.         errno = EFAULT;
  2052.         return -1;
  2053.     }
  2054.     if(af != AF_LOCAL){
  2055.         errno = EAFNOSUPPORT;
  2056.         return -1;
  2057.     }
  2058.     if(type != SOCK_STREAM && type != SOCK_DGRAM){
  2059.         errno = ESOCKTNOSUPPORT;
  2060.         return -1;
  2061.     }
  2062.     if((sv[0] = socket(af,type,protocol)) == -1)
  2063.         return -1;
  2064.     if((sv[1] = socket(af,type,protocol)) == -1){
  2065.         close_s(sv[0]);
  2066.         return -1;
  2067.     }
  2068.     up0 = itop(sv[0]);
  2069.     up1 = itop(sv[1]);
  2070.     up0->cb.local->peer = up1;
  2071.     up1->cb.local->peer = up0;
  2072.     return sv[1];
  2073. }
  2074. #endif
  2075.   
  2076.   
  2077. struct inet {
  2078.     struct inet *next;
  2079.     struct tcb *tcb;
  2080.     char *name;
  2081.     int stack;
  2082.     void (*task)(int,void *,void *);
  2083. };
  2084. #define NULLINET    (struct inet *)0
  2085. struct inet *Inet_list;
  2086.   
  2087. static void i_upcall(struct tcb *tcb,int oldstate,int newstate);
  2088.   
  2089.   
  2090. /* Start a TCP server. Create TCB in listen state and post upcall for
  2091.  * when a connection comes in
  2092.  */
  2093. int
  2094. start_tcp(port,name,task,stack)
  2095. int16 port;
  2096. char *name;
  2097. void (*task)(int,void *,void *);
  2098. int stack;
  2099. {
  2100.     struct inet *in;
  2101.     struct socket lsocket;
  2102.   
  2103.     in = (struct inet *)calloc(1,sizeof(struct inet));
  2104.     lsocket.address = INADDR_ANY;
  2105.     lsocket.port = port;
  2106.     in->tcb = open_tcp(&lsocket,NULLSOCK,TCP_SERVER,0,NULLVFP,NULLVFP,i_upcall,0,-1);
  2107.     if(in->tcb == NULLTCB){
  2108.         free(in);
  2109.         return -1;
  2110.     }
  2111.     in->stack = stack;
  2112.     in->task = task;
  2113.     in->name = strdup(name);
  2114.     in->next = Inet_list;
  2115.     Inet_list = in;
  2116.     return 0;
  2117. }
  2118.   
  2119. /* State change upcall that takes incoming TCP connections */
  2120. static void
  2121. i_upcall(tcb,oldstate,newstate)
  2122. struct tcb *tcb;
  2123. int oldstate;
  2124. int newstate;
  2125. {
  2126.     struct inet *in;
  2127.     struct sockaddr_in sock;
  2128.     struct usock *up;
  2129.     int s;
  2130.   
  2131.     if(oldstate != TCP_LISTEN)
  2132.         return; /* "can't happen" */
  2133.     if(newstate == TCP_CLOSED){
  2134.         /* Called when server is shut down */
  2135.         del_tcp(tcb);
  2136.         return;
  2137.     }
  2138.     for(in = Inet_list;in != NULLINET;in = in->next)
  2139.         if(in->tcb->conn.local.port == tcb->conn.local.port)
  2140.             break;
  2141.     if(in == NULLINET)
  2142.         return; /* not in table - "can't happen" */
  2143.   
  2144.     /* Create a socket, hook it up with the TCB */
  2145.     s = socket(AF_INET,SOCK_STREAM,0);
  2146.     up = itop(s);
  2147.     sock.sin_family = AF_INET;
  2148.     sock.sin_addr.s_addr = tcb->conn.local.address;
  2149.     sock.sin_port = tcb->conn.local.port;
  2150.     bind(s,(char *)&sock,SOCKSIZE);
  2151.   
  2152.     sock.sin_addr.s_addr = tcb->conn.remote.address;
  2153.     sock.sin_port = tcb->conn.remote.port;
  2154.     up->peernamelen = SOCKSIZE;
  2155.     up->peername = mallocw(up->peernamelen);
  2156.     memcpy(up->peername,(char *)&sock,SOCKSIZE);
  2157.     up->cb.tcb = tcb;
  2158.     tcb->user = s;
  2159.   
  2160.     /* Set the normal upcalls */
  2161.     tcb->r_upcall = s_trcall;
  2162.     tcb->t_upcall = s_ttcall;
  2163.     tcb->s_upcall = s_tscall;
  2164.   
  2165.     /* And spawn the server task */
  2166.     newproc(in->name,in->stack,in->task,s,NULL,NULL,0);
  2167. }
  2168.   
  2169. /* Close down a TCP server created earlier by inet_start */
  2170. int
  2171. stop_tcp(port)
  2172. int16 port;
  2173. {
  2174.     struct inet *in,*inprev;
  2175.   
  2176.     inprev = NULLINET;
  2177.     for(in = Inet_list;in != NULLINET;inprev=in,in = in->next)
  2178.         if(in->tcb->conn.local.port == port)
  2179.             break;
  2180.     if(in == NULLINET)
  2181.         return -1;
  2182.     close_tcp(in->tcb);
  2183.     free(in->name);
  2184.     if(inprev != NULLINET)
  2185.         inprev->next = in->next;
  2186.     else
  2187.         Inet_list = in->next;
  2188.     free(in);
  2189.     return 0;
  2190. }
  2191.   
  2192. static struct usock *Usock;        /* Socket entry array */
  2193.   
  2194. struct usock *addsocket(void) {
  2195.     struct usock *new,*up;
  2196.   
  2197.     /* See if we can allocate the socket */
  2198.     if( (new = (struct usock *) calloc(1,sizeof(struct usock))) == NULLUSOCK)
  2199.         return NULLUSOCK;
  2200.   
  2201.     /* Now add it to the end, to keep the list in increasing order ! */
  2202.     if(Usock == NULLUSOCK) {   /* the first one ! */
  2203.         new->number = SOCKBASE;
  2204.         Usock = new;
  2205.     } else {
  2206.         /* find the last socket */
  2207.         for(up=Usock;up->next;up=up->next);
  2208.         new->number = up->number + 1;
  2209.         up->next = new;
  2210.     }
  2211.     return new;
  2212. }
  2213.   
  2214. void deletesocket(int s) {
  2215.     struct usock *up,*pp;
  2216.     extern struct proc *Cmdpp;
  2217.   
  2218.     /* Find the socket number to delete */
  2219.     for(pp=NULL,up=Usock;up;pp=up,up=up->next)
  2220.         if(up->number == s)
  2221.             break;
  2222.     if(!up)
  2223.         /* Not found, what happened ??? */
  2224.         return;
  2225.   
  2226. #ifdef notdef
  2227.     if(s < SOCKBASE+2 && up->owner == Cmdpp) {
  2228.         /* We somehow manage to close the command processor's output stream socket! */
  2229. #ifdef STKTRACE
  2230.         stktrace();   /* trace calling stack! */
  2231. #endif
  2232.         return;
  2233.     }
  2234. #endif
  2235.   
  2236.     /* Link it out of the list */
  2237.     if(!pp) /* First one on list */
  2238.         Usock = Usock->next;
  2239.     else
  2240.         pp->next = up->next;
  2241.   
  2242.      /* Free the memory */
  2243.     free(up);
  2244. }
  2245.   
  2246. /* Convert a socket index to an internal user socket structure pointer */
  2247. struct usock *itop(int s)
  2248. {
  2249.     struct usock *up;
  2250.   
  2251.     for(up=Usock;up;up=up->next)
  2252.         if(up->number == s)
  2253.             break;
  2254.     return up;
  2255. }
  2256.   
  2257. /* Find the next socket in the list */
  2258. int getnextsocket(int s) {
  2259.     struct usock *up;
  2260.   
  2261.     for(up=Usock;up;up=up->next)
  2262.         if(up->number > s)
  2263.             break;
  2264.     if(up)
  2265.         return up->number;
  2266.     return -1;
  2267. }
  2268.   
  2269.   
  2270.