home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / ENGINE / USER.C < prev    next >
C/C++ Source or Header  |  1992-03-08  |  17KB  |  726 lines

  1. /*
  2. *  USER.C
  3. *  Network library interface routines
  4. *  Generally called by the session layer
  5. *
  6. *    User interface routines 
  7. *
  8. *****************************************************************************
  9. *                                                                            *
  10. *      part of:                                                                *
  11. *      TCP/IP kernel for NCSA Telnet                                            *
  12. *      by Tim Krauskopf                                                        *
  13. *                                                                            *
  14. *      National Center for Supercomputing Applications                        *
  15. *      152 Computing Applications Building                                    *
  16. *      605 E. Springfield Ave.                                                *
  17. *      Champaign, IL  61820                                                    *
  18. *                                                                            *
  19. *     This program is in the public domain.                                 *
  20. *                                                                           *
  21. ****************************************************************************
  22. *  Revisions:
  23. ***************************************************************************
  24. *
  25. *    Revision history:
  26. *
  27. *    10/87  Initial source release, Tim Krauskopf
  28. *    2/88  typedef support for other compilers (TK)
  29. *    5/88    clean up for 2.3 release, JKM    
  30. *
  31. */
  32.  
  33. #define MASTERDEF 1                                /* add user variables */
  34.  
  35. /*#define DEBUG*/
  36. #include "debug.h"
  37.  
  38. /*
  39.  *    INCLUDES
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include <stdarg.h>
  44. #include "protocol.h"
  45. #include "data.h"
  46. #include "externs.h"
  47.  
  48. #define LOWWATER 600
  49.  
  50. /***************************************************************************/
  51. /*
  52. *    netread ( pnum, buffer, n )
  53. *
  54. *    Read data from the connection buffer (specified by *pnum*) into the
  55. *    user buffer for up to *n* bytes.
  56. *
  57. *    Returns number of bytes read, or<0 if error.  Does not block.
  58. *
  59. */
  60. int netread(int pnum,char *buffer,int n)
  61. {
  62.     int howmany,i,lowwater;
  63.     struct port *p;
  64.  
  65.     if(pnum<0)            /* check validity */
  66.         return(-2);
  67.  
  68.     if(NULL==(p=portlist[pnum]))
  69.         return(-2);
  70.  
  71.     if(p->state!=SEST) {              /* foreign or netclose */
  72.         if(p->state==SCWAIT) {            /* ready for me to close my side? */
  73.             if(!p->in.contain) {
  74.                 p->tcpout.t.flags=TFIN | TACK;
  75.                 tcpsend(p,0);
  76.                 p->state=SLAST;
  77.                 return(-1);
  78.               } /* end if */
  79.             /* else, still data to be read */
  80.           } /* end if */
  81.         else
  82.             return(-1);
  83.       } /* end if */
  84.  
  85.     howmany=dequeue(&p->in,buffer,n);            /* read from tcp buffer */
  86.     i=p->in.size;                                /* how much before? */
  87.     p->in.size+=howmany;                        /* increment leftover room  */
  88.  
  89.     lowwater=p->credit>>1;
  90.     if((i<lowwater) && ((p->in.size)>=(uint)lowwater)) /* we passed mark */
  91.         p->out.lasttime=0L;
  92.  
  93.     if(p->in.contain)                            /* if still data to be read */
  94.         netputuev(CONCLASS,CONDATA,pnum);        /* don't forget it */
  95.     return(howmany);
  96. }
  97.  
  98. #ifndef NET14
  99. /**********************************************************************
  100. *  Function :   netprintf
  101. *  Purpose  :   Write printf()-like formatted data into an output queue.
  102. *                   uses netwrite to actually get the data out.
  103. *  Parameters    :
  104. *           pnum - the port to write the data out to.
  105. *           fmt - character string specifying the format
  106. *  Returns  :   the number of bytes sent, or <0 if an error
  107. *  Calls    :   netwrite()
  108. *  Called by    :   all over...
  109. **********************************************************************/
  110. int netprintf(int pnum,char *fmt,...)
  111. {
  112.     char temp_str[256];         /* this may be a problem, if the string is too long */
  113.     va_list arg_ptr;
  114.     int str_len;
  115.  
  116.     va_start(arg_ptr,fmt);        /* get a pointer to the variable arguement list */
  117.     str_len=vsprintf(temp_str,fmt,arg_ptr); /* print the formatted string into a buffer */
  118.     va_end(arg_ptr);
  119.     if(str_len>0)      /* good string to transmit */
  120.         return(netwrite(pnum,temp_str,str_len));
  121.     else
  122.         return(-3);
  123. }   /* end netprintf() */
  124. #endif
  125.  
  126. /************************************************************************/
  127. /*
  128. *    netwrite ( pnum, buffer, n )
  129. *    Write data into the output queue (specified by *pnum*).  netsleep will
  130. * come around and distribute the data onto the wire later.
  131. *
  132. *    Returns number of bytes sent or<0 if an error.
  133. *
  134. */
  135. int
  136. #if defined(NET14)
  137. CDECL
  138. #endif
  139. netwrite(int pnum,char *buffer,int n)
  140. {
  141.     int nsent,before;
  142.     struct port *p;
  143.  
  144.     if(pnum<0)
  145.         return(-2);
  146.  
  147.     if((p=portlist[pnum])==NULL)
  148.         return(-2);
  149.  
  150.     if(p->state!=SEST)            /* must be established connection */
  151.         return(-1);
  152.  
  153.     before=p->out.contain;
  154.     nsent=enqueue(&p->out,buffer,n);
  155.  
  156.     if(!before) {                    /* if this is something new, */
  157.         p->out.lasttime=0L;        /* cause timeout to be true */
  158.         p->out.push=1;            /* set the push flag */
  159.       }    /* end if */
  160.     return(nsent);
  161. }
  162.  
  163. /**************************************************************************/
  164. /*
  165. *    netpush ( pnum )
  166. *
  167. *    Sets the push bit on the specified port data, and returns whether the
  168. * queue is empty or how many bytes in the queue. <0 if an error.
  169. *
  170. */
  171. int netpush(int pnum)
  172. {
  173.     struct port *p;
  174.  
  175.     if(pnum<0)
  176.         return(-2);
  177.  
  178.     if(NULL==(p=portlist[pnum]))
  179.         return(-2);
  180.  
  181.     p->out.push=1;
  182.     return((int)p->out.contain);
  183. }    
  184.  
  185. #ifndef NET14
  186. /**************************************************************************/
  187. /*
  188. *    netqlen ( pnum )
  189. *
  190. *    Returns the number of bytes waiting to be read from the incoming queue
  191. * or<0 if error.
  192. *
  193. */
  194. int netqlen(int pnum)
  195. {
  196.     if(portlist[pnum]==NULL)
  197.         return(-2);
  198.  
  199.     return((int)portlist[pnum]->in.contain);
  200. }
  201.  
  202. /**************************************************************************/
  203. /*
  204. *    netroom ( pnum )
  205. *
  206. *    Returns how many bytes left in the output buffer for port *pnum*. <0 if
  207. * error.
  208. *
  209. */
  210. int netroom(int pnum)
  211. {
  212.     if(portlist[pnum]==NULL || portlist[pnum]->state!=SEST)
  213.         return(-2);
  214.  
  215.     return((int)(WINDOWSIZE-portlist[pnum]->out.contain));
  216. }
  217.  
  218. /**************************************************************************/
  219. /*
  220. *    netsegsize ( newsize )
  221. *    Set the segment size.
  222. *
  223. *    Returns the old size.
  224. *
  225. */
  226. int netsegsize(int newsize)
  227. {
  228.     int i;
  229.  
  230.     i=nnsegsize;
  231.     nnsegsize=newsize;
  232.     return(i);
  233. }
  234. #endif
  235.  
  236. /*
  237. *    netarptime ( t )
  238. *
  239. *    Set the dlayer timeout ( in seconds )
  240. *
  241. */
  242. void netarptime(int t)                  /* dlayer timeout in secs */
  243. {
  244.     nndto=t;
  245. }
  246.  
  247. /*
  248. *    netsetip ( st )
  249. *
  250. *    Set a new ip number.  This goes through and changes all sorts of ip
  251. * numbers.
  252. *
  253. *    This routine assumes that there are currently NO open tcp connections.
  254. *
  255. */
  256. void netsetip(unsigned char *st)
  257. {
  258. /*
  259. *  change all dependent locations relating to the IP number
  260. *  don't worry about open connections, they must be closed by higher layer
  261. */
  262.     movebytes(nnipnum,st,4);                        /* main ip number */
  263.     movebytes(arp.spa,nnipnum,4);                    /* arp */
  264.     movebytes(blankip.i.ipsource,nnipnum,4);        /* ip source */
  265.     movebytes(ulist.tcps.source,nnipnum,4);            /* udp source */
  266.     movebytes(ulist.udpout.i.ipsource,nnipnum,4);    /* more udp source */
  267. }
  268.  
  269. /*
  270. *    netgetip ( st )
  271. *
  272. *    Sets *st* to the current up number 
  273. *
  274. */
  275. void netgetip(unsigned char *st)
  276. {
  277.     movebytes(st,nnipnum,4);
  278. }
  279.  
  280. /*
  281. *    netsetbroad ( st )
  282. *
  283. *    Set the network broadcast IP address.
  284. *
  285. */
  286. void netsetbroad(unsigned char *st)
  287. {
  288.     movebytes(broadip,st,4);
  289. }
  290.  
  291. /*
  292. *    netsetmask ( st )
  293. *
  294. *    Set the network mask.
  295. *
  296. */
  297. void netsetmask(unsigned char *st)
  298. {
  299.     movebytes(nnmask,st,4);
  300. }
  301.  
  302. /*
  303. *    netgetmask ( st )
  304. *
  305. *    Get the network mask.
  306. *
  307. */
  308. void netgetmask(unsigned char *st)
  309. {
  310.     movebytes(st,nnmask,4);
  311. }
  312.  
  313. #if !defined NET14 || defined NETSPACE
  314. /*
  315. *    netfromport ( port )
  316. *
  317. *    This sets the port that the next open will use to be *port*
  318. *
  319. */
  320. void netfromport(int16 port)
  321. {
  322.     nnfromport=port;
  323. }
  324.  
  325. /**************************************************************************/
  326. /*
  327. *    netest ( pn ) 
  328. *
  329. *    Checks to see if a particular session has been established yet.
  330. *
  331. *    Returns 0 if the connection is in "established" state.
  332. *
  333. */
  334. int netest(int pn)
  335. {
  336.     struct port *p;
  337.  
  338.     if(pn<0 || pn>NPORTS)
  339.         return(-2);
  340.  
  341.     if(NULL==(p=portlist[pn]))
  342.         return(-2);
  343.  
  344.     if(p->state==SEST)
  345.         return(0);
  346.     else
  347.         if(p->state==SCWAIT) {
  348.             if(!p->in.contain) {
  349.                 p->tcpout.t.flags=TFIN | TACK;
  350.                 tcpsend(p,0);
  351.                 p->state=SLAST;
  352.                 return(-1);
  353.               }    /* end if */
  354.             else 
  355.                 return(0);                /* still more data to be read */
  356.           }    /* end if */
  357.     return(-1);
  358. }
  359.  
  360. /**************************************************************************/
  361. /*
  362. *    netlisten ( serv )
  363. *
  364. *   Listen to a TCP port number and make the connection automatically when
  365. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  366. *   with a CONOPEN event.  Save the port number returned to refer to this
  367. *   connection.
  368. *
  369. *    example usage : portnum=netlisten ( service )
  370. *
  371. *    Returns<0 if error 
  372. *
  373. */
  374. int netlisten(uint serv)
  375. {
  376.     int    pnum;
  377.     struct port *prt;
  378.     uint16 nn;
  379.  
  380.     if((pnum=makeport())<0)
  381.         return(-2);
  382.  
  383.     if(NULL==(prt=portlist[pnum]))
  384.         return(-2);
  385.  
  386.     prt->in.port=serv;
  387.     prt->out.port=0;                        /* accept any outside port #*/
  388.     prt->in.lasttime=n_clicks();            /* set time we started */
  389.     prt->state=SLISTEN;
  390.     prt->credit=512;                        /* default value until changed */
  391.     prt->tcpout.i.protocol=PROTTCP;
  392.     prt->tcpout.t.source=intswap(serv);        /* set service here too */
  393.  
  394. /*
  395. *  install maximum segment size which will be sent out in the first
  396. *  ACK-SYN packet
  397. */
  398.     prt->tcpout.x.options[0]=2;
  399.     prt->tcpout.x.options[1]=4;
  400. /* install maximum segment size */
  401.     nn=intswap(nnsegsize);
  402.     movebytes((char *)&prt->tcpout.x.options[2],(char *)&nn,2);
  403.     return(pnum);
  404. }
  405.  
  406. /***********************************************************************/
  407. /*
  408. *    netgetftp ( a, pnum )
  409. *
  410. *    This routine provides the information needed to open an ftp connection
  411. * back to the originatior of the command connection.  The other side's IP
  412. * number and the port numbers are returned in an INTEGER array ( convenient
  413. * for use in PORT commands ).
  414. *
  415. */
  416. void netgetftp(int a[],int pnum)
  417. {
  418.     struct port *p;
  419.     uint i;
  420.  
  421.     p=portlist[pnum];
  422.  
  423.     a[0]=p->tcpout.i.ipdest[0];
  424.     a[1]=p->tcpout.i.ipdest[1];
  425.     a[2]=p->tcpout.i.ipdest[2];
  426.     a[3]=p->tcpout.i.ipdest[3];
  427.     i=intswap(p->tcpout.t.source);
  428.     a[4]=i>>8;
  429.     a[5]=i & 255;
  430.     i=intswap(p->tcpout.t.dest);
  431.     a[6]=i>>8;
  432.     a[7]=i & 255;
  433. }
  434. #endif
  435.  
  436. /**************************************************************************/
  437. /*
  438. *    netxopen ( machine, service, rto, mtu, mseg, mwin )
  439. *
  440. *    Open a network socket for the user to *machine* using port *service*.
  441. * The rest of the parameters are self-explanatory.
  442. *
  443. */
  444. int netxopen(uint8 *machine,uint service,uint rto,uint mtu,uint mseg,uint mwin)
  445. {
  446.     struct port *p;
  447.     int pnum,ret,i;
  448.     uint8 *pc,*hiset;
  449.  
  450. /*
  451. *  check the IP number and don't allow broadcast addresses
  452. */
  453. #ifdef OLD_WAY
  454.     if(machine[3]==255 || !machine[3]) {
  455.         nnerror(506);
  456.         return(-4);
  457.       }
  458. #else
  459.     if(machine[3]==255) {
  460.         nnerror(506);
  461.         return(-4);
  462.       }
  463. #endif
  464.  
  465.     netsleep(0);                    /* make sure no waiting packets */
  466.  
  467.     if((pnum=makeport())<0)            /* set up port structure and packets */
  468.         return(-3);
  469.  
  470.     p=portlist[pnum];                /* create a new port */
  471. /*
  472. *  make a copy of the ip number that we are trying for
  473. */
  474.     movebytes(p->tcpout.i.ipdest,machine,4);
  475.     movebytes(p->tcps.dest,machine,4);        /* pseudo header needs it */
  476.  
  477. /*
  478. *  get the hardware address for that host, or use the one for the gateway
  479. *  all handled by 'netdlayer' by ARPs.
  480. */
  481.  
  482.     pc=netdlayer(machine);                    /* we have ether? */
  483.     if(pc==NULL) {                            /* cannot connect to local machine */
  484.         nnerror(504);
  485.         return(-2);
  486.       }
  487.  
  488.     movebytes(p->tcpout.d.dest,pc,DADDLEN);        /* load it up */
  489.  
  490. /*
  491. *   Add in machine specific settings for performance tuning
  492. */
  493.     if(rto>=MINRTO)
  494.         p->rto=rto;            /* starting retrans timeout */
  495.     if(mtu<=TMAXSIZE)        /* largest packet space we have */
  496.         p->sendsize=mtu;    /* maximum transmit size for that computer */
  497.     if(mwin<=WINDOWSIZE)        /* buffer size is the limit */
  498.         p->credit=mwin;        /* most data that we can receive at once */
  499.  
  500. #ifdef OLD_WAY
  501.     if(nnemac) {
  502. /*
  503. *   quick check to see if someone else is using your IP number
  504. *   Some boards receive their own broadcasts and cannot use this check.
  505. *   The Mac will only use this check if it is using EtherTalk.
  506. */
  507.         i=cachelook(nnipnum,0,0);                /* don't bother to ARP */
  508.         if(i >= 0)    {                /* if it is not -1, we are in trouble */
  509.             hiset=(uint8 *)arpc[i].hrd;
  510.             pc=neterrstring(-1);
  511.             sprintf(pc,"Conflict with Ethernet hardware address: %2x:%2x:%2x:%2x:%2x:%2x",
  512.             hiset[0],hiset[1],hiset[2],hiset[3],hiset[4],hiset[5]);
  513.             nnerror(-1);
  514.             nnerror(102);
  515.             netclose(pnum);
  516.             return(-3);
  517.           }
  518.       }
  519. #endif
  520.  
  521. /*
  522. *  make the connection, if you can, we will get an event notification later
  523. *  if it connects.  Timeouts must be done at a higher layer.
  524. */
  525.     ret=doconnect(pnum,service,mseg);
  526.     return(ret);
  527. }
  528.  
  529. /**********************************************************************/
  530. /*
  531. *    doconnect ( pnum, service, mseg )
  532. *
  533. *    This routine sends the actual packet out to try and establish a
  534. * connection.
  535. *
  536. */
  537. doconnect(int pnum,int service,int mseg)
  538. {
  539.     uint16 seg;
  540.     struct port *p;
  541.  
  542.     p=portlist[pnum];
  543.  
  544.     p->tcpout.i.protocol=PROTTCP;            /* this will be TCP socket */
  545.     p->tcpout.t.dest=intswap(service);        /* for example, telnet=23 */
  546.     p->out.port=service;                    /* service is same as port num*/
  547.     p->tcpout.t.flags=TSYN;                    /* want to start up sequence */
  548.     p->tcpout.t.ack=0;                        /* beginning has no ACK */
  549.     p->state=SSYNS;                            /* syn sent */
  550. /*
  551. *  install maximum segment size which will be sent out in the first
  552. *  ACK-SYN packet
  553. */
  554.     p->tcpout.x.options[0]=2;
  555.     p->tcpout.x.options[1]=4;
  556.  
  557. /* install maximum segment size */
  558.     seg=intswap(mseg);
  559.     movebytes((char *)&p->tcpout.x.options[2],(char *)&seg,2);
  560.     p->tcpout.t.hlen=96;                    /* include one more word in hdr */
  561.     tcpsend(p,4);                            /* send opening volley */
  562.     p->tcpout.t.hlen=80;                    /* normal hdr len */
  563.  
  564. /*    savenxt=p->out.nxt; */
  565.     p->out.nxt += 1;                        /* ack should be for next byte */
  566.     return(pnum);                            /* do not wait for connect */
  567. }
  568.  
  569. /*************************************************************************/
  570. /*
  571. *    netopen2 ( pnum )
  572. *
  573. *    Send out repeat SYN on a connection which is not open yet.  This checks
  574. * to make sure if it is actually needed.  Timing is handled at a higher
  575. * layer.
  576. *
  577. *    Returns 1 if the state is still at SYNS other wise 0 if connection is
  578. * proceeding.
  579. */
  580. int netopen2(int pnum)
  581. {
  582.     struct port *p;
  583.  
  584.     if(pnum<0 || pnum>NPORTS)
  585.         return(-1);
  586.  
  587.     if(NULL==(p=portlist[pnum]))
  588.         return(-2);
  589.  
  590.     if(p->state != SSYNS)
  591.             return(0);                /* done our job */
  592. /*
  593. *  The connection has not proceeded to further states, try retransmission
  594. */
  595.     p->out.nxt--;
  596.     p->tcpout.t.hlen=96;        /* include one more word in hdr */
  597.     tcpsend(p,4);                /* try sending again */
  598.     p->tcpout.t.hlen=80;        /* normal hdr len */
  599.     p->out.nxt++;
  600.     return(1);
  601. }
  602.  
  603. /**************************************************************************/
  604. /*
  605. *    netclose ( pnum )
  606. *
  607. *    Start the closing process on port pnum.
  608. *
  609. */
  610. int
  611. #if defined(NET14)
  612. CDECL
  613. #endif
  614. netclose(int pnum)
  615. {
  616.     struct port *p;
  617.  
  618.     if(pnum<0 || pnum>NPORTS)            /* is a valid port? */
  619.         return(-1);
  620.  
  621.     if((p=portlist[pnum])!=NULL) {        /* something there */
  622.  
  623. /*
  624. *printf("p->state=%d\n",p->state);
  625. */
  626.         switch (p->state) {
  627.             case SLISTEN:                /* we don't care anymore */
  628.             case SSYNS:
  629.                 p->state=SCLOSED;
  630.                 break;
  631.  
  632.             case SEST:                    /* must initiate close */
  633.                 /* send FIN */
  634.                 p->tcpout.t.flags=TACK | TFIN;
  635.                 tcpsend(p,0);
  636.                 p->state=SFW1;            /* wait for ACK of FIN */
  637.                 break;                    /* do nothing for now ?*/
  638.  
  639.             case SCWAIT:                /* other side already closed */
  640.                 p->tcpout.t.flags=TFIN | TACK;
  641.                 tcpsend(p,0);
  642.                 p->state=SLAST;
  643.                 break;
  644.  
  645.             case STWAIT:                /* time out yet? */
  646.                 if(portlist[pnum]->out.lasttime + WAITTIME<n_clicks())
  647.                     p->state=SCLOSED;
  648.                 break;
  649.  
  650.             case SLAST:                    /* five minute time out */
  651.                 if(portlist[pnum]->out.lasttime + LASTTIME<n_clicks())
  652.                     p->state=SCLOSED;
  653.                 break;
  654.  
  655.             default:
  656.                 break;
  657.           }
  658.       }
  659.     else
  660.         return(1);
  661.     return(0);
  662. }
  663.  
  664. /**************************************************************************/
  665. /*
  666. *    netinit ()
  667. *
  668. *    Handles all the initialization to bring up the network connection.
  669. *    Assumes that the configuration file has already been read up.
  670. * (called from Snetinit () )
  671. *
  672. *    Returns 0 on successful initialization.
  673. *
  674. */
  675. int netinit(void )
  676. {
  677.     int ret;
  678.  
  679.     BUG("in netinit");
  680. /*
  681. *   Initializes all buffers and hardware for data link layer.
  682. *   Machine/board dependent.
  683. */
  684.     ret=dlayerinit();
  685.     BUG("after dlayerinit");
  686.     if(ret) {
  687.         switch (ret) {
  688.             case -10:
  689.                 printf("Need a function for opening board!!\n");
  690.                 break;
  691.  
  692.             default:
  693.                 printf("Board initialization failed!.  Error code=%d\n",ret);
  694.                 break;
  695.           }    /* end switch */
  696.         nnerror(101);
  697.         return(ret);
  698.       }    /* end if */
  699. /*
  700. *  initialize the template packets needed for transmission
  701. */
  702.     protinit();             /* set up empty packets */
  703.     return(0);
  704. }
  705.  
  706. /*************************************************************************/
  707. /*
  708. *    netshut ()
  709. *
  710. *    Shut down the hardware.  This tries to close any active connections and
  711. * then turn off the hardware ( via dlayershut )
  712. *
  713. */
  714. void netshut()
  715. {
  716.     int i;
  717.  
  718.     for(i=0; i<NPORTS ; i++) 
  719.         if(portlist[i]!=NULL)
  720.             netclose(i);
  721.     netsleep(1);
  722.     dlayershut();
  723. }
  724.  
  725.