Category : C Source Code
Archive   : TEL2307S.ZIP
Filename : USER.C

 
Output of file : USER.C contained in archive : TEL2307S.ZIP
/*
* USER.C
* Network library interface routines
* Generally called by the session layer
*
* User interface routines
*
*****************************************************************************
* *
* part of: *
* TCP/IP kernel for NCSA Telnet *
* by Tim Krauskopf *
* *
* National Center for Supercomputing Applications *
* 152 Computing Applications Building *
* 605 E. Springfield Ave. *
* Champaign, IL 61820 *
* *
* This program is in the public domain. *
* *
****************************************************************************
* Revisions:
***************************************************************************
*
* Revision history:
*
* 10/87 Initial source release, Tim Krauskopf
* 2/88 typedef support for other compilers (TK)
* 5/88 clean up for 2.3 release, JKM
*
*/

#define MASTERDEF 1 /* add user variables */

/*#define DEBUG*/
#include "debug.h"

/*
* INCLUDES
*/

#include
#include
#include "protocol.h"
#include "data.h"
#include "externs.h"
#include "defines.h"

#define LOWWATER 600

/***************************************************************************/
/*
* netread ( pnum, buffer, n )
*
* Read data from the connection buffer (specified by *pnum*) into the
* user buffer for up to *n* bytes.
*
* Returns number of bytes read, or<0 if error. Does not block.
*
*/
int netread(int pnum,char *buffer,int n)
{
int howmany,i,lowwater;
struct port *p;

if(pnum<0) /* check validity */
return(-2);

if(NULL==(p=portlist[pnum]))
return(-2);

if(p->state!=SEST) { /* foreign or netclose */
if(p->state==SCWAIT) { /* ready for me to close my side? */
if(!p->in.contain) {
p->tcpout.t.flags=TFIN | TACK;
tcpsend(p,0);
p->state=SLAST;
return(-1);
} /* end if */
/* else, still data to be read */
} /* end if */
else
return(-1);
} /* end if */

howmany=dequeue(&p->in,buffer,n); /* read from tcp buffer */
i=p->in.size; /* how much before? */
p->in.size+=howmany; /* increment leftover room */

lowwater=p->credit>>1;
if((iin.size)>=(uint)lowwater)) /* we passed mark */
p->out.lasttime=0L;

if(p->in.contain) /* if still data to be read */
netputuev(CONCLASS,CONDATA,pnum); /* don't forget it */
return(howmany);
}

#ifndef NET14
/**********************************************************************
* Function : netprintf
* Purpose : Write printf()-like formatted data into an output queue.
* uses netwrite to actually get the data out.
* Parameters :
* pnum - the port to write the data out to.
* fmt - character string specifying the format
* Returns : the number of bytes sent, or <0 if an error
* Calls : netwrite()
* Called by : all over...
**********************************************************************/
int netprintf(int pnum,char *fmt,...)
{
char temp_str[256]; /* this may be a problem, if the string is too long */
va_list arg_ptr;
int str_len;

va_start(arg_ptr,fmt); /* get a pointer to the variable arguement list */
str_len=vsprintf(temp_str,fmt,arg_ptr); /* print the formatted string into a buffer */
va_end(arg_ptr);
if(str_len>0) /* good string to transmit */
return(netwrite(pnum,temp_str,str_len));
else
return(-3);
} /* end netprintf() */
#endif

/************************************************************************/
/*
* netwrite ( pnum, buffer, n )
* Write data into the output queue (specified by *pnum*). netsleep will
* come around and distribute the data onto the wire later.
*
* Returns number of bytes sent or<0 if an error.
*
*/
int

#if defined(NET14)
CDECL
#endif
netwrite(int pnum,char *buffer,int n)
{
int nsent,before;
struct port *p;

if(pnum<0)
return(-2);

if((p=portlist[pnum])==NULL)
return(-2);

if(p->state!=SEST) /* must be established connection */
return(-1);

before=p->out.contain;
nsent=enqueue(&p->out,buffer,n);

if(!before) { /* if this is something new, */
p->out.lasttime=0L; /* cause timeout to be true */
p->out.push=1; /* set the push flag */
} /* end if */
return(nsent);
}

/**************************************************************************/
/*
* netpush ( pnum )
*
* Sets the push bit on the specified port data, and returns whether the
* queue is empty or how many bytes in the queue. <0 if an error.
*
*/
int netpush(int pnum)
{
struct port *p;

if(pnum<0)
return(-2);

if(NULL==(p=portlist[pnum]))
return(-2);

p->out.push=1;
return((int)p->out.contain);
}

