home *** CD-ROM | disk | FTP | other *** search
- /*
- * net.c
- *****************************************************************************
- * *
- * 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 *
- * *
- *****************************************************************************
- *
- * Revision History:
- * 9/91 Add SLIP support Nelson B. Bolyard
- *
- * those generic tool-type things that only work on PCs.
- * includes all hardware-level calls to Ethernet that are unique to the PC
- *
- * Function pointers for Ether calls
- */
-
- /*#define DEBUG*/
-
- #ifdef NETD
- # include <conio.h>
- #else
- #ifdef DEBUG
- # include <conio.h>
- #endif
- #endif
- #include "debug.h"
- #include <stdio.h>
- #include <string.h>
- #include "protocol.h"
- #include "data.h"
- #include "hostform.h"
- #include "externs.h"
-
- int SQwait=0;
- int OKpackets=0;
-
- /*
- * defined in assembly language file for interrupt driven Ether buffering
- *
- */
-
- extern unsigned char rstat; /* last status from read */
- extern char *bufpt, /* current buffer pointer */
- *bufend, /* pointer to end of buffer */
- *bufread, /* pointer to where program is reading */
- *buforg; /* pointer to beginning of buffer */
-
- extern int bufbig, /* number of bytes currently in buffer */
- buflim; /* max number of bytes in buffer */
-
- struct config def;
-
- /*
- * Declare each and every Ethernet driver.
- * To add a driver, pick a unique 2 char prefix and declare your own
- * routines. I want to keep the same parameters for EVERY driver.
- * If your driver needs additional parameters, then see netconfig() below
- * for an indication of where to put custom board code.
- */
- #ifndef PKT_ONLY /* save 20K by compiling packet driver only rmg 931100 */
- extern int CDECL E1etopen(),
- CDECL E1getaddr(),
- CDECL E1setaddr(),
- CDECL E1recv(),
- CDECL E1xmit(),
- CDECL E1etupdate(),
- CDECL E1etclose();
- extern int CDECL E3etopen(),
- CDECL E3getaddr(),
- CDECL E3setaddr(),
- CDECL E3recv(),
- CDECL E3xmit(),
- CDECL E3etupdate(),
- CDECL E3etclose();
- extern int CDECL E5etopen(),
- CDECL E5getaddr(),
- CDECL E5setaddr(),
- CDECL E5recv(),
- CDECL E5xmit(),
- CDECL E5etupdate(),
- CDECL E5etclose(),
- CDECL E5etdma();
- extern int CDECL ATetopen(),
- CDECL ATgetaddr(),
- CDECL ATrecv(),
- CDECL ATxmit(),
- CDECL ATetupdate(),
- CDECL ATetclose();
- extern int CDECL M5etopen(),
- CDECL M5getaddr(),
- CDECL M5recv(),
- CDECL M5xmit(),
- CDECL M5etupdate(),
- CDECL M5etclose();
- extern int CDECL M9etopen(),
- CDECL M9getaddr(),
- CDECL M9recv(),
- CDECL M9xmit(),
- CDECL M9etupdate(),
- CDECL M9etclose();
- extern int CDECL U1etopen(),
- CDECL U1getaddr(),
- CDECL U1recv(),
- CDECL U1xmit(),
- CDECL U1etupdate(),
- CDECL U1etclose();
- extern int CDECL U2etopen(),
- CDECL U2getaddr(),
- CDECL U2recv(),
- CDECL U2xmit(),
- CDECL U2etupdate(),
- CDECL U2etclose();
- extern int CDECL WDetopen(),
- CDECL WDgetaddr(),
- CDECL WDrecv(),
- CDECL WDxmit(),
- CDECL WDetupdate(),
- CDECL WDetclose();
- extern int CDECL WAetopen(),
- CDECL WAgetaddr(),
- CDECL WArecv(),
- CDECL WAxmit(),
- CDECL WAetupdate(),
- CDECL WAetclose();
- extern int CDECL E2etopen(),
- CDECL E2getaddr(),
- CDECL E2recv(),
- CDECL E2xmit(),
- CDECL E2etupdate(),
- CDECL E2etclose();
- extern int CDECL E4etopen(),
- CDECL E4getaddr(),
- CDECL E4recv(),
- CDECL E4xmit(),
- CDECL E4etupdate(),
- CDECL E4etclose();
- #endif /* PKT_ONLY */
-
- #ifndef EXTERNS_H
- extern int CDECL LTopen(),
- CDECL LTgetaddr(),
- CDECL LTxmit(),
- CDECL LTclose();
- extern void CDECL LTrecv(),
- CDECL LTupdate();
- extern int CDECL pketopen(),
- CDECL pkgetaddr(),
- CDECL pkxmit(),
- CDECL pketclose();
- extern void CDECL pkrecv(),
- CDECL pketupdate();
- extern int CDECL DNetopen(),
- CDECL DNgetaddr(),
- CDECL DNxmit(),
- CDECL DNetclose();
- extern void CDECL DNrecv(),
- CDECL DNetupdate();
- extern int CDECL ILetopen(),
- CDECL ILgetaddr(),
- CDECL ILxmit(),
- CDECL ILetclose();
- extern void CDECL ILrecv(),
- CDECL ILetupdate();
- #endif
-
- static int CDECL (*etopen)(unsigned char *s,unsigned int irq,unsigned int addr,unsigned int ioaddr)=NULL, /* open the device */
- CDECL (*getaddr)(unsigned char *s,unsigned int addr,unsigned int ioaddr)=NULL, /* get the Ether address */
- CDECL (*setaddr)(char *s,int addr,int ioaddr)=NULL, /* set the Ether address */
- CDECL (*etclose)(void )=NULL, /* shut down network */
- CDECL (*xmit)(DLAYER *packet,unsigned int count)=NULL; /* transmit a packet */
- static void CDECL (*recv)(void )=NULL, /* load a packet from queue */
- CDECL (*etupdate)(void )=NULL; /* update pointers in buffer */
-
- #ifndef NET14
- #ifdef NOT_USED
- /**********************************************************************/
- /* statcheck
- * look at the connection status of the memory buffers to see if the
- * allocation schemes are working. Only used as a debug tool.
- */
-
- void statcheck(void )
- {
- int i;
- struct port *p;
-
- for(i=0; i<20; i++) {
- printf("\n%d > ",i);
- p=portlist[i];
- if(p!=NULL)
- printf("state: %d %5u %5u %10ld %5d %5d",
- p->state,intswap(p->tcpout.t.source),
- intswap(p->tcpout.t.dest),p->out.lasttime,p->rto,
- p->out.contain);
- } /* end for */
- }
- #endif
- #endif
-
- /*************************************************************************/
- /* config network parameters
- * Set IRQ and DMA parameters for initialization of the 3com adaptor
- */
- static uint nnirq=3,nnaddr=0xd000,nnioaddr=0x300;
-
- int netparms(uint irq,uint address,uint ioaddr)
- {
- BUG("netparms");
-
- nnirq=irq;
- nnaddr=address;
- nnioaddr=ioaddr;
- #ifdef DEBUG
- printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
- printf("press a key\n");
- getch();
- #endif
- return(0);
- }
-
- /**********************************************************************/
- /* netconfig
- * load the function pointers for network access
- * Currently setaddr() is not used, so it isn't loaded.
- *
- * Note that netparms is called BEFORE netconfig. So if you have any
- * really special variables to set for your board that involve
- * irq,address and ioaddr, you can add calls to your special routines
- * in this section.
- *
- * Some drivers will do the interrupt driver and board initialization
- * in etopen() and some will do it in getaddr().
- */
- void netconfig(char *s)
- {
-
- Sgetconfig(&def); /* get information provided in hosts file */
-
- #ifndef PKT_ONLY
- if(!strncmp(s,"iso",3) || !strncmp(s,"bicc",4)) {
- etopen=ILetopen;
- xmit=ILxmit;
- recv=ILrecv;
- getaddr=ILgetaddr;
- etupdate=ILetupdate;
- etclose=ILetclose;
- } /* end if */
- else if(!strncmp(s,"3c505",5) || !strncmp(s,"505",3)) {
- etopen=E5etopen;
- xmit=E5xmit;
- recv=E5recv;
- getaddr=E5getaddr;
- etupdate=E5etupdate;
- etclose=E5etclose;
- } /* end if */
- else if(!strncmp(s,"decnet",6) || !strncmp(s,"dn",2)) {
- etopen=DNetopen;
- xmit=DNxmit;
- recv=DNrecv;
- getaddr=DNgetaddr;
- etupdate=DNetupdate;
- etclose=DNetclose;
- } /* end if */
- else if(!strncmp(s,"star10",6) || !strncmp(s,"starlan",7)) {
- etopen=ATetopen;
- xmit=ATxmit;
- recv=ATrecv;
- getaddr=ATgetaddr;
- etupdate=ATetupdate;
- etclose=ATetclose;
- } /* end if */
- else if(!strncmp(s,"packet",6)) {
- #else
- if(!strncmp(s,"packet",6)) {
- #endif /* PKT_ONLY */
- etopen=pketopen;
- xmit=pkxmit;
- recv=pkrecv;
- getaddr=pkgetaddr;
- etupdate=pketupdate;
- etclose=pketclose;
- }
- #ifndef PLT_ONLY
- else if(!strncmp(s,"ni9",3) || !strncmp(s,"92",2)) {
- etopen=M9etopen;
- xmit=M9xmit;
- recv=M9recv;
- getaddr=M9getaddr;
- etupdate=M9etupdate;
- etclose=M9etclose;
- }
- else if(!strncmp(s,"ni5",3) || !strncmp(s,"mi",2)) {
- etopen=M5etopen;
- xmit=M5xmit;
- recv=M5recv;
- getaddr=M5getaddr;
- etupdate=M5etupdate;
- etclose=M5etclose;
- /*
- * special initialization call would go here
- */
- }
- else if(!strncmp(s,"nicps",5)) {
- etopen=U2etopen;
- xmit=U2xmit;
- recv=U2recv;
- getaddr=U2getaddr;
- etupdate=U2etupdate;
- etclose=U2etclose;
- }
- else if(!strncmp(s,"nicpc",5) || !strncmp(s,"pcnic",5)) {
- etopen=U1etopen;
- xmit=U1xmit;
- recv=U1recv;
- getaddr=U1getaddr;
- etupdate=U1etupdate;
- etclose=U1etclose;
- }
- else if(!strncmp(s,"wd8003a",7) || !strncmp(s,"8003a",5)) {
- etopen=WAetopen;
- xmit=WAxmit;
- recv=WArecv;
- getaddr=WAgetaddr;
- etupdate=WAetupdate;
- etclose=WAetclose;
- }
- else if(!strncmp(s,"wd",2) || !strncmp(s,"800",3)) {
- etopen=WDetopen;
- xmit=WDxmit;
- recv=WDrecv;
- getaddr=WDgetaddr;
- etupdate=WDetupdate;
- etclose=WDetclose;
- }
- else if(!strncmp(s,"3c523",5) || !strncmp(s,"523",3)) {
- etopen=E2etopen;
- xmit=E2xmit;
- recv=E2recv;
- getaddr=E2getaddr;
- etupdate=E2etupdate;
- etclose=E2etclose;
- }
- else if( !strncmp(s,"3c503",5) || !strncmp(s,"503",3)) {
- etopen=E4etopen;
- xmit=E4xmit;
- recv=E4recv;
- getaddr=E4getaddr;
- etupdate=E4etupdate;
- etclose=E4etclose;
- E4setwire(def.wire*2);
- }
- else if(!strncmp(s,"ltalk",5) || !strncmp(s,"atalk",5) || !strncmp(s,"apple",5)) {
- extern unsigned int LTalk_vector;
-
- nnkip=1; /* turn kip arping on */
- LTalk_vector=nnirq;
- #ifdef __WATCOMC__
- etopen=(void *)LTopen;
- #else
- etopen=LTopen;
- #endif
- xmit=LTxmit;
- recv=LTrecv;
- #ifdef __WATCOMC__
- getaddr=(void *)LTgetaddr;
- #else
- getaddr=LTgetaddr;
- #endif
- etupdate=LTupdate;
- etclose=LTclose;
- }
- else if(!strncmp(s,"r501",4)) { /* special reserve driver */
- etopen=E3etopen;
- xmit=E3xmit;
- recv=E3recv;
- getaddr=E3getaddr;
- etupdate=E3etupdate;
- etclose=E3etclose;
- }
- else { /* default choice */
- etopen=E1etopen;
- xmit=E1xmit;
- recv=E1recv;
- getaddr=E1getaddr;
- etupdate=E1etupdate;
- etclose=E1etclose;
- }
- #else
- else { /* default choice */
- fprintf(stdout,"You are using the PACKET DRIVER ONLY version of Telnet\n");
- #ifdef AUX
- fprintf(stdaux," packet driver version ");
- #endif
- }
- #endif
- } /* end netconfig() */
-
- /**********************************************************************/
- /* netarpme
- * send an arp to my address. arpinterpret will notice any response.
- * Checks for adapters which receive their own broadcast packets.
- */
- int netarpme(char *s)
- {
- #ifndef PKT_ONLY
- if(etopen==U2etopen)
- return(0);
- if(etopen==U1etopen)
- return(0);
- #endif
- #ifdef __WATCOMC__
- if(etopen==(void *)LTopen) /* not needed for Local Talk */
- return(0);
- #else
- if(etopen==LTopen) /* not needed for Local Talk */
- return(0);
- #endif
- reqarp(s); /* send it */
- return(0);
- } /* end netarpme() */
-
- /**********************************************************************/
- int initbuffer(void)
- {
- bufpt=bufread=buforg=raw; /* start at the beginning */
- BUG("initbuffer");
-
- bufbig=0;
- #if defined(NET14)
- bufend=&raw[4500]; /* leave 2K breathing room, required */
- buflim=2000; /* another 2K breathing room */
- #elif defined(__TURBOC__) || defined(__WATCOMC__)
- bufend=&raw[7500]; /* leave 2K breathing room, required */
- buflim=5000; /* another 2K breathing room */
- #else
- bufend=&raw[14500]; /* leave 2K breathing room, required */
- buflim=12000; /* another 2K breathing room */
- #endif
-
- BUG("before getaddr");
- #ifdef DEBUG
- printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
- printf("getaddr = %p\n",getaddr);
- printf("press a key\n");
- getch();
- #endif
-
- BUG("about to getaddr");
- /* QAK was if-def'ed out */
- (*getaddr)(nnmyaddr,nnaddr,nnioaddr);
- BUG("after getaddr");
-
- #ifdef NETD
- printf("Addr=%x.%x.%x.%x.%x.%x\n",nnmyaddr[0],nnmyaddr[1],nnmyaddr[2],
- nnmyaddr[3],nnmyaddr[4],nnmyaddr[5]);
- #endif
- return(0);
- }
-
- /**********************************************************************/
- /* demux
- * find the packets in the buffer, determine their lowest level
- * packet type and call the correct interpretation routines
- *
- * the 'all' parameter tells demux whether it should attempt to empty
- * the input packet buffer or return after the first packet is dealt with.
- *
- * returns the number of packets demuxed
- */
- int demux(int all)
- {
- uint16 getcode;
- int nmuxed;
- DLAYER *firstlook;
-
- nmuxed=0;
- if(!etupdate) /* check that network is hooked up */
- return(0);
- do { /* while all flag is on */
- (*recv)(); /* NULL operation for 3COM */
- #ifdef NETD
- printf("After Masking!\n");
- printf("bufpt->%p, bufread->%p, bufend->%p\n",bufpt,bufread,bufend);
- printf("bufbig = %d\n", bufbig);
- getch();
- #endif
- if(bufbig>0) {
- nmuxed++;
- firstlook=(DLAYER *)(bufread+2); /* where packet is */
- #ifdef CHECKRARP
- fprintf(stderr,"dest=%x.%x.%x.%x.%x.%x, me=%x.%x.%x.%x.%x.%x, type=0x%X\r\n",
- (unsigned int)firstlook->dest[0],(unsigned int)firstlook->dest[1],(unsigned int)firstlook->dest[2],
- (unsigned int)firstlook->dest[3],(unsigned int)firstlook->dest[4],(unsigned int)firstlook->dest[5],
- (unsigned int)firstlook->me[0],(unsigned int)firstlook->me[1],(unsigned int)firstlook->me[2],
- (unsigned int)firstlook->me[3],(unsigned int)firstlook->me[4],(unsigned int)firstlook->me[5],
- firstlook->type);
- fprintf(stderr,"big=%d, size=%d\r\n",bufbig,(int)(bufpt-bufread));
- #endif
-
- getcode=firstlook->type; /* where does it belong? */
- switch(getcode) { /* what to do with it? */
- case EARP:
- case ERARP:
- #ifdef CHECKRARP
- fprintf(stderr,"arp\r\n");
- #endif
- arpinterpret((ARPKT *)firstlook); /* handle ARP packet */
- break;
-
- case EIP:
- #ifdef CHECKRARP
- fprintf(stderr,"ip\r\n");
- #endif
- ipinterpret((IPKT *)firstlook);
- break;
-
- default:
- #ifdef CHECKRARP
- fprintf(stderr,"garbage\r\n");
- #endif
- break;
- } /* end switch */
- (*etupdate)(); /* update read pointers in buffer, free packet */
- } /* end if */
- else
- all=0;
- } while(all); /* should we look for more to deal with? */
- return(nmuxed); /* no packets anymore */
- } /* end demux() */
-
- /************************************************************************/
- /* dlayersend
- *
- * usage: err=dlayersend(ptr,size)
- * err=0 for successful, non-zero error code otherwise
- * ptr is to a dlayer packet header
- * size is the number of bytes total
- *
- * This particular dlayer routine is for Ethernet. It will have to be
- * replaced for any other dlayer.
- *
- * Ethernet addresses are resolved at higher levels because they will only
- * need to be resolved once per logical connection, instead of once per
- * packet. Not too layer-like, but hopefully modular.
- *
- */
- int dlayersend(DLAYER *ptr,unsigned int size)
- {
- int ret,i;
-
- #ifndef OLD_WAY
- if(size<60)
- size=60;
- if(size&0x01)
- size+=1;
- #else
- #ifdef NEW_WAY
- unsigned char *c;
-
- c=(unsigned char *)ptr;
- *(c+size++)=0; /* NULL pad last char */
- *(c+size++)=0; /* NULL pad last char */
- #else
- unsigned char *c;
- unsigned int u;
-
- /* This code is sort of a synthesis of the previous two pieces of code, let's see if it works */
- c=(unsigned char *)ptr;
- if(size<60) {
- for(u=size,c+=size; u<60; u++)
- *c++=0; /* NULL pad added chars */
- size=60;
- } /* end if */
- #ifdef QAK
- if(size&0x01)
- *(c+size++)=0; /* NULL pad last char */
- #endif
- #endif
- #endif
-
- for(i=0; i<SQwait; i++);
-
- if((++OKpackets)>10) {
- SQwait-=10;
- OKpackets=0;
- } /* end if */
-
- if(SQwait<10)
- SQwait=10;
-
- ret=(*xmit)((DLAYER *)ptr,size); /* send it out, pass back return code */
- /* xmit checks for size < 60 */
- /*
- * automatic, immediate retry once
- */
- if(ret) {
- if(ret==(*xmit)((DLAYER *)ptr,size))
- nnerror(100); /* post user error message */
- } /* end if */
- return(ret);
- } /* end dlayersend() */
-
- /***************************************************************************/
- /* dlayerinit
- * Do machine dependent initializations of whatever hardware we have
- * (happens to be ethernet board here )
- */
- int dlayerinit(void )
- {
- int my_var;
-
- BUG("dlayerinit");
- #ifdef DEBUG
- printf("etopen = %p\n",etopen);
- #endif
- if(initbuffer() || !etopen)
- return(-10);
-
- #ifdef QAK
- printf("dlayerinit(): after initbuffer()\n");
- printf("etopen=%p\n",etopen);
- printf("nnmyaddr=%p\n",nnmyaddr);
- printf("nnirq=%x, nnaddr=%x, nnioaddr=%x\n",(uint16)nnirq,(uint16)nnaddr,(uint16)nnioaddr);
- getch();
- #endif
- /*
- * Call (*etopen) first to be sure any board/driver initializations are taken care of
- */
- my_var = ((*etopen)(nnmyaddr,nnirq,nnaddr,nnioaddr));
- #ifdef QAK
- printf("my_var is %d\n", my_var);
- getch();
- #endif
- return(my_var);
- }
-
- void dlayershut(void )
- {
- if(etclose)
- (*etclose)();
- }
-
- /***************************************************************************/
- /* pcgetaddr
- * return results from indirect getaddr call.
- * This is a pc-specific request for the 48-bit address which was added
- * so that the user program could print the value.
- */
- void pcgetaddr(char *s,int x,int y)
- {
- if(getaddr)
- (*getaddr)(s,x,y);
- }
-