home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GRIPS 2: Government Rast…rocessing Software & Data
/
GRIPS_2.cdr
/
dos
/
ncsa_tel
/
tel_2_2_
/
source
/
protinit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-15
|
9KB
|
320 lines
/*
* Protinit.c
* initialize the template packets
****************************************************************************
* *
* part of: *
* TCP/UDP/ICMP/IP Network kernel for NCSA Telnet *
* by Tim Krauskopf *
* *
* National Center for Supercomputing Applications *
* 152 Computing Applications Building *
* 605 E. Springfield Ave. *
* Champaign, IL 61820 *
* *
****************************************************************************
* 'protinit' initializes packets to make them ready for transmission.
* For many purposes, pre-initialized packets are created for use by the
* protocol routines, especially to save time creating packets for
* transmit.
*
* Assumes that 'myaddr' is already set to my Ethernet hardware address
* and any other similar protocol addresses are already initialized
* (known) for the local station.
*
* As this is a convenient place for it, this file contains many of the
* data declarations for packets which are mostly static (pre-allocated).
*/
#include "stdio.h"
#include "protocol.h"
#include "data.h"
/************************************************************************/
/* main code for protinit()
* for each new type of protocol, put an initialization call here.
* There may be some requirement of order of initialization.
*/
protinit()
{
etherinit();
arpinit();
ipinit();
tcpinit();
udpinit();
return(0);
}
/*************************************************************************/
/* neteventinit
* load up the pointers for the event queue
* makes a circular list to follow, required for error messages
*/
neteventinit()
{
int i;
for (i=0; i < NEVENTS; i++)
nnq[i].next = i+1;
nnq[NEVENTS-1].next = -1;
nnefirst = 0;
nnelast = 0;
nnefree = 1;
}
/*************************************************************************/
/* Ethernet headers, initialize a default header to be used in
* subsequent pre-initialized headers. This does something similar for
* AppleTalk.
*/
etherinit()
{
movebytes(broadaddr,bseed,DADDLEN);
movebytes(blankd.dest,broadaddr,DADDLEN); /* some are broadcast */
movebytes(blankd.me,nnmyaddr,DADDLEN); /* always from me */
blankd.type = EIP; /* mostly IP packets */
}
/*************************************************************************/
/* ARP packets
*
* a very limited type of packet goes out. We currently only talk IP, so
* initialize as many fields as possible, most fields are already known.
*
* Also initialize a reverse-arp packet to be sent out on request. (later)
*/
arpinit()
{
int i;
movebytes(&arp.d,&blankd,sizeof(DLAYER));
arp.d.type = EARP; /* 0x0806 is ARP type */
arp.hrd = intswap(HTYPE); /* Ether = 1 */
arp.pro = intswap(ARPPRO); /* IP protocol = 0x0800 */
arp.hln = DADDLEN; /* Ethernet hardware length */
arp.pln = 4; /* IP length = 4 */
movebytes(arp.sha,nnmyaddr,DADDLEN); /* sender's hardware addr */
movebytes(&arp.tha,broadaddr,DADDLEN); /* target hardware addr */
movebytes(&arp.spa,nnipnum,4); /* sender's IP addr */
/*
* initialize the ARP cache to 0 time, none are gateways to start
*/
for (i=0; i<CACHELEN; i++) {
arpc[i].tm = 0L;
arpc[i].gate = 0;
}
}
/*************************************************************************/
/* Internet protocol
* initialize one packet to use for arbitrary internet transmission.
* Hopefully, most outgoing IP packets will be pre-initialized by TCP or
* UDP, but some operations may require a generic IP packet.
*/
ipinit()
{
movebytes(&blankip.d,&blankd,sizeof(DLAYER));
blankip.i.versionandhdrlen = 0x45; /* smallest header, version 4 */
blankip.i.service = 0; /* normal service */
blankip.i.tlen = 576; /* no data yet, maximum size */
blankip.i.ident = 0;
blankip.i.frags = 0; /* not a fragment of a packet */
blankip.i.ttl = 100; /* 100 seconds should be enough */
blankip.i.protocol = PROTUDP; /* default to UDP */
blankip.i.check = 0; /* disable checksums for now */
movebytes(blankip.i.ipsource,nnipnum,4); /* my return address */
movebytes(blankip.i.ipdest,broadip,4); /* to ? */
#ifdef notneedednow
/*
* Make a blank ICMP packet for sending ICMP requests or responses
*/
movebytes(&blankicmp,&blankip,sizeof(DLAYER)+sizeof(IPLAYER));
blankicmp.i.protocol = PROTICMP;
#endif
/*
* create a mask which can determine whether a machine is on the same wire
* or not. RFC950
* Only set the mask if not previously set.
* This mask may be replaced by a higher level request to set the subnet mask.
*/
if (comparen(nnmask,"\0\0\0\0",4)) { /* now blank */
if (!(nnipnum[0] & 0x80)) /* class A */
netsetmask(nnamask);
else if ((nnipnum[0] & 0xC0) == 0x80) /* class B */
netsetmask(nnbmask);
else if ((nnipnum[0] & 0xC0) == 0xC0) /* class C */
netsetmask(nncmask);
}
}
/**************************************************************************/
/* UDP initialization
* set up ulist for receive of UDP packets
*/
udpinit()
{
ulist.stale = 1;
ulist.length = 0;
movebytes(&ulist.udpout,&blankip,sizeof(DLAYER)+sizeof(IPLAYER));
ulist.udpout.i.protocol = PROTUDP; /* UDP type */
ulist.tcps.z = 0;
ulist.tcps.proto = PROTUDP;
movebytes(ulist.tcps.source,nnipnum,4);
}
/**************************************************************************/
/* TCP stuff
* get ready for makeport()
* makeport() actually does the initialization when you open a port
*/
tcpinit()
{
int i;
for (i=0; i < NPORTS; i++)
portlist[i] = NULL; /* no ports open yet */
}
/**************************************************************************/
/* makeport
*
* This is the intialization for TCP based communication. When a port
* needs to be created, this routine is called to do as much pre-initialization
* as possible to save overhead during operation.
*
* This structure is created upon open of a port, either listening or
* wanting to send.
*
* A TCP port, in this implementation, includes all of the state data for the
* port connection, a complete packet for the TCP transmission, and two
* queues, one each for sending and receiving. The data associated with
* the queues is in struct window.
*/
makeport()
{
int i,j,retval;
struct port *p,*q;
/*
* Check to see if any other connection is done with its port buffer space.
* Indicated by the connection state of SCLOSED
*/
p = NULL;
i = 0;
do {
q = portlist[i];
if (q != NULL && (q->state == SCLOSED ||
(q->state == STWAIT && q->out.lasttime + WAITTIME < time(NULL))))
p = q;
retval = i++; /* port # to return */
} while (p == NULL && i < NPORTS);
/*
* None available pre-allocated, get a new one, about 8.5 K with a 4K windowsize
*/
if (p == NULL) {
p = (struct port *)malloc(sizeof(struct port));
for (i=0; portlist[i] != NULL; i++)
if (i >= NPORTS) {
nnerror(500);
return(-1); /* out of room for ports */
}
portlist[i] = p;
retval = i;
}
if (p == NULL) {
nnerror(505);
return(-1);
}
movebytes(&p->tcpout,&blankip,sizeof(DLAYER)+sizeof(IPLAYER));
/* static initialization */
p->tcpout.i.tlen = 0;
p->tcpout.t.urgent = 0; /* no urgent data */
p->tcpout.t.hlen = 20 << 2; /* header length << 2 */
p->tcps.z = 0;
p->tcps.proto = PROTTCP;
movebytes(p->tcps.source,nnipnum,4);
setupwindow(&p->in,WINDOWSIZE); /* queuing parameters */
setupwindow(&p->out,WINDOWSIZE);
do {
i = time(NULL);
i |= 2048; /* make sure it is at least this large */
i &= 0x3fff; /* at least this small */
for (j=0; j<NPORTS && i != portlist[j]->in.port ; j++)
;
} while (j < NPORTS);
if ( nnfromport ) { /* allow the from port to be forced */
i = nnfromport;
nnfromport = 0; /* reset it so the next one will be random */
}
p->in.port = i;
p->tcpout.t.source = intswap(i);
p->tcpout.t.seq = longswap(p->out.nxt);
p->state = SCLOSED;
p->credit = nncredit;
p->sendsize = TSENDSIZE;
p->rto = MINRTO;
return(retval);
}
setupwindow(w,wsize)
struct window *w;
unsigned int wsize;
{
w->endbuf = w->where + wsize;
w->base = w->endlim = w->where;
w->contain = 0; /* nothing here yet */
w->lasttime = time(NULL);
w->size = wsize;
w->push = 0;
/*
* base this on time of day clock, for uniqueness
*/
w->ack = w->nxt = ((w->lasttime << 12) & 0x0fffffff);
}