#ifndef NET14
/**************************************************************************/
/*
* netqlen ( pnum )
*
* Returns the number of bytes waiting to be read from the incoming queue
* or<0 if error.
*
*/
int netqlen(int pnum)
{
if(portlist[pnum]==NULL)
return(-2);

return((int)portlist[pnum]->in.contain);
}

/**************************************************************************/
/*
* netroom ( pnum )
*
* Returns how many bytes left in the output buffer for port *pnum*. <0 if
* error.
*
*/
int netroom(int pnum)
{
if(portlist[pnum]==NULL || portlist[pnum]->state!=SEST)
return(-2);

return((int)(WINDOWSIZE-portlist[pnum]->out.contain));
}

/**************************************************************************/
/*
* netsegsize ( newsize )
* Set the segment size.
*
* Returns the old size.
*
*/
int netsegsize(int newsize)
{
int i;

i=nnsegsize;
nnsegsize=newsize;
return(i);
}
#endif

/*
* netarptime ( t )
*
* Set the dlayer timeout ( in seconds )
*
*/
void netarptime(int t) /* dlayer timeout in secs */
{
nndto=t;
}

/*
* netsetip ( st )
*
* Set a new ip number. This goes through and changes all sorts of ip
* numbers.
*
* This routine assumes that there are currently NO open tcp connections.
*
*/
void netsetip(unsigned char *st)
{
/*
* change all dependent locations relating to the IP number
* don't worry about open connections, they must be closed by higher layer
*/
movebytes(nnipnum,st,4); /* main ip number */
movebytes(arp.spa,nnipnum,4); /* arp */
movebytes(blankip.i.ipsource,nnipnum,4); /* ip source */
movebytes(udplist[DNRINDEX]->tcps.source,nnipnum,4); /* udp source - eej */
movebytes(udplist[DNRINDEX]->udpout.i.ipsource,nnipnum,4); /* more udp source - eej */
}

/*
* netgetip ( st )
*
* Sets *st* to the current up number
*
*/
void netgetip(unsigned char *st)
{
movebytes(st,nnipnum,4);
}

/*
* netsetbroad ( st )
*
* Set the network broadcast IP address.
*
*/
void netsetbroad(unsigned char *st)
{
movebytes(broadip,st,4);
}

/*
* netsetmask ( st )
*
* Set the network mask.
*
*/
void netsetmask(unsigned char *st)
{
movebytes(nnmask,st,4);
}

/*
* netgetmask ( st )
*
* Get the network mask.
*
*/
void netgetmask(unsigned char *st)
{
movebytes(st,nnmask,4);
}


#if !defined NET14 || defined NETSPACE || defined WIN /* rmg hahaha! */
/*
* netfromport ( port )
*
* This sets the port that the next open will use to be *port*
*
*/
void netfromport(int16 port)
{
nnfromport=port;
}

/**************************************************************************/
/*
* netest ( pn )
*
* Checks to see if a particular session has been established yet.
*
* Returns 0 if the connection is in "established" state.
*
*/
int netest(int pn)
{
struct port *p;

if(pn<0 || pn>NPORTS)
return(-2);

if(NULL==(p=portlist[pn]))
return(-2);

if(p->state==SEST)
return(0);
else
if(p->state==SCWAIT) {
if(!p->in.contain) {
p->tcpout.t.flags=TFIN | TACK;
tcpsend(p,0);
p->state=SLAST;
return(-1);
} /* end if */
else
return(0); /* still more data to be read */
} /* end if */
return(-1);
}

/**************************************************************************/
/*
* netlisten ( serv )
*
* Listen to a TCP port number and make the connection automatically when
* the SYN packet comes in. The TCP layer will notify the higher layers
* with a CONOPEN event. Save the port number returned to refer to this
* connection.
*
* example usage : portnum=netlisten ( service )
*
* Returns<0 if error
*
*/
int netlisten(uint serv)
{
int pnum;
struct port *prt;
uint16 nn;

if((pnum=makeport())<0)
return(-2);

if(NULL==(prt=portlist[pnum]))
return(-2);

prt->in.port=serv;
prt->out.port=0; /* accept any outside port #*/
prt->in.lasttime=n_clicks(); /* set time we started */
prt->state=SLISTEN;
prt->credit=512; /* default value until changed */
prt->tcpout.i.protocol=PROTTCP;
prt->tcpout.t.source=intswap(serv); /* set service here too */

/*
* install maximum segment size which will be sent out in the first
* ACK-SYN packet
*/
prt->tcpout.x.options[0]=2;
prt->tcpout.x.options[1]=4;
/* install maximum segment size */
nn=intswap(nnsegsize);
movebytes((char *)&prt->tcpout.x.options[2],(char *)&nn,2);
return(pnum);
}

