home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 *
- * *
- * Copyright (c) 1987, Board of Trustees of the University of Illinois *
- * *
- ****************************************************************************
- * '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 <string.h>
-
- #include <Events.h>
- #include <Memory.h>
-
- #include "protocol.h"
- #include "data.h"
- #include "tools.h"
- #include "user.h"
-
- #define UNKNOWN_PORT_TYPE 0 /* BYU 2.4.16 */
- #define MACTCP_PORT_TYPE 1 /* BYU 2.4.16 */
- #define NCSA_PORT_TYPE 2 /* BYU 2.4.16 */
-
- extern unsigned char SLIP_ip_number[]; /* BYU 2.4.15 */
-
- extern short porttype[]; /* BYU 2.4.16 */
-
- /*************************************************************************/
- /* Ethernet headers, initialize a default header to be used in
- * subsequent pre-initialized headers. This does something similar for
- * AppleTalk.
- */
-
- void etherinit
- (
- void
- )
- {
- 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)
- */
-
- void arpinit
- (
- void
- )
- {
- 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.
- */
-
- void ipinit
- (
- void
- )
- {
- 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);
- }
-
- }
-
- /**************************************************************************/
- /* TCP stuff
- * get ready for makeport()
- * makeport() actually does the initialization when you open a port
- */
-
- void tcpinit
- (
- void
- )
- {
- int i;
-
- for (i=0; i < NPORTS; i++) { /* BYU 2.4.16 */
- portlist[i] = NULL; /* no ports open yet */
- porttype[i] = UNKNOWN_PORT_TYPE; /* BYU 2.4.16 */
- } /* BYU 2.4.16 */
- }
-
- /**************************************************************************/
- /* UDP initialization
- * set up ulist for receive of UDP packets
- */
-
- void udpinit
- (
- void
- )
- {
- 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);
-
- }
-
- /************************************************************************/
- /* main code for protinit()
- * for each new type of protocol, put an initialization call here.
- * There may be some requirement of order of initialization.
- */
- int protinit
- (
- void
- )
- {
-
- etherinit();
- arpinit();
- ipinit();
- tcpinit();
- udpinit();
-
- return(0);
- }
-
- void setupwindow
- (
- 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);
-
- }
-
- /**************************************************************************/
- /* 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.
- */
- int makeport
- (
- short connectionType /* BYU 2.4.15 - was "void" */
- )
- {
- 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 && porttype[i] == NCSA_PORT_TYPE && (q->state == SCLOSED || /* BYU 2.4.16 */
- (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 *)NewPtr(sizeof(struct port));
-
- for (i=0; portlist[i] != NULL || /* BYU 2.4.16 */
- porttype[i] != UNKNOWN_PORT_TYPE; i++) /* BYU 2.4.16 */
- 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;
-
- if (connectionType) { /* BYU 2.4.15 */
- movebytes(p->tcpout.i.ipsource,SLIP_ip_number,4); /* BYU 2.4.15 */
- movebytes(p->tcps.source,SLIP_ip_number,4); /* BYU 2.4.15 */
- } else /* BYU 2.4.15 */
- movebytes(p->tcps.source,nnipnum,4); /* BYU 2.4.15 */
-
- 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;
- }
-
- 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);
- }
-