home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / contribu / byu_tel2.hqx / tcpip / userd.c < prev    next >
Text File  |  1989-07-08  |  35KB  |  1,585 lines

  1. /*
  2. *  USER.C
  3. *  Network library interface routines
  4. *  Generally called by the session layer
  5. *
  6. ****************************************************************************
  7. *                                                                          *
  8. *      part of:                                                            *
  9. *      TCP/IP kernel for NCSA Telnet                                       *
  10. *      by Tim Krauskopf                                                    *
  11. *                                                                          *
  12. *      National Center for Supercomputing Applications                     *
  13. *      152 Computing Applications Building                                 *
  14. *      605 E. Springfield Ave.                                             *
  15. *      Champaign, IL  61820                                                *
  16. *                                                                          *
  17. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  18. *                                                                          *
  19. ****************************************************************************
  20. *  Revisions:
  21. *  10/87  Initial source release, Tim Krauskopf
  22. *  2/88  typedef support for other compilers (TK)
  23. *  8/88  Gaige Paulsen - support for MacTCP drivers
  24. *  1/89  TK - conversion to new drivers, minor update for new calling convention
  25. *  6/89  TK - update to MacTCP 1.0 include files and use of GetMyIPAddr()
  26. *
  27. */
  28. #define MASTERDEF 1
  29. #include "stdio.h"
  30. #include "protocol.h"
  31. #include "data.h"
  32.  
  33. #include <Devices.h>
  34. #include "MacTCPCommonTypes.h"
  35. #include "TCPPB.h"
  36. #include "UDPPB.h"
  37. #include "getmyipaddr.h"
  38.  
  39. #ifdef TRUSTING
  40. #define initMyWorld()    /* noop */
  41. #define myWorld()        /* noop */
  42. #define theirWorld()    /* noop */
  43. #endif  TRUSTING
  44.  
  45. int EtherNet = -99;        /* Signify Drivers */
  46.  
  47. #define LOWWATER 600
  48.  
  49. void initUDPstub(),UDPstub();
  50.  
  51. pascal void TCPNotify();
  52. pascal void UDPNotify();
  53. long openComplete();
  54. long closeComplete();
  55. long sendComplete();
  56.  
  57. /*
  58.  * UDP Stuff
  59.  */
  60.  
  61. #define    UDPBUFSIZ    (1024*8)
  62. #define    getUPB(x,y,z,a)    (UDPiopb *)getPB(x,y,z,a)
  63.  
  64. typedef struct UDPRec {
  65.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  66.     char   *buffer;                    /* Where the immovable UDP buffer is */
  67.     uint    port;                    /* Which UDP port to use */
  68.     } UDPRec, *UDPRPtr;
  69.  
  70. UDPRPtr uport[ NPORTS];                /* our wonderful little thingies. */
  71.  
  72. /*
  73.  * TCP Stuff
  74.  */
  75. #define    noError    0
  76. #define TCPBUFSIZ    (1024*8)
  77. #define    MAX_FDS_ELEMS    32
  78. #define    MAX_SWDS_ELEMS    16
  79. #define MAX_FREE_PB        128
  80. #define MAX_FREE_SWDS    64
  81.  
  82. #define    Qcall    true
  83. #define    noQcall    false
  84.  
  85. typedef    struct freeEntry {
  86.     int inuse;                        /* is this being used? */
  87.     Ptr    ptr;                        /* Pointer to the free entry */
  88.     } freeEntry;
  89.     
  90. typedef struct exfds {
  91.     int    inuse;                        /* Is this being used */
  92.     wdsEntry fds;                    /* The real data */
  93.     } exfds;
  94.     
  95. typedef struct StreamRec {
  96.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  97.     char   *buffer;                    /* Where the immovable TCP buffer is */
  98.     int        push;                    /* TRUE if we should push next data block */
  99.     char   *sbuffer;                /* Where the send buffer is */
  100.     wdsEntry    fds[MAX_FDS_ELEMS];    /* Free Data Structure list */
  101.     exfds    exFDS[MAX_FDS_ELEMS];    /* exFDS entries */
  102.     int        maxFDSused;                /* Max of the FDS's that have been used */
  103.     } StreamRec, *StreamRPtr;
  104.     
  105. short TCPd = 0;                        /* refnum of TCP drivers */
  106.  
  107. StreamRPtr streams[NPORTS];
  108.  
  109. char *malloc();
  110. int numPB=0;                        /* Number of PB's ever allocated  (Perf. mon. only ) */
  111. int numSWDS=0;                        /* Number of SWDS's ever alloc'd (PM Only) */
  112.  
  113. freeEntry    freePB[ MAX_FREE_PB];
  114. freeEntry    freeSWDS[ MAX_FREE_SWDS];
  115.  
  116. /**************************************************************************/
  117. wdsEntry *getSWDS()
  118. {
  119.     wdsEntry *wds;
  120.     int n=0;
  121.     
  122.     while (freeSWDS[n].inuse &&  n<MAX_FREE_SWDS) n++;
  123.     if (n >= MAX_FREE_SWDS)
  124.         return(0L);
  125.     
  126.     freeSWDS[n].inuse=1;
  127.     if (freeSWDS[n].ptr==0L) {
  128.         char temp[50];
  129.         freeSWDS[n].ptr = malloc ( sizeof(wdsEntry) *MAX_SWDS_ELEMS);
  130.         numSWDS++;
  131.         sprintf(temp,"New SWDS(%d)",numSWDS);
  132.         putln(temp);
  133.         }
  134.     return( freeSWDS[n].ptr);
  135. }
  136.  
  137. /**************************************************************************/
  138. returnSWDS( wds)
  139. wdsEntry *wds;
  140. {
  141.     int n=0;
  142.     
  143.     while (freeSWDS[n].ptr != wds && n<MAX_FREE_SWDS) n++;
  144.     if (n >= MAX_FREE_SWDS)
  145.         return(-1);
  146.     freeSWDS[n].inuse=0;
  147. }
  148.  
  149. /**************************************************************************/
  150. TCPiopb *getPB( driver, call, stream, usernum)
  151. int driver, call, usernum;
  152. unsigned long stream;
  153. {
  154.     TCPiopb *pbp;
  155.     int n=0;
  156.     
  157.     while (freePB[n].inuse &&  n<MAX_FREE_PB) n++;
  158.     if (n >= MAX_FREE_PB)
  159.         return(0L);
  160.     
  161.     freePB[n].inuse=1;
  162.     if (freePB[n].ptr==0L) {
  163.         char temp[50];
  164.         
  165.         freePB[n].ptr = malloc ( sizeof(TCPiopb)+sizeof(int) );
  166.         numPB++;
  167.         sprintf(temp,"New PB(%d)",numPB);
  168.         putln(temp);
  169.         }
  170.     pbp = freePB[n].ptr;
  171.  
  172.  
  173.     if (!pbp) {
  174.         putln("GETPB failed! panic! ");
  175.         quit();
  176.         }
  177.     
  178.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  179.     
  180.     pbp->ioCRefNum = driver;
  181.     pbp->tcpStream=stream;
  182.     pbp->csCode = call;
  183.     
  184.     return(pbp);
  185. }
  186.  
  187. /**************************************************************************/
  188. clearPB( pbp, driver, call, stream, usernum)
  189. TCPiopb *pbp;
  190. int driver, call, usernum;
  191. unsigned long stream;
  192. {
  193.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  194.     
  195.     pbp->ioCRefNum = driver;
  196.     pbp->tcpStream=stream;
  197.     pbp->csCode = call;
  198.     
  199. }
  200.  
  201. returnPB( pbp)
  202. TCPiopb *pbp;
  203. {
  204.     int n=0;
  205.     
  206.     while (freePB[n].ptr != pbp && n<MAX_FREE_PB) n++;
  207.     if (n >= MAX_FREE_PB)
  208.         return(-1);
  209.     freePB[n].inuse=0;
  210.     
  211. }
  212.  
  213. /***************************************************************************/
  214. /*  netread
  215. *   Read from a connection buffer into a user buffer.  
  216. *   Returns number of bytes read, < 0 on error
  217. * NOTE:
  218. *    current version very inefficient, but hopefully works.
  219. */
  220. netread(pnum,buffer,n)
  221.     int pnum,n;
  222.     char *buffer;
  223.     {
  224.     int howmany,i;
  225.     StreamRPtr p;
  226.     TCPiopb *pbp;
  227.     int inQ, reqdamt;
  228.     
  229.     if (pnum < 0)            /* check validity */
  230.         return(-2);
  231.  
  232.     if (NULL == (p = streams[pnum]))
  233.         return(-2);
  234.     
  235.     
  236.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  237.     if (PBControl( pbp, noQcall) != noError) {
  238.         putln("TCPStatus failed(read)"); return(-1);
  239.         }
  240. #ifdef DEBUGHEADERS    
  241.     { char temp[100];
  242.         sprintf(temp, "Stat: %x(%d)->%x(%d) <%d,%d,%d> [%d,%d] {%d,%d}",
  243.             (int)pbp->csParam.status.remoteHost,
  244.             (int)pbp->csParam.status.remotePort,
  245.             (int)pbp->csParam.status.localHost,
  246.             (int)pbp->csParam.status.localPort,
  247.             (int)pbp->csParam.status.tosFlags,
  248.             (int)pbp->csParam.status.precedence,
  249.             (int)pbp->csParam.status.connectionState,
  250.             (int)pbp->csParam.status.sendWindow,
  251.             (int)pbp->csParam.status.rcvWindow,
  252.             (int)pbp->csParam.status.amtUnackedData,
  253.             (int)pbp->csParam.status.amtUnreadData);
  254.         putln(temp);
  255.     }
  256. #endif DEBUGHEADERS
  257.     
  258.     if (pbp->csParam.status.connectionState !=8) {
  259.         char temp[50];
  260.         sprintf(temp,"CState: %d is %d",(int)pnum, (int)pbp->csParam.status.connectionState);
  261.         putln(temp);
  262.         return(-1);                              /* Connection not established */
  263.         }
  264.     
  265.     inQ = pbp->csParam.status.amtUnreadData;
  266.     reqdamt = n >inQ ? inQ : n;
  267.     
  268.     clearPB( pbp, TCPd, TCPRcv, p->stream, pnum);
  269.     pbp->csParam.receive.rcvBuff = buffer;
  270.     pbp->csParam.receive.rcvBuffLen = reqdamt;
  271.     
  272.     if (reqdamt<1) {                                /* Drop out if no data */
  273.         returnPB(pbp);
  274.         return(0);
  275.         }
  276.     
  277.     if (PBControl( pbp, noQcall) != noError) {
  278.         char temp[100];
  279.         sprintf(temp,"TCPRcv failed (%d)",i);
  280.         putln( temp);
  281.         return(-1);
  282.         }
  283.         
  284.     reqdamt = pbp->csParam.receive.rcvBuffLen;
  285.     if (reqdamt<inQ) {
  286.         netputuev( CONCLASS, CONDATA, pnum);            /* more data to get */
  287.         }
  288.         
  289.     returnPB(pbp);                    /* Trash PB */
  290. #ifdef TESTINGPARMS
  291.     {
  292.         char temp[100];
  293.         sprintf(temp, "NETRead: %d from %d", reqdamt, pnum);
  294.         putln(temp);
  295.     }
  296. #endif TESTINGPARMS
  297.     return(reqdamt);
  298. }
  299.  
  300. /************************************************************************/
  301. /* netwrite
  302. *  write something into the output queue, netsleep routine will come
  303. *  around and send the data, etc.
  304. *
  305. */
  306. netwrite(pnum,buffer,nsend)
  307.     int pnum,nsend;
  308.     char *buffer;
  309.     {
  310.     StreamRPtr p;
  311.     char *sbuf;
  312.     wdsEntry *swds;
  313.     int remaining, queued, n,m;
  314.     TCPiopb *pbp;
  315.     
  316.     if (pnum < 0)
  317.         return(-2);
  318.  
  319.     if ( (p = streams[pnum]) == NULL)
  320.         return(-2);
  321.     
  322.     if ( !nsend )
  323.         return(0);
  324.         
  325.     swds = getSWDS();
  326.     
  327.     reclaim( p);
  328.     compressfds( p->fds);
  329.  
  330.     n=0; remaining = nsend;
  331.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  332.         swds[n].ptr = p->fds[n].ptr;
  333.         if ( p->fds[n].length > remaining) {
  334.             swds[n].length = remaining;
  335.             p->fds[n].length -= remaining;
  336.             p->fds[n].ptr += remaining;
  337.             remaining=0;
  338.             }
  339.         else {
  340.             swds[n].length =  p->fds[n].length;
  341.             remaining -= p->fds[n].length;
  342.             p->fds[n].length = 0;
  343.             p->fds[n].ptr = 0;
  344.             }
  345.         n++;
  346.         }
  347.     if (n>p->maxFDSused) p->maxFDSused=n;
  348.     
  349.     compressfds( p->fds);
  350.     queued = nsend-remaining;
  351.     
  352.     for (m=0; m<n; m++) {
  353.         memcpy( swds[m].ptr, buffer, swds[m].length);    /* Put data in WDS */
  354.         buffer +=swds[m].length;
  355.         }
  356.     swds[m].ptr =0L;
  357.     swds[m].length=0;
  358.     
  359.     pbp=getPB( TCPd, TCPSend, p->stream, pnum);            /* Make send call */
  360.     pbp->csParam.send.wdsPtr = swds;
  361.     pbp->csParam.send.pushFlag = p->push;
  362.     
  363.     pbp->ioCompletion = sendComplete;                    /* Completion routine */
  364.  
  365.     p->push=0;
  366.  
  367.     if (PBControl( pbp, Qcall) != noError) {
  368.         putln("TCPSend failed to Q"); return(-1);
  369.         }
  370.     
  371. #ifdef TESTINGPARMS
  372.     putln("TCP Sent");
  373.     { char temp[100];
  374.         sprintf(temp, "TCP Sent: %d of %d on %d [%d/%d]", queued, nsend, pnum,n,p->maxFDSused);
  375.         putln(temp);
  376.     }
  377. #endif TESTINGPARMS
  378.     return(queued);
  379. }
  380.  
  381. /**************************************************************************/
  382. /*  netpush
  383. *   attempt to push the rest of the data from the queue
  384. *   and then return whether the queue is empty or not (0 = empty)
  385. *   returns the number of bytes in the queue.
  386. */
  387. netpush(pnum)
  388.     int pnum;
  389.     {
  390.     StreamRPtr p;
  391.     TCPiopb *pbp;
  392.     int inQ;
  393.     
  394.     if (pnum < 0)
  395.         return(-2);
  396.  
  397.     if (NULL == (p = streams[pnum]))
  398.         return(-2);
  399.  
  400.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  401.     if (PBControl( pbp, noQcall) != noError) {
  402.         putln("TCPStatus failed(push)"); return(-1);
  403.         }
  404.     inQ = pbp->csParam.status.amtUnackedData;
  405.     returnPB( pbp);
  406.     
  407.     p->push=1;
  408.     
  409.     return(inQ);
  410.  
  411. }    
  412.  
  413. /**************************************************************************/
  414. /*  netqlen
  415. *   return the number of bytes waiting to be read from the incoming queue.
  416. */
  417. netqlen(pnum)
  418.     int pnum;
  419.     {
  420.     StreamRPtr p;
  421.     TCPiopb *pbp;
  422.     int inQ;
  423.     
  424.     if (pnum < 0)
  425.         return(-2);
  426.  
  427.     if (NULL == (p = streams[pnum]))
  428.         return(-2);
  429.  
  430.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  431.     if (PBControl( pbp, noQcall) != noError) {
  432.         putln("TCPStatus failed(qlen)"); return(-1);
  433.         }
  434.     inQ = pbp->csParam.status.amtUnreadData;
  435.     returnPB( pbp);
  436.     
  437.     p->push = 1;
  438.     return(inQ);
  439. }
  440.  
  441. /**************************************************************************/
  442. /*  netroom()
  443. *    return how much room is available in output buffer for a connection
  444. */
  445. netroom(pnum)
  446.     int pnum;
  447.     {
  448.     StreamRPtr p;
  449.     TCPiopb *pbp;
  450.     int inQ,n;
  451.     
  452.     if (pnum < 0)
  453.         return(-2);
  454.  
  455.     if (NULL == (p = streams[pnum]))
  456.         return(-2);
  457.  
  458.     reclaim( p);
  459.     compressfds( p->fds);
  460.  
  461. #ifdef OLDM
  462.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  463.     if (PBControl( pbp, noQcall) != noError) {
  464.         putln("TCPStatus failed(room)"); return(-1);
  465.         }
  466.     inQ = pbp->csParam.status.sendWindow -
  467.                 pbp->csParam.status.amtUnackedData;
  468.     returnPB( pbp);
  469. #endif
  470.  
  471.     inQ = n = 0;
  472.     while (p->fds[n].ptr) {
  473.     
  474.         inQ += p->fds[n].length;                /* add up free list space */
  475.         n++;
  476.         }
  477.  
  478.     return(inQ);
  479. }
  480.  
  481. /**************************************************************************/
  482. /* netsegsize and neterrchange and netsetip and netgetip
  483. *
  484. *  set operating parameters to change them from the default values used.
  485. */
  486.  
  487. netsegsize(newsize)
  488.     int newsize;
  489.     {
  490.     int i;
  491.  
  492.     i = nnsegsize;
  493.     nnsegsize = newsize;
  494.  
  495.     return(i);
  496. }
  497.  
  498. /**************************************************************************/
  499. netquench(newcredit)
  500.     int newcredit;
  501.     {
  502.     int i;
  503.  
  504.     i = nncredit;
  505.     nncredit = newcredit;
  506.  
  507.     return(i);
  508. }
  509.  
  510. /**************************************************************************/
  511. netarptime(t)                    /* dlayer timeout in secs */
  512.     int t;
  513.     {
  514.     nndto = t;
  515. }
  516.  
  517. /**************************************************************************/
  518. netsetip(st)
  519.     unsigned char *st;
  520.     {
  521. /*
  522. *  this is a no-op with the MacTCP driver
  523. */
  524. }
  525.  
  526. /**************************************************************************/
  527. netgetip(st)
  528. unsigned char *st;
  529. {
  530.     struct IPParamBlock mypb;
  531.     long netmask;
  532.  
  533.     putln("Attempting getmyipaddr");
  534.     
  535.     memset( &mypb, '\0', sizeof(struct IPParamBlock));    /* Default to all zeros */
  536.     
  537.     mypb.ioCRefNum = TCPd;            /* TCP driver has to be open by now */
  538.     mypb.csCode = ipctlGetAddr;
  539.  
  540.     if (PBControl( &mypb, noQcall) != noError) {
  541.         putln("Getting my address failed"); 
  542.         return(-1);
  543.         }
  544.     
  545.     memcpy(st, &mypb.ourAddress, 4);    /* copy the address */
  546.     
  547.     /* netmask is here if we want it, too */
  548.     
  549.     return(0);
  550.  
  551. }
  552.  
  553.  
  554. /**************************************************************************/
  555. netsetmask(st)
  556. unsigned char *st;
  557. {
  558.     movebytes(nnmask,st,4);
  559. }
  560.  
  561. /**************************************************************************/
  562. netgetmask(st)
  563. unsigned char *st;
  564. {
  565.     movebytes(st,nnmask,4);
  566. }
  567.  
  568. netfromport(port)            /* next "open" will use this port */
  569. int16 port;
  570. {
  571.     nnfromport = port;
  572.  
  573. }
  574.  
  575. /**************************************************************************/
  576. /*  netest?
  577. *  is a particular session established yet?
  578. *  Returns 0 if the connection is in the established state.
  579. */
  580. netest(pnum)
  581. int pnum;
  582. {
  583.     StreamRPtr p;
  584.     TCPiopb *pbp;
  585.     int inQ;
  586.     
  587.     if (pnum < 0)
  588.         return(-2);
  589.  
  590.     if (NULL == (p = streams[pnum]))
  591.         return(-2);
  592.  
  593.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  594.     if (PBControl( pbp, noQcall) != noError) {
  595.         putln("TCPStatus failed(est)");
  596.         inQ = -1;
  597.         }
  598.     else 
  599.         inQ = pbp->csParam.status.connectionState !=8;
  600.     returnPB( pbp);
  601.     
  602.     return(inQ);
  603.  
  604. }
  605.  
  606. /**************************************************************************/
  607. /*  netlisten
  608. *   Listen to a TCP port number and make the connection automatically when
  609. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  610. *   with a CONOPEN event.  Save the port number returned to refer to this
  611. *   connection.
  612. *
  613. *   usage:   portnum = netlisten(service);
  614. *            int service;
  615. *
  616. */
  617. netlisten(serv)
  618. uint serv;
  619. {
  620.     int    pnum;
  621.     StreamRPtr p;
  622.     uint16 nn;
  623.     TCPiopb *pbp;
  624.  
  625.     pnum = makestream();
  626.  
  627.     if (pnum < 0)
  628.         return(-2);
  629.  
  630.     if (NULL == (p = streams[pnum]))
  631.         return(-2);
  632.  
  633.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, pnum);            /* Make Listen call */
  634.     
  635.     pbp->csParam.open.localPort = serv;
  636.     pbp->ioCompletion = openComplete;                    /* IO Completion for open */
  637.     
  638.     if (PBControl( pbp, Qcall) != noError) {
  639.         putln("TCPListen failed"); return(-1);
  640.         }
  641.         
  642.     return(pnum);
  643. }
  644.  
  645. /***********************************************************************/
  646. /*  netgetftp
  647. *  Provides the information that ftp needs to open a stream back to the
  648. *  originator of the command connection.  The other side's IP number
  649. *  and the port numbers to be used to calculate the default data connection
  650. *  number.  Returns values in an integer array for convenient use in 
  651. *  PORT commands.
  652. */
  653. netgetftp(a,pnum)
  654. int a[];
  655. int pnum;
  656. {
  657.     StreamRPtr p;
  658.     TCPiopb *pbp;
  659.     long temp;
  660.     
  661.     if (pnum < 0)
  662.         return(-2);
  663.  
  664.     if (NULL == (p = streams[pnum]))
  665.         return(-2);
  666.  
  667.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  668.     if (PBControl( pbp, noQcall) != noError) {
  669.         putln("TCPStatus failed(getftp)"); return(-1);
  670.         }
  671.  
  672.     temp      = pbp->csParam.status.remoteHost;
  673.     a[0]= (temp>>24) & 0xff;
  674.     a[1]= (temp>>16) & 0xff;
  675.     a[2]= (temp>> 8) & 0xff;
  676.     a[3]= (temp    ) & 0xff;
  677.     temp    = pbp->csParam.status.localPort;
  678.     a[4]= (temp>> 8) & 0xff;
  679.     a[5]= (temp    ) & 0xff;
  680.     temp    = pbp->csParam.status.remotePort;
  681.     a[6]= (temp>> 8) & 0xff;
  682.     a[7]= (temp    ) & 0xff;
  683.  
  684.     returnPB( pbp);
  685. }
  686.  
  687. /**************************************************************************/
  688. /*  netopen
  689. *   Netopen is a cheap way to open a connection without looking up any
  690. *   machine information.  Uses suitable default values for everything.
  691. */
  692. netopen(s,tport)
  693. unsigned char *s;
  694. uint tport;
  695. {
  696.  
  697.     return(netxopen(s,tport,MINRTO,TSENDSIZE,DEFSEG,DEFWINDOW));
  698. }
  699.  
  700.  
  701. /**************************************************************************/
  702. /*  netxopen
  703. *   Open a network socket for the user.
  704. *
  705. */
  706. netxopen(machine,service,rto,mtu,mseg,mwin)
  707. uint32 *machine;
  708. uint service,rto,mtu,mseg,mwin;        /* unix service port number */
  709. {
  710.     int    pnum;
  711.     StreamRPtr p;
  712.     uint16 nn;
  713.     TCPiopb *pbp;
  714.     char temp[100];
  715.     
  716.     pnum = makestream();
  717.  
  718.     if (pnum < 0)
  719.         return(-2);
  720.  
  721.     if (NULL == (p = streams[pnum]))
  722.         return(-2);
  723.  
  724.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, pnum);            /* Make Listen call */
  725.     
  726.     pbp->csParam.open.remoteHost = *machine;            /* IP # */
  727.     pbp->csParam.open.remotePort = service;                /* Port */
  728.     pbp->csParam.open.localPort = nnfromport;            /* My Port */
  729.     nnfromport=0;                                            /* Next one is random */
  730.     
  731.     pbp->ioCompletion = openComplete;                    /* IO Completion for open */
  732.     
  733.     if (PBControl( pbp, Qcall) != noError) {
  734.         putln("TCPOpen failed(Active)"); return(-1);
  735.         }
  736.     sprintf(temp,"TCPOpen on %d",pnum);
  737.     putln(temp);
  738.     return(pnum);
  739. }
  740.  
  741.  
  742. /**************************************************************************/
  743. /* netclose
  744. *  Do appropriate actions to return connection state to SCLOSED which
  745. *  enables the memory for that port to be reused.
  746. *
  747. *    Specifically:
  748. *        o If status is closed, then release the data structures
  749. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  750. *            which should make the session layer call us again
  751. */
  752. netclose(pnum)
  753. int pnum;
  754. {
  755.     StreamRPtr p;
  756.     TCPiopb *pbp;
  757.     int errorCode=0;
  758.     int status;
  759.  
  760.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  761.         return(-1);
  762.  
  763.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  764.         return (1);
  765.  
  766.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  767.     if ((errorCode = PBControl( pbp, noQcall)) != noError) {
  768.         if ( errorCode == invalidStreamPtr) {
  769.             putln("TCPStatus failed because of bad stream pointer (close)");
  770.             return(-1);
  771.             }
  772.         else
  773.             status=0;
  774.         }
  775.     else 
  776.         status = pbp->csParam.status.connectionState;            /* The connection Status */
  777.  
  778.     if (status < 18 && status >2 ) {                            /* We aren't closed yet ! */
  779.         char temp[50];
  780.         sprintf(temp, "TCPClose being attempted state ...[%d]",status);    /* Prolly because outstanding close */
  781.         putln(temp);
  782.         clearPB( pbp, TCPd, TCPClose, p->stream, pnum);            /* Make Close call */
  783.         pbp->ioCompletion = closeComplete;                        /* IO Completion for close */
  784.         if ((errorCode=PBControl( pbp, Qcall)) != noError) {
  785.             char temp[50];
  786.             sprintf(temp, "TCPClose failed...[%d]",errorCode);    /* Prolly because outstanding close */
  787.             putln(temp);
  788.             }
  789.         return (0);                                            /* Return with OK */
  790.         }
  791.  
  792.     /* IF we got here, we must be at closed state, so free memory */
  793.  
  794.     putln("TCP Being Released...... ");
  795.     clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Release call */
  796.     if (PBControl( pbp, noQcall) != noError) {
  797.         putln("TCPRelease failed"); return(-1);
  798.         }
  799.     
  800.     free( p->buffer);                /* Free Receive Buffer */
  801.     free( p->sbuffer);                /* Free Send Buffer */
  802.     free( p);                        /* Free Stream Structure */
  803.     streams[pnum]=0L;
  804.  
  805.     returnPB(pbp);
  806.     return(0);
  807. }
  808.  
  809. /**************************************************************************/
  810. /* netabort
  811. *    Nuke the connection, NOW!
  812. */
  813. netabort(pnum)
  814. int pnum;
  815. {
  816.     StreamRPtr p;
  817.     TCPiopb *pbp;
  818.     int errorCode=0;
  819.  
  820.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  821.         return(-1);
  822.  
  823.     if ((p = streams[pnum]) != NULL) {            /* something there */
  824.         pbp=getPB( TCPd, TCPAbort, p->stream, pnum);            /* Make Close call */
  825.         if ((errorCode=PBControl( pbp, noQcall)) != noError) {
  826.             char temp[50];
  827.             sprintf(temp, "TCPAbort failed...[%d]",errorCode);
  828.             putln(temp);
  829.             }
  830.         clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Close call */
  831.         if (PBControl( pbp, noQcall) != noError) {
  832.             putln("TCPRelease failed"); return(-1);
  833.             }
  834.         }
  835.     else
  836.         return(1);
  837.     
  838.     free( p->buffer);                /* Free Receive Buffer */
  839.     free( p->sbuffer);                /* Free Send Buffer */
  840.     free( p);                        /* Free Stream Structure */
  841.     streams[pnum]=0L;
  842.  
  843.     returnPB(pbp);
  844.     return(0);
  845. }
  846.  
  847. /**************************************************************************/
  848. /*  netinit
  849. *   Calls all of the various initialization routines that set up queueing
  850. *   variables, static values, reads configuration files, etc.
  851. */
  852.  
  853. netinit()
  854. {
  855.     int i;
  856.     
  857.     for (i=0; i<NPORTS;i++)
  858.         streams[i]= (StreamRPtr) 0;
  859.         
  860.     for (i=0; i<NPORTS;i++)
  861.         uport[i]= (UDPRPtr) 0;
  862.     
  863.     if (OpenDriver(".IPP",&TCPd) != noError) {
  864.         putln( "Couldn't open IP driver ");
  865.         quit();
  866.         }
  867.         
  868.     initMyWorld();
  869.     initUDPstub( UDPNotify);
  870.     
  871.     return(0);                /* set up empty packets */
  872. }
  873.  
  874. /*************************************************************************/
  875. /*  netshut
  876. *   Close all the connections and turn off the hardware.
  877. */
  878. netshut()
  879.     {
  880.     int i;
  881.  
  882.     for (i=0; i < NPORTS ; i++) 
  883.         if (streams[i] != (StreamRPtr) NULL)
  884.             netabort(i);                        /* Prolly should abort */
  885.     for (i=0; i < NPORTS ; i++) 
  886.         if (uport[i] != (UDPRPtr) NULL)
  887.             netuclose(uport[i]->port);            /* Shut down UDP too... */
  888. #ifdef SAFE
  889.     CloseDriver( TCPd);
  890. #endif SAFE
  891. }
  892.  
  893. /**************************************************************************/
  894. /*
  895.  * Returns an empty stream
  896.  */ 
  897. makestream()
  898. {
  899.     int    pnum;
  900.     StreamRPtr p;
  901.     TCPiopb *pbp;
  902.     int i;
  903.     
  904.     for ( pnum=0; streams[pnum]!= NULL && pnum<NPORTS; pnum++);
  905.     
  906.     if (pnum >= NPORTS)
  907.         return(-2);
  908.  
  909.     p= streams[pnum] =malloc(sizeof(StreamRec));
  910.  
  911.     if ((p->buffer = malloc( TCPBUFSIZ)) == (char *)NULL)
  912.         return(-1);
  913.     if ((p->sbuffer = malloc( TCPBUFSIZ)) == (char *)NULL)
  914.         return(-1);
  915.     
  916.     for (i=0; i<MAX_FDS_ELEMS; i++) {
  917.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  918.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  919.         }
  920.     p->fds[0].length = TCPBUFSIZ;
  921.     p->fds[0].ptr = p->sbuffer;
  922.     p->maxFDSused=0;
  923.     
  924.     pbp=getPB( TCPd, TCPCreate, 0, pnum);            /* Make Create call */
  925.     pbp->csParam.create.rcvBuff = p->buffer;
  926.     pbp->csParam.create.rcvBuffLen = TCPBUFSIZ;
  927.     pbp->csParam.create.notifyProc = TCPNotify;
  928.     if (PBControl( pbp, noQcall) != noError) {
  929.         putln("TCPCreate failed"); return(-1);
  930.         }
  931.     
  932.     p->stream = pbp->tcpStream;
  933.     
  934.     putln("Made a new stream");
  935.     returnPB(pbp);
  936.     return(pnum);
  937. }
  938.  
  939.  
  940. /**************************************************************************/
  941. pascal void TCPNotify( streamPtr, code, uptr, terminReason, icmpMsg)
  942. StreamPtr streamPtr;
  943. enum  TCPEventCode code;
  944. enum  TCPTerminationReason terminReason;
  945. struct ICMPReport *icmpMsg;
  946. Ptr uptr;   /* user data pointer */
  947. {
  948.     StreamRPtr p;
  949.     int pnum;
  950.     
  951.     myWorld();
  952.     pnum= findbystream(streamPtr);
  953.     
  954.     if (pnum<0 || (p=streams[pnum])==0L) {
  955.         theirWorld();
  956.         return;
  957.         }
  958.     
  959.     switch( code) {
  960.         case TCPTerminate:
  961.         case TCPClosing:
  962.             netputevent(CONCLASS, CONCLOSE, pnum);
  963.             break;
  964.         case TCPULPTimeout:
  965.             netputevent(CONCLASS, CONFAIL, pnum);
  966.             break;
  967.         case TCPDataArrival:
  968.         case TCPUrgent:
  969.             netputuev(CONCLASS, CONDATA, pnum);
  970.             break;
  971.         case TCPICMPReceived:
  972.         default:
  973.             break;
  974.         }
  975.     theirWorld();
  976.     return;
  977. }
  978.  
  979. /**************************************************************************/
  980. int findbystream( streamPtr)
  981. StreamPtr streamPtr;
  982. {
  983.     int pnum=0;
  984.     
  985.     while (pnum<NPORTS &&
  986.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  987.         pnum++;
  988.     if (pnum >=NPORTS)
  989.         return(-1);
  990.     else
  991.         return(pnum);
  992. }
  993.  
  994. /*************************************************************************/
  995. /*  netopen2
  996. *   Send out repeat SYN on a connection which is not open yet
  997. *   Checks, and only sends one if needed.
  998. *   Returns 1 if the state is still SYNS and 0 if the connection has proceeded.
  999. *   The timing is all handled at a higher layer.
  1000. */
  1001. netopen2(pnum)
  1002. int pnum;
  1003. {
  1004.     return( netest(pnum));
  1005. }
  1006.  
  1007. /**************************************************************************/
  1008. long openComplete( pbp)
  1009. TCPiopb *pbp;
  1010. {
  1011.     StreamRPtr p;
  1012.     int pnum;
  1013.     
  1014.     myWorld();
  1015.     pnum= findbystream(pbp->tcpStream);
  1016.     
  1017.     if (pnum<0 || (p=streams[pnum])==0L) {
  1018.         theirWorld();
  1019.         return(-1);
  1020.         }
  1021.         
  1022.     if (pbp->ioResult !=noError) 
  1023.         netputevent(CONCLASS, CONFAIL, pnum);            /* Failure ... */
  1024.     else 
  1025.         netputevent(CONCLASS, CONOPEN, pnum);            /* Success ! */
  1026.  
  1027.     returnPB( pbp);
  1028.  
  1029.     theirWorld();
  1030.     return(0);
  1031.     
  1032. }
  1033.  
  1034. /**************************************************************************/
  1035. long sendComplete( pbp)
  1036. TCPiopb *pbp;
  1037. {
  1038.     StreamRPtr p;
  1039.     int pnum;
  1040.     wdsEntry *swds;
  1041.     int i=0,j=0;
  1042.     
  1043.     myWorld();
  1044.     swds = pbp->csParam.send.wdsPtr;
  1045.     
  1046.     pnum= findbystream(pbp->tcpStream);
  1047.     if (pnum<0 || (p=streams[pnum])==0L) {
  1048.         theirWorld();
  1049.         return(-1);
  1050.         }
  1051.  
  1052.     returnSWDS( swds);
  1053.     returnPB( pbp);
  1054.  
  1055.     giveback( p, pbp->csParam.send.wdsPtr);            /* Give this back.... NOW */
  1056.     
  1057.     theirWorld();
  1058.     return(0);
  1059. }
  1060.  
  1061.  
  1062. /**************************************************************************/
  1063. long closeComplete( pbp)
  1064. TCPiopb *pbp;
  1065. {
  1066.     StreamRPtr p;
  1067.     int pnum;
  1068.     
  1069.     myWorld();
  1070.     pnum= findbystream(pbp->tcpStream);
  1071.     
  1072.     if (pnum<0 || (p=streams[pnum])==0L) {
  1073.         theirWorld();
  1074.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1075.         return(-1);
  1076.         }
  1077.         
  1078.     if (pbp->ioResult !=noError) 
  1079.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1080.     else 
  1081.         netputevent(SCLASS, CLOSEDONE, pnum);            /* Success ! */
  1082.  
  1083.     returnPB( pbp);
  1084.  
  1085.     theirWorld();
  1086.     return(0);
  1087.     
  1088. }
  1089.  
  1090.  
  1091. /**************************************************************************/
  1092. /*
  1093.  *     compressfds( fds)
  1094.  *        compress an fds data structure to make everyone happy
  1095.  */
  1096.  
  1097. compressfds( fds)
  1098. wdsEntry *fds;
  1099. {
  1100.     int n,m,compressed;
  1101.     
  1102.     compressed = 0;
  1103.     
  1104.     while ( !compressed) {
  1105.         compressed=1;
  1106.         for (n=0; n< MAX_FDS_ELEMS; n++) {                /* Slow Forwards */
  1107.             if (fds[n].ptr) {                                /* Do if N exists */
  1108.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) {    /* Fast Backwards */
  1109.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  1110.                         fds[n].length+=fds[m].length;
  1111.                         fds[n].ptr = fds[m].ptr;
  1112.                         fds[m].ptr=0L;
  1113.                         fds[m].length=0;
  1114.                         compressed=0;
  1115.                         }
  1116. #ifdef CHECKBOTHWAYZ
  1117.                     else 
  1118.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) {
  1119.                         fds[m].length+=fds[n].length;
  1120.                         fds[n].ptr=0L;
  1121.                         fds[n].length=0;
  1122.                         compressed=0;
  1123.                         }
  1124. #endif CHECKBOTHWAYZ
  1125.                     }
  1126.                 }
  1127.             }
  1128.         }
  1129.     m=0;n=0;
  1130.     
  1131.     /* Close the gaps */
  1132.     
  1133.     while (n+m < MAX_FDS_ELEMS) {
  1134.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS) {
  1135.             m++;            /* increase gap to valid entry */
  1136.             }
  1137.         if (n+m<MAX_FDS_ELEMS)
  1138.             fds[n]=fds[n+m];
  1139.         n++;
  1140.         }
  1141.     
  1142.     /* Get rid of the empty spaces */
  1143.     
  1144.     n--;        /* for the next loop */
  1145.     while (n < MAX_FDS_ELEMS) {
  1146.         fds[n].ptr=0; fds[n++].length=0;
  1147.         }
  1148. }
  1149.  
  1150. /**************************************************************************/
  1151. /* 
  1152.  *    reclaim( p) -
  1153.  *        reclaims buffer space to stream (from pointer p) into the FDS list 
  1154.  */
  1155.  
  1156. reclaim(p)
  1157. StreamRPtr p;
  1158. {
  1159.     int n=0, offset=0;
  1160.     
  1161.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  1162.     
  1163.     if (offset >= MAX_FDS_ELEMS) {
  1164.         putln("Couldn't reclaim because offset was too large ");
  1165.         return(0);
  1166.         }
  1167.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) {
  1168.         if (p->exFDS[ n].inuse) {
  1169.             p->fds[ offset++]=p->exFDS[ n].fds;
  1170.             p->exFDS[ n].inuse = 0;
  1171.             }
  1172.         }
  1173. }
  1174.  
  1175. /**************************************************************************/
  1176. /*
  1177.  *    giveback( p, wds) -
  1178.  *        gives WDS entries back to the stream by putting them in the 
  1179.  *        mutually exclusive buffer.
  1180.  *    p -> stream
  1181.  *    wds -> wds array
  1182.  */
  1183. giveback( p, wds)
  1184. StreamRPtr p;
  1185. wdsEntry *wds;
  1186. {
  1187.     int n=0, m=0;
  1188.     
  1189.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) {
  1190.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  1191.         if (m> MAX_FDS_ELEMS)
  1192.             return(-1);                /* No room in the RECLAIMation center */
  1193.         else {
  1194.             p->exFDS[ m].inuse =1;
  1195.             p->exFDS[ m].fds = wds[n];
  1196.             m++;
  1197.             }
  1198.         n++;
  1199.         }
  1200. }
  1201.  
  1202.  
  1203.  
  1204. /*****************************************************************************
  1205.  *
  1206.  * Here lie the awful UDP routines, I put them here for the drivers from Apple.
  1207.  *
  1208.  */
  1209.  
  1210.  int UDPlisten =0;                /* what port the old routines listen for */
  1211.  
  1212.  
  1213. /****************************************************************************/
  1214. /*                    New UDP routines....                                    */
  1215. /****************************************************************************/
  1216.  
  1217. /**************************************************************************/
  1218. /*
  1219.  * netuopen (port)             - open the udp port "Port"
  1220.  */
  1221.  
  1222. netuopen(port)
  1223. int port;
  1224. {
  1225.     int pnum;
  1226.  
  1227.     return(makeuport( port));
  1228. }
  1229.  
  1230. /**************************************************************************/
  1231. /*
  1232.  * netuclose( port)             - close the udp port 
  1233.  */
  1234.  
  1235. netuclose( port)
  1236. int port;
  1237. {
  1238.     UDPRPtr p;
  1239.     UDPiopb *pbp;
  1240.     int pnum;
  1241.     
  1242.     pnum= UDPfindport( port);
  1243.     
  1244.     if (pnum<0)
  1245.         return(-1);
  1246.     
  1247.     p=uport[pnum];
  1248.     
  1249.     pbp = getUPB( TCPd, UDPRelease, p->stream, 0);
  1250.     if (PBControl( pbp, noQcall) != noError) {
  1251.         putln("UDPClose failed"); return(-1);
  1252.         }
  1253.     free( p->buffer);
  1254.     free( uport[pnum]);
  1255.     uport[pnum]=0;                /* use me again */
  1256.     
  1257.     returnPB( pbp);
  1258. }
  1259.  
  1260. /**************************************************************************/
  1261. /*
  1262.  *    netuget( port, buffer,len, who,where)
  1263.  *                    - read up to len bytes from port port into buffer buffer, noting
  1264.  *                        who it was from and where....
  1265.  */
  1266.  
  1267. netuget( port, buffer, len, who, where)
  1268. int port, len;
  1269. int *who, *where;
  1270. char *buffer;
  1271. {
  1272.     int pnum, length;
  1273.     UDPRPtr p;
  1274.     UDPiopb *pbp;
  1275.     
  1276.     pnum= UDPfindport( port);
  1277.     
  1278.     if (pnum<0)
  1279.         return(-1);
  1280.     
  1281.     p=uport[pnum];
  1282.     
  1283.     pbp= getUPB( TCPd, UDPRead, p->stream, 0);
  1284.     pbp->csParam.receive.timeOut = 1;                            /* time out at one sec. */
  1285.     
  1286.     if (PBControl( pbp, noQcall) != noError) {
  1287.         putln("UDPRead failed"); return(-1);
  1288.         }
  1289.     
  1290.     length = pbp->csParam.receive.rcvBuffLen;                /* look how BIG it is */
  1291.     length = length > len ? len:length;
  1292.     
  1293.     memcpy( buffer, pbp->csParam.receive.rcvBuff,length);
  1294.     
  1295.     pbp->csCode = UDPBfrReturn;                                /* Let my buffer go.. */
  1296.     if (PBControl( pbp, noQcall) != noError) {
  1297.         putln("UDPReturn failed"); return(-1);
  1298.         }
  1299.         
  1300.     returnPB( pbp);
  1301.     
  1302.     return(length);
  1303. }
  1304.  
  1305. /**************************************************************************/
  1306. netuput( machine, port, myport, buffer, n)
  1307. long *machine;
  1308. char *buffer;
  1309. int port, myport;
  1310. int n;
  1311. {
  1312.     wdsEntry wds[2];
  1313.     UDPRPtr p;
  1314.     UDPiopb *pbp; int pnum;
  1315.     
  1316.     pnum= UDPfindport( myport);
  1317.     
  1318.     if (pnum<0)
  1319.         return(-1);
  1320.     
  1321.     p=uport[pnum];
  1322.     
  1323.     pbp= getUPB( TCPd, UDPWrite, p->stream, 0);
  1324.     pbp->csParam.send.remoteHost = *machine;
  1325.     pbp->csParam.send.remotePort = port;
  1326.     pbp->csParam.send.checkSum   = 1;                    /* Do do that checksum that you do so well */
  1327.     pbp->csParam.send.wdsPtr = wds;
  1328.     pbp->csParam.send.remoteHost = *machine;
  1329.     
  1330.     wds[0].ptr = buffer;
  1331.     wds[0].length=n;
  1332.     wds[1].ptr = (char *) 0L; wds[1].length=0;
  1333.     
  1334.     if (PBControl( pbp, noQcall) != noError) {
  1335.         putln("UDPReturn failed"); return(-1);
  1336.         }
  1337.         
  1338.     returnPB( pbp);
  1339.     return(0);
  1340. }
  1341.  
  1342.  
  1343. /****************************************************************************/
  1344. /*  neturead
  1345. *   get the data from the UDP buffer
  1346. *   Returns the number of bytes transferred into your buffer, -1 if none here
  1347. *   This needs work.
  1348. */
  1349. neturead(buffer)
  1350. char *buffer;
  1351. {
  1352.     int who, where;
  1353.     
  1354.     if (!UDPlisten)
  1355.         return(-1);
  1356.         
  1357.     return( netuget( UDPlisten, buffer, 512, &who, &where));
  1358. }
  1359.  
  1360. /***************************************************************************/
  1361. /*  netulisten
  1362. *   Specify which UDP port number to listen to.
  1363. *   Can only listen to one at a time.
  1364. */
  1365. netulisten(port)
  1366. int port;
  1367. {
  1368.     char temp[50];
  1369.     int pnum;
  1370.  
  1371.     
  1372.     sprintf( temp, "UDP listening on ....%d", port);
  1373.     putln(temp);
  1374.     
  1375.     UDPlisten = port;
  1376.     
  1377.     if ( (pnum=UDPfindport( port))<0)
  1378.         pnum= netuopen(port);
  1379.     
  1380.     return (pnum);
  1381. }
  1382.  
  1383. /***************************************************************************/
  1384. /*  netusend
  1385. *   send some data out in a UDP packet
  1386. *   uses the preinitialized data in the port packet ulist.udpout
  1387. *   
  1388. *   returns 0 on okay send, nonzero on error
  1389. */
  1390. netusend(machine,port,retport,buffer,n)
  1391. unsigned char *machine,*buffer;
  1392. unsigned int port,retport;
  1393. int n;
  1394. {
  1395.     /* find if port is open */
  1396.     if ( UDPfindport( retport)<0)
  1397.         netuopen(retport);
  1398.     
  1399.     /* Send data */
  1400.     netuput( machine, port, retport, buffer,n);
  1401. }
  1402.  
  1403. /**************************************************************************/
  1404. makeuport( port)
  1405. int port;
  1406. {
  1407.     int    pnum;
  1408.     UDPRPtr p;
  1409.     UDPiopb *pbp;
  1410.     int i;
  1411.     
  1412.     for ( pnum=0; uport[pnum]!= NULL && pnum<NPORTS; pnum++);
  1413.     
  1414.     if (pnum >= NPORTS)
  1415.         return(-2);
  1416.  
  1417.     p= uport[pnum] =malloc(sizeof(UDPRec));
  1418.  
  1419.     if ((p->buffer = malloc( UDPBUFSIZ)) == (char *)NULL)
  1420.         return(-1);
  1421.     
  1422.     
  1423.     pbp=getUPB( TCPd, UDPCreate, 0, pnum);            /* Make Create call */
  1424.     
  1425.     pbp->csParam.create.rcvBuff  = p->buffer;
  1426.     pbp->csParam.create.rcvBuffLen= UDPBUFSIZ;
  1427.     pbp->csParam.create.notifyProc     = UDPNotify;
  1428.     pbp->csParam.create.localPort = port;
  1429.     
  1430.     if ((i=PBControl( pbp, noQcall)) != noError) {
  1431.         char temp[50];
  1432.         sprintf(temp, "UDPCreate failed (%d)",i);
  1433.         putln(temp);
  1434.         return(-1);
  1435.         }
  1436.     else {
  1437.         char temp[50];
  1438.         sprintf(temp, "UDPCreate successfull on %d(%d) [%x]",port,pnum,pbp->udpStream);
  1439.         putln(temp);
  1440.         }
  1441.     
  1442.     p->stream = pbp->udpStream;
  1443.     p->port = port;
  1444.     
  1445.     putln("Made a new UPORT");
  1446.     returnPB(pbp);
  1447.     return(pnum);
  1448. }
  1449.  
  1450. /**************************************************************************/
  1451. int ufindbystream( streamPtr)
  1452. StreamPtr streamPtr;
  1453. {
  1454.     int pnum=0;
  1455.     
  1456.     while (pnum<NPORTS &&
  1457.             ( uport[pnum] ==(UDPRPtr)0L || streamPtr !=uport[pnum]->stream))
  1458.         pnum++;
  1459.     if (pnum >=NPORTS)
  1460.         return(-1);
  1461.     else
  1462.         return(pnum);
  1463. }
  1464.  
  1465. /**************************************************************************/
  1466. int UDPfindport( port)
  1467. int port;
  1468. {
  1469.     int pnum=0;
  1470.     
  1471.     while (pnum<NPORTS &&
  1472.             ( uport[pnum] ==(UDPRPtr)0L || port !=uport[pnum]->port))
  1473.         pnum++;
  1474.     if (pnum >=NPORTS)
  1475.         return(-1);
  1476.     else
  1477.         return(pnum);
  1478. }
  1479.  
  1480. /**************************************************************************/
  1481. pascal void UDPNotify( streamPtr, code, uptr, icmpMsg)
  1482. StreamPtr streamPtr;
  1483. unsigned short code;
  1484. struct ICMPReport *icmpMsg;
  1485. Ptr uptr;   /* user data */
  1486. {
  1487.     UDPRPtr p;
  1488.     int pnum;
  1489.     
  1490.     myWorld();
  1491.     pnum= ufindbystream(streamPtr);
  1492.     
  1493.     if (pnum<0 || (p=uport[pnum])==0L) {
  1494.         theirWorld();
  1495.         return;
  1496.         }
  1497.     
  1498.     switch( code) {
  1499.         case UDPDataArrival:
  1500.             netputuev(USERCLASS,UDPDATA,p->port);        /* post that it is here */
  1501.         default:
  1502.             break;
  1503.         }
  1504.     theirWorld();
  1505.     return;
  1506. }
  1507.  
  1508. netconfig( hardware)
  1509. char *hardware;
  1510. {
  1511.     putln("I'm a driver TCP, I don't need hardware.....");
  1512.     initipnum(0);
  1513. }
  1514.  
  1515. netarpme(s)
  1516. char *s;
  1517. {
  1518.     putln("Drivers don't need arps, either.");
  1519. }
  1520.  
  1521. netsetgate(s)
  1522. char *s;
  1523. {
  1524.     putln("Yeah, right....");
  1525. }
  1526.  
  1527. netgetrarp()
  1528. {
  1529.     putln("RARP handled above me....");
  1530. }
  1531.  
  1532. uint8 *getdlayer()
  1533. {
  1534.     putln("This shouldn't be called...");
  1535.     return(0L);
  1536. }
  1537.  
  1538. tcpsend()
  1539. {
  1540. }
  1541.  
  1542. demux()
  1543. {
  1544.     return(0);
  1545. }
  1546.  
  1547. /*************************************************************************/
  1548. /* neteventinit
  1549. *  load up the pointers for the event queue
  1550. *  makes a circular list to follow, required for error messages
  1551. */
  1552. neteventinit()
  1553.     {
  1554.     int i;
  1555.  
  1556.     for (i=0; i < NEVENTS; i++)
  1557.         nnq[i].next = i+1;
  1558.  
  1559.     nnq[NEVENTS-1].next = -1;
  1560.  
  1561.     nnefirst = 0;
  1562.     nnelast = 0;
  1563.     nnefree = 1;
  1564. }
  1565.  
  1566. getATaddress()
  1567. {
  1568. }
  1569.  
  1570. KIPfindgate()
  1571. {
  1572. }
  1573.  
  1574. KIPgetns()
  1575. {
  1576. }
  1577.  
  1578. KIPgetdynam()
  1579. {
  1580. }
  1581.  
  1582. KIPregister()
  1583. {
  1584. }
  1585.