/***********************************************************************/
/*
* netgetftp ( a, pnum )
*
* This routine provides the information needed to open an ftp connection
* back to the originatior of the command connection. The other side's IP
* number and the port numbers are returned in an INTEGER array ( convenient
* for use in PORT commands ).
*
*/
void netgetftp(int a[],int pnum)
{
struct port *p;
uint i;

p=portlist[pnum];

a[0]=p->tcpout.i.ipdest[0];
a[1]=p->tcpout.i.ipdest[1];
a[2]=p->tcpout.i.ipdest[2];
a[3]=p->tcpout.i.ipdest[3];
i=intswap(p->tcpout.t.source);
a[4]=i>>8;
a[5]=i & 255;
i=intswap(p->tcpout.t.dest);
a[6]=i>>8;
a[7]=i & 255;
}
#endif

/**************************************************************************/
/*
* netxopen ( machine, service, rto, mtu, mseg, mwin )
*
* Open a network socket for the user to *machine* using port *service*.
* The rest of the parameters are self-explanatory.
*
*/
int netxopen(uint8 *machine,uint service,uint rto,uint mtu,uint mseg,uint mwin)
{
struct port *p;
int pnum,ret,i;
uint8 *pc,*hiset;

/*
* check the IP number and don't allow broadcast addresses
*/
#ifdef OLD_WAY
if(machine[3]==255 || !machine[3]) {
nnerror(506);
return(-4);
}
#else
if(machine[3]==255) {
nnerror(506);
return(-4);
}
#endif

netsleep(0); /* make sure no waiting packets */

if((pnum=makeport())<0) /* set up port structure and packets */
return(-3);

p=portlist[pnum]; /* create a new port */
/*
* make a copy of the ip number that we are trying for
*/
movebytes(p->tcpout.i.ipdest,machine,4);
movebytes(p->tcps.dest,machine,4); /* pseudo header needs it */

/*
* get the hardware address for that host, or use the one for the gateway
* all handled by 'netdlayer' by ARPs.
*/

pc=netdlayer(machine); /* we have ether? */
if(pc==NULL) { /* cannot connect to local machine */
nnerror(504);
return(-2);
}

movebytes(p->tcpout.d.dest,pc,DADDLEN); /* load it up */

/*
* Add in machine specific settings for performance tuning
*/
if(rto>=MINRTO)
p->rto=rto; /* starting retrans timeout */
if(mtu<=TMAXSIZE) /* largest packet space we have */
p->sendsize=mtu; /* maximum transmit size for that computer */
if(mwin<=WINDOWSIZE) /* buffer size is the limit */
p->credit=mwin; /* most data that we can receive at once */

#ifdef OLD_WAY
if(nnemac) {
/*
* quick check to see if someone else is using your IP number
* Some boards receive their own broadcasts and cannot use this check.
* The Mac will only use this check if it is using EtherTalk.
*/
i=cachelook(nnipnum,0,0); /* don't bother to ARP */
if(i >= 0) { /* if it is not -1, we are in trouble */
hiset=(uint8 *)arpc[i].hrd;
pc=neterrstring(-1);
sprintf(pc,"Conflict with Ethernet hardware address: %2x:%2x:%2x:%2x:%2x:%2x",
hiset[0],hiset[1],hiset[2],hiset[3],hiset[4],hiset[5]);
nnerror(-1);
nnerror(102);
netclose(pnum);
return(-3);
}
}
#endif

/*
* make the connection, if you can, we will get an event notification later
* if it connects. Timeouts must be done at a higher layer.
*/
ret=doconnect(pnum,service,mseg);
return(ret);
}

/**********************************************************************/
/*
* doconnect ( pnum, service, mseg )
*
* This routine sends the actual packet out to try and establish a
* connection.
*
*/
doconnect(int pnum,int service,int mseg)
{
uint16 seg;
struct port *p;

p=portlist[pnum];

p->tcpout.i.protocol=PROTTCP; /* this will be TCP socket */
p->tcpout.t.dest=intswap(service); /* for example, telnet=23 */
p->out.port=service; /* service is same as port num*/
p->tcpout.t.flags=TSYN; /* want to start up sequence */
p->tcpout.t.ack=0; /* beginning has no ACK */
p->state=SSYNS; /* syn sent */
/*
* install maximum segment size which will be sent out in the first
* ACK-SYN packet
*/
p->tcpout.x.options[0]=2;
p->tcpout.x.options[1]=4;

/* install maximum segment size */
seg=intswap(mseg);
movebytes((char *)&p->tcpout.x.options[2],(char *)&seg,2);
p->tcpout.t.hlen=96; /* include one more word in hdr */
tcpsend(p,4); /* send opening volley */
p->tcpout.t.hlen=80; /* normal hdr len */

/* savenxt=p->out.nxt; */
p->out.nxt+=1; /* ack should be for next byte */
return(pnum); /* do not wait for connect */
}

/*************************************************************************/
/*
* netopen2 ( pnum )
*
* Send out repeat SYN on a connection which is not open yet. This checks
* to make sure if it is actually needed. Timing is handled at a higher
* layer.
*
* Returns 1 if the state is still at SYNS other wise 0 if connection is
* proceeding.
*
*/
int netopen2(int pnum)
{
struct port *p;

if(pnum<0 || pnum>NPORTS)
return(-1);

if(NULL==(p=portlist[pnum]))
return(-2);

if(p->state != SSYNS)
return(0); /* done our job */
/*
* The connection has not proceeded to further states, try retransmission
*/
p->out.nxt--;
p->tcpout.t.hlen=96; /* include one more word in hdr */
tcpsend(p,4); /* try sending again */
p->tcpout.t.hlen=80; /* normal hdr len */
p->out.nxt++;
return(1);
}

/**************************************************************************/
/*
* netclose ( pnum )
*
* Start the closing process on port pnum.
*
*/
int
#if defined(NET14)
CDECL
#endif
netclose(int pnum)
{
struct port *p;

if(pnum<0 || pnum>NPORTS) /* is a valid port? */
return(-1);

if((p=portlist[pnum])!=NULL) { /* something there */

/*
*printf("p->state=%d\n",p->state);
*/
switch (p->state) {
case SLISTEN: /* we don't care anymore */
case SSYNS:
p->state=SCLOSED;
break;

case SEST: /* must initiate close */
/* send FIN */
p->tcpout.t.flags=TACK | TFIN;
tcpsend(p,0);
p->state=SFW1; /* wait for ACK of FIN */
break; /* do nothing for now ?*/

case SCWAIT: /* other side already closed */
p->tcpout.t.flags=TFIN | TACK;
tcpsend(p,0);
p->state=SLAST;
break;

case STWAIT: /* time out yet? */
if(portlist[pnum]->out.lasttime + WAITTIME p->state=SCLOSED;
break;

case SLAST: /* five minute time out */
if(portlist[pnum]->out.lasttime + LASTTIME p->state=SCLOSED;
break;

default:
break;
}
}
else
return(1);
return(0);
}

/**************************************************************************/
/*
* netinit ()
*
* Handles all the initialization to bring up the network connection.
* Assumes that the configuration file has already been read up.
* (called from Snetinit () )
*
* Returns 0 on successful initialization.
*
*/
int netinit(void )
{
int ret;

BUG("in netinit");
/*
* Initializes all buffers and hardware for data link layer.
* Machine/board dependent.
*/
ret=dlayerinit();
BUG("after dlayerinit");
if(ret) {
switch (ret) {
case -10:
printf("Need a function for opening board!!\n");
break;

default:
printf("Board initialization failed!. Error code=%d\n",ret);
break;
} /* end switch */
nnerror(101);
return(ret);
} /* end if */
/*
* initialize the template packets needed for transmission
*/
protinit(); /* set up empty packets */
return(0);
}

/*************************************************************************/
/*
* netshut ()
*
* Shut down the hardware. This tries to close any active connections and

* then turn off the hardware ( via dlayershut )
*
*/
void netshut()
{
int i;

for(i=0; i if(portlist[i]!=NULL)
netclose(i);
netsleep(1);
dlayershut();
}



  3 Responses to “Category : C Source Code
Archive   : TEL2307S.ZIP
Filename : USER.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/