
/*
   * NETWATCH is based on some code from Statnet 
   * Statnet is protected under the GNU Public License (GPL2). 
   * Author: Jeroen Baekelandt (jeroenb@igwe.vub.ac.be)       
   * 27DEC95: Scot E. Wilcoxon (sewilco@fieldday.mn.org)     
   * NETWATCH is VERY loosely based on the code from Statnet... thanks out
   * to Jeroen and Scot...
   * 
   * NETWATCH allows a user (superuser) to monitor an ETHERNET and examine
   * activity on the network. Hostnames are highlighted in colours (for
   * those supporting them) to indicate activity on the bus network based on 
   * time ( less than 1 minute RED, less than 5 minutes YELLOW, less than 30 
   * minutes GREEN and otherwise BLUE). The monitor includes statistics on 
   * a) Transmitted and received packets b) Protocol of LAST packet (TX or
   * RC) c) LAST Communication partner (IP address)
   * 
   * The number of hosts capable of support is a function of memory. They
   * are stored in 2 doubly-linked lists (local and remote).
   * 
   * Screen updates take place 1 per second (unless a rare  lockout... when
   * linked list links are updating... in which case it displays in the next 
   * second)
   * 
   * Keyboard usage is admittedly limited (and a kludge... due to some
   * ncurses settings that need better tinkering) ->   Go forward to next
   * option <-   Go backward to previous option <UP>         Go back to
   * previous page (back 20 lines on most consoles) <DOWN>       Go forward
   * to next page (forward 20 lines on most consoles) c    Clear counters
   * for fresh counting n    Clear linked lists for new start
   * 
   * It is a simple program to execute for ETHERNET under LINUX. It assumes
   * that there is a "/etc/rc.d/rc.inet1" file for network configuration. If 
   * so, it checks for an "eth0" ifconfig and picks up the netmask from the
   * file. UPDATE: It actually looks at the /proc entry for device configuration
   * to get its info... if no /proc THEN it trys the config file (for OLD SL
   * systems)
   * 
   * For those with multiple "eth" interfaces, I am sorry it doesn't support 
   * both simultaneously.
   * 
   * AUTHOR:      G. MacKay E-MAIL:      mackay@gmml.slctech.org
   * 
   * P.S. Given the fact that I was sick for 3 days and decided to write
   * this code... forgive me for not writing beautiful code... (those that
   * know me, probably don't think my code is beautiful when I am healthy)
   * 
   * NEW CODE IS COPYRIGHTED to  G. MacKay   under  GPL 
*/

/*
   * This is the main FILE 
*/
#define MAIN_LINE 1
#include "config.h"

#ifdef NEWCURSES_SUPP
#include <ncurses/curses.h>
#else
#ifdef NEWCURSESROOT_SUPP
#include <ncurses.h>
#else
#include <curses.h>
#endif
#endif

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h> 
#include <unistd.h>
/*
   * #include <sys/socket.h> 
*/
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/times.h>
#ifdef NETINET_SUPP_in
#include <netinet/in.h>
#else
#include <linux/in.h>
#endif
#ifdef NETINET_SUPP_if_ether
#include <netinet/if_ether.h>
#else
#include <linux/if_ether.h>
#endif
#include <strings.h>
#include <sys/ioctl.h>

#ifdef NETINET_SUPP_if
#include <net/if.h>
#else
#include <linux/if.h>
#endif
#ifdef NETINET_SUPP_if_ppp
#include <net/if_ppp.h>
#else
#include <linux/if_ppp.h>
#endif

#include <signal.h>
#ifdef NETINET_SUPP_ip
#include <netinet/ip.h>
#else
#include <linux/ip.h>
#endif
#ifdef NETINET_SUPP_tcp
#include <netinet/tcp.h>
#else
#ifdef NETINET_SUPP_ip_tcp
#include <netinet/ip_tcp.h>
#else
#include <linux/tcp.h>
#endif
#endif
#ifdef NETINET_SUPP_udp
#include <netinet/udp.h>
#else
#ifdef NETINET_SUPP_ip_udp
#include <netinet/ip_udp.h>
#else
#include <linux/udp.h>
#endif
#endif
#if NETINET_SUPP_icmp
#include <netinet/ip_icmp.h>
#else
#include <linux/icmp.h>
#endif

#if SYS_IF_PACKET_H
#include <sys/if_packet.h>
#endif
#if LINUX_IF_PACKET_H
#include <linux/if_packet.h>
#endif
#if NET_IF_PACKET_H
#include <net/if_packet.h>
#endif
/*  For those systems that need it!!!! -> New OS */
//#if LINUX_TIMEDEF
#include <time.h>
//#endif

#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include "curs.h"
#include "netresolv.h"
#include "netwatch.h"

extern int errno;

#define MAXFILENAME 256
char *version = "1.0c";
char *iv = "-gm";
char progtitle[60];
char specconfigfile[MAXFILENAME] = "/root/.netwatch.conf";

int fdlog;
#if defined(_LINUX_IF_ETHER_H) || defined(_NETINET_IF_ETHER_H)
#undef NET_3   /*
   * not using Net/3 definitions 
*/
#endif

#ifndef ETH_HLEN
#define ETH_HLEN 14  /*
   * Ethernet header length 
*/
#endif

#ifndef ETH_P_ATALK
#define ETH_P_ATALK 0x809B /*
   * Appletalk 
*/
#endif

#ifndef SOCK_PACKET
#define SOCK_PACKET SOCK_RAW /*
   * If SOCK_PACKET is wrong, try SOCK_RAW 
*/
#endif

#ifndef NET_3
#define ether_head ethhdr /*
   * ether_head structure 
*/
#define ether_type h_proto /*
   * Ethernet Packet Type ID field 
*/
#define ip  iphdr /*
   * IP header structure 
*/
#define ip_off  frag_off 
/*
 * IP protocol field 
*/
#define ip_p  protocol
/*
 * IP protocol field 
*/
#define ip_hl  ihl
/*
 * IP header length field 
*/
#ifndef _NETINET_IP_TCP_H
#ifndef __FAVOR_BSD
#define th_sport source /*
   * TCP source port field 
*/
#define th_dport dest /*
   * TCP destination port field 
*/
#endif
#endif
#ifdef LINUXINET_SUPP_udp

#define ui_sport source /*
   * UDP source port field 
*/
#define ui_dport dest /*
   * UDP destination port field 
*/

#endif
#endif


#define ETHERHEADSIZE (sizeof(struct ether_head))
int ethsz = ETHERHEADSIZE;
#define IPSIZE (sizeof(struct ip))
int ipsz = IPSIZE;
#define IPOPTSIZE 12
int ipoptsz = IPOPTSIZE;
#define TCPHEADSIZE (sizeof(struct tcphdr))
int tcpheadsz = TCPHEADSIZE;
#define SN_RCV_BIGBUFSIZE 2048
/*
   #define SN_RCV_BIGBUFSIZE SN_RCV_BUF_SIZE+80
   * above was 1600, but kernel discards 
*/
/*
   * excess and tells us full length,   
*/
/*
   * so we only need enough to analyze. 
*/
const int sn_rcv_bufsize = SN_RCV_BIGBUFSIZE;
int ESCON = 0;
#define ESC 0x1b
#define RETURNKEY 0x0d
#define CONTROLL  12
#define MAXHELPPAGE 3
HOSTINFO ldummy, rdummy;
HOSTINFO *lfirst, *rfirst, *previous, *current, *next, *work;
struct itimerval newtm, oldtm; /*
   * TIMER for measuring 
*/
time_t new;
time_t starttime;
time_t wakeup_reload;
int wakeup_state = FALSE;
time_t reload_timer_start;
int reload_timer_sec = 0;
int reload_active = FALSE;
int statsdate = FALSE;
int statsappend = TRUE;
char tmstring[80] = "%Y.%m.%d.%H.%M";
int freezedisplay = FALSE;
int lastfreeze = FALSE;
int sentclear = FALSE;
int donecleaning = TRUE;
int recresolv = 0;
int timeresolv = 0;
int sendresolv = 0;
int errread = 0;
int errioctl = 0;

int bpsflag = 0;

#define MAXDAYROUTE 1440
float dayroute[MAXDAYROUTE];
int cur_dayroute = 0;
int routersummary = FALSE;
int rdelta = 60;
int router_offset = 0;

int autostatus = TRUE;
int noresolv = FALSE;

int rel_hours, rel_mins;

int localcount = 0;
int remotecount = 0;

#define MAXSTATUS 14
#define STATUSSIZE 200
char status_lines[MAXSTATUS][STATUSSIZE];
int cur_status_line = 0;

int sREDTIME = 60;
int sYELLOWTIME = 300;
int sGREENTIME = 1800;
char configfile[MAXFILENAME] = "/etc/rc.d/rc.inet1";
char statsfile[MAXFILENAME] = "/etc/netwatch.stats";
char newstatsfile[MAXFILENAME];
int newconfig = FALSE;
char ethdevname[64] = "eth0";
int newethname = FALSE;
int probcnt = 0;  /*
   * Problem Count  on ETH reads 
*/
int intrcnt = 0;  /*
   * EINTR hits  on ETH reads 
*/



#define MAGNABUFSIZE 2048
struct magrec
{
      int len;
      char dir;
      unsigned char buf[MAGNABUFSIZE];
};
#define MAGNAMAX 800
#define MAGNAOFFS 40
struct magrec magna[MAGNAMAX];
int magnacnt = 0;
int magnaoffs = MAGNAOFFS;
char magnamatch[RESOLVE_MAX];
HOSTINFO *magnaspot;
u_int32_t magnakey;
int magnaphys = 0;
int magnafirst = TRUE;
int magnafull = FALSE;
HOSTINFO *magnacomhost = NULL;
u_int32_t magnacomkey;

double maxburst = 0.0;
double absmaxburst = 0.0;
unsigned char netmask[4] = {  255, 255, 255, 0  };
unsigned char localaddr[4];
int ethok = 1;
struct hostent *hostent;
int wai = 0;
int selprob = 0;
int selcode = 0;
int bugfix = FALSE;
int help = FALSE;
int helppage = 1;
int watch = FALSE;
int remoterow = -1;
int localrow = -1;
int localupdate = 0;
int remoteupdate = 0;
int poschange = 0;
int refreshloc = 0;
int refreshrem = 0;
int refreshgen = 0;
int llockout = 0;
int rlockout = 0;
int lydisp = 0;
int rydisp = 0;
int ydisp = 0;
int localkey = TRUE;
int dispopt = DISP_TX_RC;
int colour;
unsigned long int routeruse = 0;
unsigned long int routerto = 0;
unsigned long int routerfrom = 0;
int disprouterstats = FALSE;
int scrmid;
int selecthost = FALSE;
int numselect = 0;
int selectside = 0;
int selectchange = FALSE;
int bluedie = 0;
int ignoredomain = 0;
int statpid = -1010;  /*
   * Magic number to indicate NO
   * status process present 
*/

int sd;

char tmpbuf[256];
char speclogfile[MAXFILENAME] = "/root/.watchlog";
FILE *fpspeclog;
int speclog = 0;
int printtospeclog = 0;
int speclogext = 0;

int topflag = 0;
HOSTINFO *toplocal;
HOSTINFO *topremote;
HOSTINFO tldummy, trdummy;
/*
   * For screen size independent settings.... display... 
*/
int curskeyspot;
int curskeyval;
int cursllockout;
int cursrlockout;
int curslines;
int curshosttrim;
int cursproto;
int cursdest;
int noscreen = 0;
int fishspeclog = 0;  /*
   * old speclog for fishing
   * expedition 
*/

long int ethcnt = 0;
int isethdev = TRUE;
int keycnt = 0;
int repeatcount = 1;
int repeatindex = 0;
char repeatbuf[255];

int isbridge = FALSE;
int dupcount = 0;
int forcelocal = FALSE;
u_int32_t flocal;
int nonameresolve = FALSE;
int forcemask = FALSE;
u_int32_t fmask;
int nokeys = FALSE;

unsigned char workingmac[ETH_ALEN];
/*
   * unsigned char badmac[ETH_ALEN]; 
*/
/*
   * unsigned long badmactime; 
*/

#define SMALLSCREEN 0
#define FULLSCREEN 1

unsigned char buf[SN_RCV_BIGBUFSIZE + 1];
unsigned char rbuf[SN_RCV_BIGBUFSIZE + 1];


struct ifreq ifr, oldifr;
struct sockaddr_in *pin;


struct at_frame_type
{
      unsigned char filler[20];
      u_int16_t appletalk_type1; /*
         * what is formal name? 
*/
      unsigned char filler2[12];
      u_int8_t appletalk_type2; /*
         * what is formal name? 
*/
};    /*
   * Ethernet Appletalk 
*/
#define SIM_MAGIC 0xfafa
unsigned short simmagic = SIM_MAGIC;
/*   Simulator file.... STARTING TIME (on creation)
   *   					MAGIC (16 bits)
   *   					PACKET OFFSET TIME (from starting time)
   *   					LENGTH of remainder in bytes
   *   					PACKET Data (Length long)
   *   					MAGIC (16 bits)
   *   					etc...
*/
int simchange = FALSE;
int simfwdir = TRUE;
int simarr[8]= {  4,4,4,4,4,4,4,4  };
char *simfmt = "\\%d<\\%d<\\%d<\\%d%c\\%d>\\%d>\\%d>";
const int MAXTHEM=20;
const int MAXTHEMm1=19;
/*
 *   #define MAXTHEM 20
 *   #define MAXTHEMm1 MAXTHEM
*/
int themnum=0;
u_int32_t logthem[20];  /* Up to 20 log names allowed */
time_t actstart;
double mactstart;
clock_t lasttime;  /* last NOW... */
clock_t offsclk=0; /* Offset from sim. start */
clock_t loff = 0;
clock_t lrealoff = 0;
clock_t fileclk; /* Clock INSIDE file record */
struct tms dumbtime;
clock_t sclk;		/* Starting time of program... */
int iseth = FALSE;
int nw_logall = 0;
char nw_allname[256]="/root/nw_allpackets";
FILE *nw_fpall=NULL;
int nw_logremote = 0;
char nw_remname[256]="/root/nw_rempackets";
FILE *nw_fprem=NULL;
int nw_loglocal = 0;
char nw_locname[256]="/root/nw_locpackets";
FILE *nw_fploc=NULL;
int nw_logindiv = 0;
char nw_indivmain[256]="/root/nw_indiv.";
int nw_logselect = 0;
int nw_simulate = 0;
char nw_simfile[256]="";
enum {  SIMSEC, SIMKEY  };
int nw_simrate = SIMSEC;
int simkeyrate = 0;
FILE *simfp=NULL;
int plogselect=0;
int plogdeselect=0;
int buf_detail = 0;  /* For ASCII default */
#define BUF_DETAIL_MAX 3
int mailflag = 1;
int syslogflag = 1;
char userwarn[256] = "noone@xxx.xxx.xxx"; /* ENTER your MAIL Address here.. */
char fishstring[256] = "";
int fishstringlen = 0;
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr,
   int eth, int direct);
void handle_ip (struct ip *buf, int length, int direct);
void processinetrc (unsigned char *netmask, unsigned char *local, int *peth);
void warning (char s[], unsigned char *buf);


typedef void (*sigfunc) (int);

/*
 *	Section for FIFO and X-term I/F
 *	   FIFO name, FIFO descriptor, FIFO flag... if using?
 *
 */
char fifoname[256]="/root/.netwatch.pipe";
int fifo;
int using_fifo=FALSE;
int fifoval = 0;
#define FIFOMARK 0xf5
const int  INTSIZE=sizeof(short int);

static pid_t mypid, child;
int msocket[2];
int osocket[2];
int resolvetimeout = 0;
extern long int timezone;

int movemagnakeyloc = FALSE;
int movemagnakeyrem = FALSE;
u_int32_t searchaddr = 0;


void findaddr( u_int32_t searchaddr );
	
void do_fifo()
{
	static short int keycomm[256];
	unsigned char look;
	short int id;
	short int length;
	unsigned char *p;
	int i;	
	u_int32_t lookaddr;
	/* Read from FIFO until marker is found... */
	do
	{
		if (read(fifo,&look,1)<0)
		{
			look = -1;
			break;
		}
	} while (look!=FIFOMARK);
	/*
	 *	If good read... Read ID and Length 
	 *	then read into buffer the actual length of data
	 *	then read FINAL mark...
	 */
	
	if (look==FIFOMARK)
	{
		read(fifo,&id,INTSIZE);
		read(fifo,&length,INTSIZE);
		mvprintw(2,3,"ID=%3d  LENGTH=%3d",id,length);
		if (length<256)
			read(fifo,keycomm,length*INTSIZE);
		do
		
		{
			if (read(fifo,&look,1)<0)
			{
				look = -1;
				break;
			}
		} while (look!=FIFOMARK);
		fifoval=keycomm[0];
		if (look==FIFOMARK)
		{
			switch (id)
			{
			case 1:
				for (i=0;i<length;i++)
					dokeyin(keycomm[i]);
				break;
			case 4:
				cur_status_line = fifoval;
				break;
			case 5:
                  		rewrite_labels = 1;
				dispopt = fifoval;
				break;
			case 6:
				lookaddr = *(u_int32_t *)keycomm;
				p = (unsigned char *)keycomm;
				mvprintw(1,3,"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
				findaddr(lookaddr);
				break;
			}
		}
		else
			mvprintw(1,3,"INCORRECT PACKET FORMAT");
		refresh();
	}
}



void
   adjusttime (time_t * pt, int hrs, int mins)
   {
      struct tm tm;
      struct tm *ps;
      time_t v;
      int i, j;

      v = time (0);
      ps = localtime (&v);
      tm = *ps;
      if (hrs < tm.tm_hour - 1 || (hrs == tm.tm_hour - 1 && mins < tm.tm_min - 1))
      {
         tm.tm_mday++;
      }
      tm.tm_hour = hrs;
      tm.tm_min = mins;
      *pt = mktime (&tm);
/* Adjust to UTC */
   }

void
   processspecconfig ()
   {
      FILE *fp;
      static char w1[140], w2[140], w3[140], w4[140];
      int narg;
      struct in_addr naddr;

      if ((fp = fopen (specconfigfile, "r")))
      {
         themnum = 0;
         while ((fgets (tmpbuf, 256, fp)))
         {
            if (tmpbuf[0] != '#')
            {
               tmpbuf[strlen (tmpbuf) - 1] = 0;
               if ((narg = sscanf (tmpbuf, "%s %s %s %s", w1, w2, w3, w4))
                  >= 2)
               {
/* Config file Keywords -
                     warnmail
                     logfile
                     statsfile
                     fishstring
*/
                  if (!strncasecmp (w1, "warnmail", 8))
                     strncpy (userwarn, w2, 256);
                  else if (!strncasecmp (w1, "noautostatus", 12))
                     autostatus = FALSE;
                  else if (!strncasecmp (w1, "bridge", 6))
                     isbridge = TRUE;
                  else if (!strncasecmp (w1, "autostatus", 10))
                     autostatus = TRUE;
                  else if (!strncasecmp (w1, "noresolve", 9))
                     nonameresolve = TRUE;
                  else if (!strncasecmp (w1, "resolve", 7))
                     nonameresolve = FALSE;
                  else if (!strncasecmp (w1, "yellow", 6))
                     sYELLOWTIME = atoi (w2);
                  else if (!strncasecmp (w1, "red", 3))
                     sREDTIME = atoi (w2);
                  else if (!strncasecmp (w1, "green", 5))
                     sGREENTIME = atoi (w2);
                  else if (!strncasecmp (w1, "logfile", 7))
                     strncpy (speclogfile, w2, MAXFILENAME);
                  else if (!strncasecmp (w1, "timefmt", 7))
                     strncpy (tmstring, w2, 256);
                  else if (!strncasecmp (w1, "statsfile", 9))
                     strncpy (statsfile, w2, MAXFILENAME);
                  else if (!strncasecmp (w1, "netmask", 8))
                  {
                     forcemask = TRUE;
                     fmask = inet_addr (w2);
                  }
                  else if (!strncasecmp (w1, "inetaddr", 8))
                  {
                     forcelocal = TRUE;
                     flocal = inet_addr (w2);
                  }
                  else if (!strncasecmp (w1, "statsoption", 11))
                  {
                     if (!strncasecmp (w2, "append", 6))
                        statsappend = TRUE;
                     else if (!strncasecmp (w2, "date", 4))
                        statsappend = FALSE;
                  }
                  else if (!strncasecmp (w1, "logone", 9))
                  {
                     if (strlen(w2))
                     {
                        if ( inet_aton(w2,&naddr) )
                        {
                           logthem[themnum] = naddr.s_addr;
                           if (themnum<19)
                              themnum++;
                        }
                     }
                  }
                  else if (!strncasecmp (w1, "logremote", 9))
                  {
                     if (strlen(w2))
                        strncpy (nw_remname, w2,256 );
                     nw_logremote = TRUE;
                  }
                  else if (!strncasecmp (w1, "loglocal", 8))
                  {
                     if (strlen(w2))
                        strncpy (nw_locname, w2,256 );
                     nw_loglocal = TRUE;
                  }
                  else if (!strncasecmp (w1, "logindivbase", 12))
                  {
                     if (strlen(w2))
                        strncpy (nw_indivmain, w2,256 );
                  }
                  else if (!strncasecmp (w1, "logindiv", 8))
                  {
                     if (strlen(w2))
                        strncpy (nw_indivmain, w2,256 );
                     nw_logindiv = TRUE;
                  }
                  else if (!strncasecmp (w1, "logall", 6))
                  {
                     if (strlen(w2))
                        strncpy (nw_allname, w2,256 );
                     nw_logall = TRUE;
                  }
                  else if (!strncasecmp (w1, "playrate", 8))
                  {
                     if (!strncasecmp(w2,"second",6))
                        nw_simrate = SIMSEC;
                     else if (!strncasecmp(w2,"key",3))
					 {
                        nw_simrate = SIMSEC;
						simkeyrate = 0;
						simarr[3]=1;
         				simchange = TRUE;
					 }
                     else
                     {
                        simkeyrate = atoi(w2);
                        if (simkeyrate<=0)
						{
						   simarr[3]=1;
                           simkeyrate = 0;
						 }
						if (simkeyrate>2) simarr[6]=3;
						if (simkeyrate>1) simarr[5]=3;
						if (simkeyrate>0) simarr[4]=3;
                        nw_simrate = SIMSEC;
         				simchange = TRUE;
                     }
                  }
                  else if (!strncasecmp (w1, "playback", 8))
                  {
                     if (strlen(w2))
                        strncpy (nw_simfile, w2,256 );
                     nw_simulate = TRUE;
                     nw_simrate = SIMSEC;
                  }
                  else if (!strncasecmp (w1, "fishstring", 10))
                  {
                     strncpy (fishstring, &tmpbuf[11], 256);
                     fishstringlen = strlen (fishstring);

                  }
                  else if (!strncasecmp (w1, "reload", 6))
                  {
                     if (!strncasecmp (w2, "at", 2))
                     {
                        if (narg == 4)
                        {
                           reload_timer_sec = 60 * atoi (w4);
                           if (reload_timer_sec > 0)
                           {
                              sscanf (w3, "%2d:%2d", &rel_hours,
                                 &rel_mins);

                              adjusttime (&wakeup_reload, rel_hours,
                                 rel_mins);
                              wakeup_state = TRUE;
                           }
                        }
                     }
                     else
                     {
                        reload_timer_sec = 60 * atoi (w2);
                        if (reload_timer_sec > 0)
                        {
                           reload_timer_start = time (0);
                           reload_active = TRUE;
                        }
                     }

                  }


               }
            }

         }

         fclose (fp);
      }

   }


void
   handletimeout (int sig)
   {
      resolvetimeout = 10;
      timeresolv++;
/*
         * printf("Got TIMEOUT\n");  
*/
/* signal (SIGUSR1, handletimeout); */
   }

void
   handlesigpipe (int sig)
   {
      pid_t pipepid;
      int status;

      if (sendresolv)
      {
/* NETRESOLV has died... Why???? */
         pipepid = waitpid (child, &status, 0);
         if (pipepid == child)
         {
            if (WIFSIGNALED (status))
            {
               sprintf (&status_lines[11][3],
                  " NETRESOLV terminated with SIGNAL #%d --> NO INET NAMES",
                  WTERMSIG (status));
               cur_status_line = 11;
            }
         }
         noresolv = TRUE;  /* Turn off pipe communication */

      }
   }

void
   handlechild (int sig)
   {
      int status;
      pid_t killpid;

      killpid = wait (&status);
      if (killpid == child)
      {
         if (WIFEXITED (status))
         {
            sprintf (&status_lines[3][3],
               "NETRESOLV normal termination... EXIT #%d for %ld",
               WEXITSTATUS (status), killpid);
            cur_status_line = 3;

         }
         else if (WIFSIGNALED (status))
         {
            sprintf (&status_lines[3][3],
               "NETRESOLV Abnormal termination... signal #%d for %ld",
               WTERMSIG (status), killpid);
            cur_status_line = 3;
         }
         noresolv = TRUE;  /* Netresolv died.. so NO name resolution */
      }
      else if (killpid < 0)
      {
/* In the 2.2.x kernel... the EINTR appears
            to happen and the RESTART causes a REAL wait int
            the wait() call... it doesn't come out...

            This means that we have to IGNORE this type of call
            and we run the risk of a REAL signal which has a -1
            return for a REAL reason
*/
         if (errno != EINTR)
         {
            sprintf (&status_lines[3][3],
               "CHILD process termination (WAIT ERROR)... ERR=%d", errno);
            cur_status_line = 3;
            noresolv = TRUE; /* Just in case */
         }
      }

   }

void
   processres (int sig)
   {
      struct gotname one;
      int actnum;
      int st;
      int i, sz;
      static int inside = 0;
      sigset_t sigset, oldmask;
      int moreinfo;
      long oldflags;

      sigprocmask (0, NULL, &sigset);
      sigaddset (&sigset, sig);
      sigprocmask (SIG_BLOCK, &sigset, &oldmask);
      oldflags = fcntl (osocket[0], F_GETFL);
      fcntl (osocket[0], F_SETFL, FNDELAY);
      moreinfo = TRUE;
      while (moreinfo)
      {
         st = read (osocket[0], &one, sizeof (one));
         if (st < 0)
         {
            if (errno == EWOULDBLOCK)
               break;
            selprob = 88;
            errread++;
            break;
         }
         if (!sentclear && one.name[0])
         {
            strncpy (one.where, one.name, RESOLVE_MAX);
            one.where[RESOLVE_MAX - 1] = 0;
         }
         else if (one.where == (char *) 1 && !one.name[0])
            sentclear = FALSE;
         recresolv++;
         noresolv = FALSE;
      }
      fcntl (osocket[0], F_SETFL, oldflags);
      sigprocmask (SIG_SETMASK, &oldmask, NULL);
   }

void
   setupsignals ()
   {
      signal (SIGUSR1, handletimeout);
      signal (SIGUSR2, processres);
   }

void
   startnetresolv ()
   {
      struct resolvaddr one;

      one.pid = mypid;
      one.inetaddr = 0L;
      one.where = (char *) 1;
      write (msocket[1], &one, sizeof (one));
      sendresolv++;
      kill (child, SIGUSR1);
/* sentclear=FALSE; */
   }

void
   clearnetresolv ()
   {
      struct resolvaddr one;

      one.pid = mypid;
      one.inetaddr = 0L;
      one.where = (char *) 0;
      sentclear = TRUE;
      write (msocket[1], &one, sizeof (one));
      sendresolv++;
      kill (child, SIGUSR1);
   }

void
   mygethostbyaddr (char *where, unsigned char *p, int len, int proto)
   {
      struct resolvaddr one;
      u_int32_t *pi = (u_int32_t *) p;

      if (noresolv)
         return;
      if (nonameresolve)
         return;
      if (*pi == 0L)
         return;
      one.pid = mypid;
      one.inetaddr = *(u_int32_t *) p;
      one.where = where;
      write (msocket[1], &one, sizeof (one));
      sendresolv++;
      kill (child, SIGUSR1);
   }




void
   clearentry (HOSTINFO * current)
   {
      current->pktcntsend = current->pktcntrec = 0;
      current->intpktcntsend = current->intpktcntrec = 0;
      current->extpktcntsend = current->extpktcntrec = 0;
      current->sendbytes = current->recbytes = 0;
      current->intsendbytes = current->intrecbytes = 0;
      current->extsendbytes = current->extrecbytes = 0;
      current->timebytes = current->timelastbytes = 0;
      current->plog = 0;
      current->plogactive = 0;

   }

/*
   * FOR RELIABLE SIGNAL HANDLING --- make sure a restart of system calls is 
   * performed when signals interrupt 
*/
sigfunc signal (int signo, sigfunc func)
{
   struct sigaction act, oact;

   act.sa_handler = func;
   sigemptyset (&act.sa_mask);
   act.sa_flags = 0;
   if (signo != SIGALRM)
      act.sa_flags |= SA_RESTART;
   if (sigaction (signo, &act, &oact) < 0)
      return (SIG_ERR);
   return (oact.sa_handler);
}

/*
   * FOR SELECT System call SIGNAL HANDLING --- make sure there is NO 
   * restart of system calls when signals interrupt 
*/
sigfunc signal_intr (int signo, sigfunc func)
{
   struct sigaction act, oact;

   act.sa_handler = func;
   sigemptyset (&act.sa_mask);
   act.sa_flags = 0;
   if (sigaction (signo, &act, &oact) < 0)
      return (SIG_ERR);
   return (oact.sa_handler);
}

/*
   * Simple Control C and Hangup handler... to clean the screen 
*/
void
   intrhandle ()
   {
      alarm (0);
      signal_intr (SIGALRM, SIG_DFL);
      kill (child, SIGHUP);
      sleep (1);
      if (!noscreen)
         cleanup_curses ();

      printf
         ("Thank you for using NETWATCH..see http://www.slctech.org/~mackay/netwatch.html\n");
      if (speclog)
         fclose (fpspeclog);
      if (using_fifo)
      {
	      close(fifo);
	      unlink(fifoname);
      }
      if (nw_logremote && nw_fprem!=NULL)
         fclose(nw_fprem);
      if (nw_loglocal && nw_fploc!=NULL)
         fclose(nw_fploc);
      if (nw_logall && nw_fpall!=NULL)
         fclose(nw_fpall);
/*
         * Should this be rewritten to cooperate with other net tools? 
*/
      strcpy (oldifr.ifr_name, ethdevname);
      if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
      {
         perror ("Can't set flags: ");
         close (sd);
         gh (3);
         exit (4);
      }
      close (sd);
      gh (1);
      exit (0);

   }



/*
   * A Routine to Log the CURRENT (passed) Record to the log file which is
   * already open for use 
*/
void
   logcurr (HOSTINFO * c, FILE * fp)
   {
      static char tmphost[RESOLVE_MAX];

      fprintf (fp, "HOSTINFO=%p\n", c);
      hostent = gethostbyaddr ((char *) c->othaddr, 4, AF_INET);
      if (hostent)
         strncpy (tmphost, hostent->h_name, RESOLVE_MAX);
      else
         strcpy (tmphost, "<unresolved>");

      fprintf (fp, "HOST=%s     LAST ACCESS=%s", c->name, ctime (&(c->tstamp)));
      fprintf (fp, "IP Addr = %u.%u.%u.%u\n", c->addr[0], c->addr[1],
         c->addr[2], c->addr[3]);
      fprintf (fp, "Last Communication to %u.%u.%u.%u known as %s\n",
         c->othaddr[0], c->othaddr[1], c->othaddr[2], c->othaddr[3],
         tmphost);
      fprintf (fp, "with Protocol %s and Service %s\n", c->ip_pr,
         servicenm (c->servicename, c->port));

      fprintf (fp, "Packet Counts    Incoming      Outgoing\n");
      fprintf (fp, "    ALL          %8lu      %8lu\n", c->pktcntrec,
         c->pktcntsend);
      fprintf (fp, "   LOCAL         %8lu      %8lu\n", c->intpktcntrec,
         c->intpktcntsend);
      fprintf (fp, "  REMOTE         %8lu      %8lu\n", c->extpktcntrec,
         c->extpktcntsend);
      fprintf (fp, "\n BYTE Counts    Incoming      Outgoing\n");
      fprintf (fp, "    ALL          %8lu      %8lu\n", c->recbytes,
         c->sendbytes);
      fprintf (fp, "   LOCAL         %8lu      %8lu\n", c->intrecbytes,
         c->intsendbytes);
      fprintf (fp, "  REMOTE         %8lu      %8lu\n", c->extrecbytes,
         c->extsendbytes);
      fprintf (fp, "\n\n");

   }

void
   adjust (int *h, int *m)
   {
      int min = *m;
      int hour = *h;

      min--;
      if (min < 0)
      {
         hour--;
         if (hour < 0)
            hour = 23;
         min = 59;
      }
      *m = min;
      *h = hour;
   }

/*
   * Handle dumping stats to a file for use at a later time... 
*/

void
   gostats ()
   {
      HOSTINFO *current;
      FILE *fp;
      time_t here;
      static char tarr[80];
      struct tm *tm;
      static struct tm wtm;
      int smin, i;
      int hrs, mins;

      here = time (0);
      tm = localtime (&here);
      wtm = *tm;
      if (statsappend)
         strcpy (newstatsfile, statsfile);
      else
      {
         strftime (tarr, 80, tmstring, &wtm);
         sprintf (newstatsfile, "%s.%s", statsfile, tarr);
      }
      fp = fopen (newstatsfile, "a");
      if (fp == NULL)
         return;
      strcpy (tmpbuf, ctime (&here));
      fprintf (fp, "\nStatistics    from %s to %s\n", ctime (&starttime), tmpbuf);
      fprintf (fp, "\nLOCAL STATISTICS\n");
      current = lfirst->flink;
      fprintf (fp, "Init Current=%p Left first->link = %p\n", current,
         lfirst->flink);
      while (current != lfirst)
      {
         logcurr (current, fp);
         current = current->flink;
      }
      fprintf (fp, "\nREMOTE STATISTICS\n");
      current = rfirst->flink;
      while (current != rfirst)
      {
         logcurr (current, fp);
         current = current->flink;
      }
      fclose (fp);
      if (statsappend)
         strcpy (newstatsfile, statsfile);
      else
      {
         sprintf (newstatsfile, "%s.router.%s", statsfile, tarr);
      }
      fp = fopen (newstatsfile, "a");
      if (fp == NULL)
         return;
      fprintf (fp, "\nRouter Statistics (Last DAY)    from  %s\n\n", tmpbuf);
      fprintf (fp, "    Time      Router Throughput (kbits/sec)\n");
      smin = 1;
      hrs = wtm.tm_hour;
      mins = wtm.tm_min;
      for (i = cur_dayroute - 1; i != cur_dayroute && dayroute[i] != -1;
         i--, smin++)
      {
         adjust (&hrs, &mins);
         if (i < 0)
         {
            i = MAXDAYROUTE - 1;
            if (i == cur_dayroute || dayroute[i] == -1)
               break;
         }
         fprintf (fp, "  %02d:%02d        %10.2f\n", hrs, mins, dayroute[i]);
      }
      fclose (fp);
   }

void
   disphelp (int helppage, int xoff)
   {
      switch (helppage)
      {
         case 1:
            mvprintw (6, xoff + 10, "HELP WINDOW");
            mvprintw (8, xoff + 3, "Normal Mode Commands");
            mvprintw (10, xoff + 3, "<TAB>  - toggle REMOTE/LOCAL");
            mvprintw (11, xoff + 3, "         for keyboard control");
            mvprintw (12, xoff + 3, "<LEFT> - Go back ONE Option");
            mvprintw (13, xoff + 3, "<RIGHT>  Go forward ONE OPTION");
            mvprintw (14, xoff + 3, "<UP>   - Back ONE PAGE on");
            mvprintw (15, xoff + 3, "         CURRENT (REMOTE/LOCAL)");
            mvprintw (16, xoff + 3, "<DOWN> - Forward ONE PAGE on");
            mvprintw (17, xoff + 3, "         CURRENT (REMOTE/LOCAL)");
            mvprintw (18, xoff + 3, "<ESC>  Exit HELP MODE");
            mvprintw (19, xoff + 3, "or <F10>");
            mvprintw (20, xoff + 3, "or <END>    <ENTER> for MORE Help");
            break;
         case 2:
            mvprintw (6, xoff + 10, "HELP WINDOW");
            mvprintw (8, xoff + 3, "Special Mode Commands");
            mvprintw (10, xoff + 3, "c      - Clear Counters (Packets");
            mvprintw (11, xoff + 3, "         and Bytes) ");
            mvprintw (12, xoff + 3, "n      - NEW Host List (Restart)");
            mvprintw (13, xoff + 3, "w      - Enter WATCH Mode");
            mvprintw (14, xoff + 3, "         (See Watch Page");
            mvprintw (15, xoff + 3, "p      - Print to Log File");
            mvprintw (16, xoff + 3, "         (new file each print)");
            mvprintw (18, xoff + 3, "<ESC>  Exit HELP MODE");
            mvprintw (19, xoff + 3, "or <F10>");
            mvprintw (20, xoff + 3, "or <END>    <ENTER> for MORE Help");
            break;
         case 3:
            mvprintw (6, xoff + 10, "HELP WINDOW");
            mvprintw (8, xoff + 3, "Additional Commands");
            mvprintw (10, xoff + 3, "l      - Log stats to log file");
            mvprintw (11, xoff + 3, "b      - Toggle Blue Hosts ");
            mvprintw (12, xoff + 3, "          displayed or not");
            mvprintw (13, xoff + 3, "d      - Toggle DOMAIN Hosts");
            mvprintw (14, xoff + 3, "          service displayed");
            mvprintw (15, xoff + 3, "          or not");
            mvprintw (16, xoff + 3, "t      - TOP Mode toggle   ");
            mvprintw (17, xoff + 3, "f      - FREEZE SCREEN toggle");
            mvprintw (18, xoff + 3, "<ESC>  Exit HELP MODE");
            mvprintw (19, xoff + 3, "or <F10>");
            mvprintw (20, xoff + 3, "or <END>    <ENTER> for MORE Help");
            break;

      }
   }

void
   setupauxscr (int *xoff, int bigscreen)
   {
      int xst = 1;
      int xend;

      scrmid = MCOLS >> 1;
      xend = scrmid;
      if (localkey)
      {
         xst = scrmid + 1;
         xend = MCOLS - 1;
      }
      if (bigscreen)
      {
         xst = 1;
         xend = MCOLS - 1;
      }
      clrportion (4, xst, MLINES - 1, xend);
      mvhline (4, xst + 1, ACS_BLOCK, xend - xst - 2);
      mvhline (MLINES - 3, xst + 1, ACS_BLOCK, xend - xst - 2);
      mvvline (5, xst + 1, ACS_BLOCK, MLINES - 8);
      mvvline (5, xend - 2, ACS_BLOCK, MLINES - 8);
      *xoff = xst;
   }

#define MAXSTAT 6




void
   status_box (char header[], char mss[], int x, int y, int width)
   {
      int mess_len;
      int center;
      int mid;
      int numoflines = 3;
      int splitspot = 0;
      char *p[MAXSTAT];
      int i;
      int start;
      static char mess[512];
      char *pw = mess;

      strncpy (mess, mss, 512);
      mid = width >> 1;
      mess_len = strlen (pw);
      p[numoflines - 3] = pw;
      while (mess_len > width - 2 && numoflines < MAXSTAT + 1)
      {
         numoflines++;
         for (pw = pw + width - 2; *pw != ' ' && pw > p[numoflines - 4]; pw--);
         *pw = 0;
         pw++;
         p[numoflines - 3] = pw;
         mess_len = strlen (pw);
      }
      p[numoflines - 2] = NULL;

      clrportion (y, x, y + numoflines - 1, x + width - 1);
      mvhline (y, x, ACS_BLOCK, width);
      if (header && header[0])
      {
         center = strlen (header) >> 1;
         start = mid - center;
         if (start < 0)
            start = 0;
         attron (col3);
         mvprintw (y, x + start, "%s", header);
         attron (col4);

      }
      mvhline (y + numoflines - 1, x, ACS_BLOCK, width);
      mvvline (y, x, ACS_BLOCK, numoflines);
      mvvline (y, x + width - 1, ACS_BLOCK, numoflines);
      for (i = 0; p[i]; i++)
      {
         mess_len = strlen (p[i]);
         center = mess_len >> 1;
         start = mid - center;
         mvprintw (y + i + 1, x + start, "%s", p[i]);
      }

   }

void
   debug_packet (unsigned char *s)
   {
      static char debugstr[1024];
      static char hexasc[10];
      int i;
      unsigned char key;

      debugstr[0] = 0;
      for (i = 0; i < 60; i++)
      {
         key = *s;
         s++;
/*      if (isalnum(key) || isspace(key) ||ispunct(key))
            {
            hexasc[0]=key;
            hexasc[1]=0;
            }
            else */
         {
            sprintf (hexasc, " %02X ", key);
         }
         strcat (debugstr, hexasc);
      }
      status_box ("PPP DEBUG", debugstr, 10, 4, 40);
      while (getch () == ERR);
   }




void
   setuphelp ()
   {
      int xoff = 1;
      setupauxscr (&xoff, SMALLSCREEN);
      disphelp (helppage, xoff);
   }

void
   setupwatch (int bigscreen)
   {
      int xoff = 1;

      setupauxscr (&xoff, bigscreen);
      if (!bigscreen)
      {
         mvprintw (6, xoff + 10, "WATCH WINDOW");
         if (!disprouterstats)
         {
            mvprintw (8, xoff + 3, "Special Commands");
            mvprintw (10, xoff + 3, "s   - select host for trace");
            mvprintw (11, xoff + 3, "       Up/Down   Left/Right");
            mvprintw (12, xoff + 3, "      <new host> <pkt. spot>");
            mvprintw (13, xoff + 3, "r   - examine router stats");
            mvprintw (14, xoff + 3, "<ESC>  Exit WATCH MODE");
            mvprintw (15, xoff + 3, "or <F10>");
            mvprintw (16, xoff + 3, "or <END>");
         }
      }
   }

void
   indepscreen ()
   {
      curskeyspot = MCOLS - 12;
      curskeyval = MCOLS - 5;
      cursllockout = MCOLS - 18;
      cursrlockout = MCOLS - 15;
      curslines = MCOLS - 10;
      curshosttrim = MCOLS / 2 - 17;
      cursproto = curshosttrim - 7;
      cursdest = curshosttrim - 2;

   }

void
   winchange ()
   {
      static struct winsize size;

      if (ioctl (0, TIOCGWINSZ, (char *) &size) >= 0)
      {
         MLINES = size.ws_row;
         MCOLS = size.ws_col;
         wresize (stdscr, MLINES, MCOLS);
         indepscreen ();
         clrscr ();
         if (watch)
            setupwatch (SMALLSCREEN);
         if (help)
            setuphelp ();
         rewrite_labels = TRUE;
         refreshrem = TRUE;
         refreshloc = TRUE;
      }
   }

clock_t putoneeth( FILE *fp, char *buf, int *plen)
{
   int st;
   short nlen;
   short len;
   unsigned short simcheck;
   clock_t clk;
   long begrec;
/* Read ETH header and calculate the length... then read the rest */
/* You assume that you are at the END of the current record
      and you have to go back... since lengths are encoded at
      front AND back (just for this)... you can seek back and
      read the length... then seek back the length - sizeof(length)*2
      - sizeof(clk)... then read it to REVERSE it...
      THEN seek back to  the start of this record again so  you can
      either go forwards or backwards for processing
      >> must make magna work with this???
*/
   fseek(fp,-sizeof(simcheck)-sizeof(nlen),SEEK_CUR);
   st = fread(&nlen,1,sizeof(short),fp);
   len = ntohs(nlen);
   fseek(fp,-len-sizeof(nlen)*2-sizeof(clk),SEEK_CUR);
   begrec = ftell(fp);
   st = fread(&clk,1,sizeof(clk),fp);
   st = fread(&nlen,1,sizeof(short),fp);
   len = ntohs(nlen);
   if (st<sizeof(short))
      return(-1);
   st = fread(buf,1,len,fp);
   if (st<len)
      return(-1);
   st = fread(&nlen,1,sizeof(short),fp);
   st = fread(&simcheck,1,sizeof(simcheck),fp);
   if (simcheck!=simmagic)
   {
      mvprintw(MLINES-1,10,"Illegal File format - no MAGIC val");
      return(-1);
   }
   fseek(fp,begrec,SEEK_SET);
   *plen = len;
   return(clk);
}

clock_t getoneeth( FILE *fp, char *buf, int *plen)
{
   int st;
   short nlen;
   short len;
   unsigned short simcheck;
   clock_t clk;
/* Read ETH header and calculate the length... then read the rest */

   st = fread(&clk,1,sizeof(clk),fp);
   st = fread(&nlen,1,sizeof(short),fp);
   len = ntohs(nlen);
   if (st<sizeof(short))
      return(-1);
   st = fread(buf,1,len,fp);
   if (st<len)
      return(-1);
   st = fread(&nlen,1,sizeof(short),fp);
   st = fread(&simcheck,1,sizeof(simcheck),fp);
   if (simcheck!=simmagic)
   {
      mvprintw(MLINES-1,10,"Illegal File format - no MAGIC val");
      return(-1);
   }
   *plen = len;
   return(clk);
}

/*
   *  Simulate ethernet reads from file AND read the keyboard as
   *  required
*/
int sim_process()
{
   int n;
   int simdone=FALSE;
   fd_set rset;
/* long int cset, eset; */
   long int rsset, csset;
   int maxfd=1;
   int tfd = 0;
   struct timeval seltime;
   int i;
   int st;
   int length;
   unsigned short simcheck;
   time_t chactstart;
   clock_t loldrealoff;  /* temp clock ticks */
   clock_t thistime;  /* NOW... */
   clock_t sysclk;  /* Start of simulation... */
   clock_t adjoffs;  /* Adjusted offset for slowing down simulation */
/* Some options... if the SIMKEY option is chosen...
      simulate only when "." key is hit
      if the SIMSEC option is chosen...
      perform a timeout on SELECT and then
      read "simkeyrate" ethernet records

      In both cases, the simulation file must be opened.
*/
   if (strlen(nw_simfile))
   {
      simfp = fopen(nw_simfile,"r");
      if (simfp==NULL)
      {
         printf("SIM FILE:%s did not open\n",nw_simfile);
         return(1);
      }
      sysclk = times(&dumbtime);
      if (nw_simrate==SIMSEC)
	  	loff = sysclk;
	  else
	    loff=0;
      st = fread(&actstart,1,sizeof(actstart),simfp);
   	  chactstart = actstart;
   	  mactstart = (double)actstart;
      st = fread(&simcheck,1,sizeof(simcheck),simfp);
      if (simcheck != simmagic)
      {
         printf("SIM FILE is OLD or incorrect format\n");
         return(1);
      }
      if (simkeyrate && nw_simrate==SIMSEC)
	      fileclk = getoneeth(simfp,buf,&length);
      else
		fileclk=0;
      lrealoff = 0;
      adjoffs = fileclk;
      selprob = 0;
      thistime = times(&dumbtime);
      while (TRUE)
      {
         FD_ZERO(&rset);
         FD_SET(0,&rset);
	 if (using_fifo)
	 {
		 FD_SET(fifo,&rset);
		 maxfd = fifo+1;
         }
/*      			cset = eset = rset; */
         if (nw_simrate==SIMSEC)
         {
            selprob = selprob + 1;
            seltime.tv_sec = 0;
            seltime.tv_usec = 1000;
            if ((selcode =	select (maxfd, &rset, NULL, NULL,
               &seltime)) > 0)
            {
               if (FD_ISSET (tfd, (fd_set *) & rset))
               {
                  if (dokeyin (0) < 0)
		  {  
		     fclose(simfp);
                     return (0);
		  }
               }
	       else if (using_fifo && FD_ISSET (fifo, (fd_set *) & rset))
	       {
			do_fifo();
	       }
            }
            else
            {
	      if (simkeyrate>0)
  	      {
                   loff = offsclk;
		   lasttime = thistime;
		   thistime = times(&dumbtime);
                   offsclk = lrealoff + ((thistime - lasttime) <<(simkeyrate-1));
		   loldrealoff = lrealoff;
		   lrealoff = offsclk;
               /* refresh(); */
               if (!simdone)
               {
                  while (adjoffs<=offsclk)
                  {
                     ethcnt++;
/*				   mvprintw(23,2,"lrealoff=%lu  offsclk=%lu delta=%lu",lrealoff,offsclk,thistime -lasttime);  */
                     handle_frame(buf,length,NULL,TRUE,1);
                     fileclk = getoneeth(simfp,buf,&length);
                     if (fileclk == -1)
                     {
                        adjoffs=offsclk + 2000;
                        simdone = TRUE;
                     }
                     else
                     {
                        adjoffs = fileclk ;
/* only works for ETH logs not PPP??? */  }
                  }
/*				   mvprintw(23,2,"CHACTSTART=%lu  MACTSTART=%lf OFFS=%lu",chactstart,mactstart,offsclk); */
                  /* mactstart = mactstart + (double)((offsclk-loff)<<(simkeyrate-1))/CLK_TCK; */
                  mactstart = mactstart + (double)(offsclk-loldrealoff)/_SC_CLK_TCK;
					   /* lrealoff = fileclk; */
                  actstart = (time_t)((mactstart));
               }
	      }
	      else if (simkeyrate<0)
  	      {
                   loff = offsclk;
		   lasttime = thistime;
		   thistime = times(&dumbtime);
                   offsclk = lrealoff - ((thistime - lasttime) <<(simkeyrate-1));
		   loldrealoff = lrealoff;
		   lrealoff = offsclk;
               /* refresh(); */
               if (!simdone)
               {
                  while (adjoffs>=offsclk)
                  {
                     ethcnt--;
/*				   mvprintw(23,2,"lrealoff=%lu  offsclk=%lu delta=%lu",lrealoff,offsclk,thistime -lasttime);  */
                     handle_frame(buf,length,NULL,TRUE,-1);
                     fileclk = putoneeth(simfp,buf,&length);
                     if (fileclk == -1)
                     {
                        adjoffs=offsclk - 2000;
                        simdone = TRUE;
                     }
                     else
                     {
                        adjoffs = fileclk ;
/* only works for ETH logs not PPP??? */  }
                  }
/*				   mvprintw(23,2,"CHACTSTART=%lu  MACTSTART=%lf OFFS=%lu",chactstart,mactstart,offsclk); */
                  /* mactstart = mactstart + (double)((offsclk-loff)<<(simkeyrate-1))/CLK_TCK; */
                  mactstart = mactstart + (double)(offsclk-loldrealoff)/_SC_CLK_TCK;
					   /* lrealoff = fileclk; */
                  actstart = (time_t)((mactstart));
               }
	      }
            }
         }
         else  /* All is read from keyboard.... */
         {
	    if (using_fifo)
            {
               if ((selcode =	select (maxfd, &rset, NULL, NULL,NULL)) > 0)
               {
               		if (FD_ISSET (tfd, (fd_set *) & rset))
               		{
                  		if (dokeyin (0) < 0)
		  		{  
		     			fclose(simfp);
                     			return (0);
		  		}
               		}
	       		else if (FD_ISSET (fifo, (fd_set *) & rset))
	       		{
				do_fifo();
	       		}
            	}
            }
	    else
            {
	            if (dokeyin(0) < 0)
        	    {
               		fclose(simfp);
               		return(0);
            	    }
	    }
				   /* mvprintw(23,2,"ACTSTART=%lu  MACTSTART=%lf OFFS=%lu",actstart,mactstart,loff);  */
				refresh();
            keycnt++;
         }

      }


   }


}

/*
   * Use SELECT system call to read in characters and process OR read in the 
   * Ethernet Buffer... 
*/
int
   process ()
   {
      static char dumbuf[80];
      char dum;
      int n;
      long int rset, cset, eset;
      long int rsset, csset;
      int maxfd;
      int tfd = 0;
      struct timeval seltime;

      starttime = time(0);
      sclk = times(&dumbtime);
      rsset = 0;
      rset = 1 << sd;
      if (!noscreen)
      {
         rset |= 1;
         rsset = 1;
      }
/*
         * FAST METHOD of Setting FD 0 and FD SD
         * bits (nokeys will disable keyin)
*/
/*
         * FD_SET(sd, &rset); FD_SET(tfd, &rset);
*/
      cset = eset = rset;
      csset = rsset;
      maxfd = sd + 1;
	 if (using_fifo)
	 {
		 FD_SET(fifo,(fd_set *)&rset);
      		 cset = eset = rset;
		 maxfd = fifo+1;
         }
/*
         * printf("SD=%d\n  CSET=%x  MAXFD=%d\n",sd,cset,maxfd); 
*/
      while (TRUE)
      {
         rset = cset;
         eset = rset;
         selprob = 1;
         seltime.tv_sec = 1;
         seltime.tv_usec = 0;
         if (noscreen)
         {

            if (!sentclear && doeth () < 0)
               return (2);
            ethcnt++;
         }
         else
         {
/*
               * printf("** SD=%d\n  CSET=%x  MAXFD=%d\n",sd,cset,maxfd); 
*/
            if (
               (selcode =
               select (maxfd, (fd_set *) & rset, NULL, (fd_set *) & eset,
               &seltime)) <= 0)
            {
               if (errno == EINTR)
               {
                  selprob = 89;
                  continue;
               }
               perror ("SELECT");
               return (1);
            }
            if (!eset && !rset)
            {
/*
                  * Not possible...
*/
               continue;
            }
            if (eset)
            {
               selprob = 55;
               if (!noscreen)
               {
                  if (FD_ISSET (tfd, (fd_set *) & eset))
                  {
                     read (tfd, &dum, 1);
                     keycnt++;
                  }
               }
               if (FD_ISSET (sd, (fd_set *) & eset))
               {
                  n = read (sd, dumbuf, 80);
                  ethcnt++;
               }
            }
            selprob = 0;
            if (!noscreen)
            {
               if (FD_ISSET (tfd, (fd_set *) & rset))
               {
                  selprob = 3;
                  if (dokeyin (0) < 0)
                     return (0);

                  keycnt++;
               }
	       else if (using_fifo && FD_ISSET (fifo, (fd_set *) & rset))
	       {
			do_fifo();
	       }
            }
            if (FD_ISSET (sd, (fd_set *) & rset))
            {
               selprob = 4;
               if (!sentclear && doeth () < 0)
                  return (2);
               if (!sentclear)
                  ethcnt++;
            }
         }
      }
   }

void
   setupstatus ()
   {
      int i;
      int workit = STATUSSIZE * MAXSTATUS;

      for (i = 0; i < MAXDAYROUTE; i++)
         dayroute[i] = -1.0;
      rdelta = 60;
      memset (&status_lines[0][0], '~', workit);
      for (i = 0; i < MAXSTATUS; i++)
      {
         status_lines[i][MCOLS] = 0;
      }
      sprintf (&status_lines[1][3], " < NO NetBus attacks found to date > ");
      sprintf (&status_lines[2][3],
         " < NO Back Orifice attacks found to date > ");
      sprintf (&status_lines[3][3], " < NO BAD MAC Addresses seen to date > ");
      sprintf (&status_lines[11][3],
         " WARNING %s VIA E-MAIL on NetBus or B.O. Attacks ", userwarn);
   }

u_int32_t localifaddr;

int
   main (int argc, char *argv[])
   {
	struct stat tstat;
	int st;
      {    /*
            * Compound statement to make initializers 
            * vanish after init. 
*/
         int op;
         long int mask;
         u_int32_t *p;
#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
            int devindex;
         struct sockaddr_ll workll;
#endif
         starttime = time (0);
         gh (0);
         for (op = 0; op < MAGNAMAX; op++)
            magna[op].len = -1;
         magnamatch[0] = 0;
         strcpy (progtitle, "NETWATCH Program ");
         strcat (progtitle, version);
         strcat (progtitle, iv);
         pipe (msocket);
         pipe (osocket);
         mypid = getpid ();
         setupsignals ();
         if ((child = fork ()) == 0)
         {    /*
               * CHILD 
*/
            close (0);
            signal (SIGUSR1, SIG_DFL);
            signal (SIGUSR2, SIG_DFL);
            signal (SIGALRM, SIG_DFL);
            dup2 (msocket[0], 0);
            close (msocket[0]);
            close (1);
            dup2 (osocket[1], 1);
            close (osocket[1]);
            execlp ("netresolv", "netresolv", NULL);
            perror ("exec netresolv");
            exit (1);
         }
         close (msocket[0]);
         close (osocket[1]);
         signal (SIGCHLD, handlechild);
         signal (SIGPIPE, handlesigpipe);

         rewrite_labels = 1;
         lfirst = &ldummy;  /*
            * The dummy record header for linked list 
*/
         lfirst->flink = lfirst;
         lfirst->blink = lfirst;
/*
            * lfirst->disprow = localrow; 
*/

         rfirst = &rdummy;  /*
            * The dummy record header for linked list 
*/
         rfirst->flink = rfirst;
         rfirst->blink = rfirst;
/*
            * rfirst->disprow = remoterow; 
*/
         services ();  /*
            * default labels for these services 
*/

         help_flag = 0;  /*
            * No help unless asked for 
*/
         redraw_screen = 0;  /*
            * No redraw unless asked for 
*/
         noscreen = 0;
         processspecconfig ();
         while ((op = getopt (argc, argv, "H:R:L:S:bfzi:m:ns:l:hu:tc:e:")) != EOF)
         {
            switch (op)
            {
               case 'b':  /*
                     * TRANSPARENT Bridge flag... actually 
                     * causes every other packet to be ignored
                     * since comes in pairs in Kernel 
*/
                  isbridge = TRUE;
                  break;
	       case 'f':
		  using_fifo=TRUE;
		  break;
               case 'n':  /*
                     * No Name resolution (IP address only) 
*/
                  noresolv = TRUE;
                  break;
               case 'H':
                  logthem[themnum] = inet_addr(optarg);
                  if (themnum<MAXTHEM-1)
                     themnum++;
                  break;
               case 'i':  /*
                     * Force INET Setting (Override def.) 
*/
                  forcelocal = TRUE;
                  flocal = inet_addr (optarg);
                  break;
               case 'm':  /*
                     * Force NETMASK Setting (Override def.) 
*/
                  forcemask = TRUE;
                  fmask = inet_addr (optarg);
                  break;
               case 'z':  /*
                     * No screen display 
*/
                  noscreen = TRUE;
                  break;
               case 'l':  /*
                     * Log file specified 
*/
                  //strncpy (log, optarg, MAXFILENAME);
                  break;
               case 's':  /*
                     * Special Log file specified 
*/
                  strncpy (speclogfile, optarg, MAXFILENAME);
                  break;
               case 'c':
                  strncpy (configfile, optarg, MAXFILENAME);
                  newconfig = TRUE;
                  break;
               case 'u':
                  strncpy (userwarn, optarg, 256);
                  break;
               case 'e':
                  strncpy (ethdevname, optarg, 64);
                  isethdev = TRUE;
                  if (!strncmp (ethdevname, "ppp", 3))
                     isethdev = FALSE;
                  newethname = TRUE;
                  break;
               case 't':
                  topflag = TRUE;
                  break;
               case 'L':   /* LOG MODE */
                  switch(optarg[0])
                  {
                     case 'a':   /* Log all packets */
                        nw_logall = TRUE;
                        break;
                     case 'l':   /* Log LOCAL traffic only */
                        nw_loglocal = TRUE;
                        break;
                     case 'r':   /* Log Remote traffic only */
                        nw_logremote = TRUE;
                        break;
                     case 's':   /* Log individual traffic */
                        nw_logselect = TRUE;
                        break;
                     case 'i':   /* Log individual traffic */
                        nw_logindiv = TRUE;
                        break;
                  }
                  break;
               case 'S':   /*   Simulation File - Sim mode   */
                  strncpy(nw_simfile,optarg,256);
                  nw_simulate = TRUE;
                  nw_simrate = SIMSEC;
                  simkeyrate = 0;
				  simarr[3] = 1;
				  simchange=TRUE;
                  break;
               case 'R':  /* Simulation Option -- Key or Number/sec */
                  if (!strncasecmp(optarg,"key",3))
                  {
                     nw_simrate = SIMSEC;
                     simkeyrate = 0;
				     simarr[3] = 1;
				     simchange=TRUE;
                  }
                  else
                  {
                     simkeyrate = atoi(optarg);
                     nw_simrate = SIMSEC;
                        if (simkeyrate<=0)
						{
						   simarr[3]=1;
                           simkeyrate = 0;
						 }
						if (simkeyrate>2) simarr[6]=3;
						if (simkeyrate>1) simarr[5]=3;
						if (simkeyrate>0) simarr[4]=3;
						simchange=TRUE;
                  }
                  break;

               case ':':
                           fprintf (stderr, "Missing Parameter\n\n");
               case 'h':
               default:
                  usage (argv[0]);
                  break;
            }
         }
         processinetrc (netmask, localaddr, &ethok);
         if (!ethok)
         {
            printf ("NO %s Interface to work on!!\n", ethdevname);
            gh (3);
            exit (1);
         }
         if (nw_simulate)
         {
            strcpy (progtitle, "NETWATCH Simulator ");
            strcat (progtitle, version);
         }

/*
            * printf("NETMASK=%u.%u.%u.%u    LOCALADDR=%u.%u.%u.%u\n",
            * netmask[0],netmask[1],netmask[2],netmask[3],
            * localaddr[0],localaddr[1],localaddr[2],localaddr[3]); getchar(); 
*/
/*
            * INIT ALARMFUCTION: Alarm triggers update of the display 
*/

         if (signal_intr (SIGINT, intrhandle) == SIG_ERR)
         {
            perror ("INT Signal error: ");
            gh (3);
            exit (5);
         }
         if (signal_intr (SIGHUP, intrhandle) == SIG_ERR)
         {
            perror ("HUP Signal error: ");
            gh (3);
            exit (5);
         }
         if (!noscreen)
         {
            if (signal_intr (SIGALRM, dispdata) == SIG_ERR)
            {
               perror ("ALRM Signal error: ");
               gh (3);
               exit (5);
            }
            if (signal_intr (SIGWINCH, winchange) == SIG_ERR)
            {
               perror ("ALRM Signal error: ");
               gh (3);
               exit (5);
            }
         }
/*
            * OPEN SOCKET 
*/
         if (!nw_simulate)
         {
#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
               if ((sd = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
#else
            if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
#endif
            {
               perror ("Can't get socket: ");
               gh (3);
               exit (1);
            }
/*
               * SET PROMISC 
*/

            strcpy (oldifr.ifr_name, ethdevname);
            if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
            {
               perror ("Can't get flags: ");
               close (sd);
               gh (3);
               exit (2);
            }
#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
/* strcpy (oldifr.ifr_name, ethdevname);
               if (ioctl (sd, SIOCGIFINDEX, &oldifr) < 0)
               {
               perror ("Can't get IFINDEX: ");
               close (sd);
               gh (3);
               exit (2);
               }
               devindex = oldifr.ifr_ifindex;
               workll.sll_family = PF_PACKET;
               workll.sll_ifindex = devindex;
               if (bind(sd, (struct sockaddr *)&workll, sizeof(struct sockaddr_ll))!=0)
               {
               perror("BIND PACKET to DEVICE");
               close(sd);
               gh(3);
               exit(2);
               }
*/
#endif
            if (oldifr.ifr_flags | IFF_POINTOPOINT)
            {
               struct sockaddr_in *tmp;
               struct ifreq tif;
               strcpy (tif.ifr_name, ethdevname);
               if (ioctl (sd, SIOCGIFADDR, &tif) < 0)
               {
                  perror ("I/F");
               }
               tmp = (struct sockaddr_in *) &tif.ifr_addr;
               memcpy (localaddr, &(tmp->sin_addr.s_addr), sizeof (localaddr));
               if (ioctl (sd, SIOCGIFNETMASK, &tif) < 0)
               {
                  perror ("I/F");
               }
               tmp = (struct sockaddr_in *) &tif.ifr_addr;
               memcpy (netmask, &(tmp->sin_addr.s_addr), sizeof (netmask));
            }
         }
         if (forcelocal)
         {
            p = (u_int32_t *) & localaddr[0];
            *p = flocal;
         }
         if (forcemask)
         {
            p = (u_int32_t *) & netmask[0];
            *p = fmask;
         }


/*
            printf("NETMASK=%u.%u.%u.%u    LOCALADDR=%u.%u.%u.%u\n",
            netmask[0],netmask[1],netmask[2],netmask[3],
            localaddr[0],localaddr[1],localaddr[2],localaddr[3]); getchar(); 
*/
/*
            * Should this be rewritten to cooperate with other net tools? 
*/
         if (!nw_simulate)
         {
            ifr = oldifr;
            ifr.ifr_flags |= IFF_PROMISC;
            strcpy (ifr.ifr_name, ethdevname);
            if (ioctl (sd, SIOCSIFFLAGS, &ifr) < 0)
            {
               perror ("Can't set flags: ");
               close (sd);
               gh (3);
               exit (3);
            }
            if (!noscreen)
               fcntl (sd, F_SETFL, FNDELAY);
/*
               * No delay... although
               * waiting at SELECT!
*/
         }
      }    
      
      /*
       * Make the FIFO... if necessary...
       * 
       */
       if (using_fifo)
       {
       		st = stat(fifoname,&tstat);
       		if (!st && !tstat.st_mode|S_IFIFO)
		{
			unlink(fifoname);
			fifo = mkfifo(fifoname,S_IRUSR|S_IWUSR);
			if (fifo) using_fifo = FALSE;
		}
       		else if (st)
		{
			fifo = mkfifo(fifoname,S_IRUSR|S_IWUSR);
			if (fifo) using_fifo = FALSE;
		}
       }
       if (using_fifo)
       {
		fifo = open(fifoname,O_RDWR);
		if (fifo<=0)
			using_fifo = FALSE;
       }
      /*
       * END OF INITIALISATION
       */
      speclog = FALSE;
      sprintf (buf, "%s.%03d", speclogfile, speclogext);
      fpspeclog = fopen (buf, "w");
      if (fpspeclog != NULL)
         speclog = TRUE;

      if (!noscreen)
      {
/*
            * init_curses ();
*//*
            * initialize the screen
*/
         initscr ();
         cbreak ();
         noecho ();
         nodelay (stdscr, TRUE);
         nonl ();
         keypad (stdscr, TRUE);
         intrflush (stdscr, FALSE);
         getmaxyx (stdscr, MLINES, MCOLS);
         indepscreen ();
/*
            * if (has_colors ()) 
*/
         {
            colour = TRUE;
            start_color ();
            init_pair (6, COLOR_BLACK, COLOR_CYAN);
            init_pair (5, COLOR_BLACK, COLOR_MAGENTA);
            init_pair (4, COLOR_WHITE, COLOR_BLUE);
            init_pair (1, COLOR_WHITE, COLOR_RED);
            init_pair (2, COLOR_BLACK, COLOR_YELLOW);
            init_pair (3, COLOR_BLACK, COLOR_GREEN);
            col1 = COLOR_PAIR (1);
            col2 = COLOR_PAIR (2);
            col3 = COLOR_PAIR (3);
            col4 = COLOR_PAIR (4);
            col5 = COLOR_PAIR (5);
            col6 = COLOR_PAIR (6);
         }
/*
            * else { colour = FALSE; col1 = A_BLINK; col2 = A_REVERSE; col3 = A_BOLD;
            * col4 = A_NORMAL;
            * 
            * } 
*/
         clrscr ();
/*
            * clear the screen
*/
         alarm (1);
/*
            * first screen update in about a second
*/
         setupstatus ();
      }
      if (nw_simulate)
      {
         simchange = TRUE;
         sim_process();
      }
      else
         process ();

/*
         * TERMINATE 
*/
      if (nw_logremote && nw_fprem!=NULL)
         fclose(nw_fprem);
      if (nw_loglocal && nw_fploc!=NULL)
         fclose(nw_fploc);
      if (nw_logall && nw_fpall!=NULL)
         fclose(nw_fpall);
/* Pray for all open files to close on exit???  or walk through
         and close properly... */
      alarm (0);
      signal_intr (SIGALRM, SIG_DFL);
      kill (child, SIGHUP);
      sleep (1);
      if (!noscreen)
         cleanup_curses ();
      printf
         ("Thank you for using NETWATCH..see http://www.slctech.org/~mackay/netwatch.html\n");
      if (speclog)
         fclose (fpspeclog);
      if (using_fifo)
      {
	      close(fifo);
	      unlink(fifoname);
      }
/*
         * Should this be rewritten to cooperate with other net tools? 
*/
      if (!nw_simulate)
      {
         strcpy (oldifr.ifr_name, ethdevname);
         if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
         {
            perror ("Can't set flags: ");
            close (sd);
            gh (3);
            exit (4);
         }
         close (sd);
      }
      gh (1);
      exit (0);
   }


void
   handle_other (unsigned char *buf, int length)
   {

/*
         * frame_protocol is global 
*/
      if (frame_protocol < 1501)
      {    /*
            * if IEEE 802.3 packet instead of 
            * Ethernet packet (per RFC 1700) 
*/
//         if ((short int) buf[14] <= SN_MAX_SAP)
//         {
//            sap_count[(short int) buf[14]]++; /*
//               * count 802.2 SAP number 
//*/
//         }
         regis.new_ethernet_count++;
      }
/*
         * if IEEE 802.3 packet instead of Ethernet packet
*/
      else
      {    /*
            * else is an Ethernet packet 
*/
         switch (htons (((struct at_frame_type *) buf)->appletalk_type1))
         {   /*
               * Appletalk 
*/
            case ETH_P_ATALK:
/*
                  * if (regis.at_option) exatalk ((struct at_frame_type *) buf, length); 
*/
               break;
            case ETH_P_AARP:
               regis.aarp++;
               break;
            default:
               break;
         }
      }    /*
         * else is an Ethernet packet 
*/
   }

void
   makeaddr (unsigned char naddr[], char ascii[])
   {
      sprintf (ascii, "%u.%u.%u.%u        ", naddr[0], naddr[1], naddr[2],
         naddr[3]);
      ascii[15] = 0;
      return;
   }

int
   tlocal (u_int32_t * addr)
   {
      static unsigned char lhost[] = {  127, 0, 0, 1  };
      u_int32_t *k = (u_int32_t *) netmask;
      u_int32_t reslocal, restest;
      if (*addr == *(u_int32_t *) lhost)
         return (TRUE);
      restest = *addr & *k;
      reslocal = *(u_int32_t *) localaddr & *k;
      return (restest == reslocal);
   }

HOSTINFO *
   searchforinsertion (u_int32_t key, HOSTINFO * first)
   {
      HOSTINFO *current;
      current = first->flink;
      while (current != first
         && key <
         (u_int32_t) ntohl (*(u_int32_t *) current->addr)) current =
         current->flink;
      return(current);
   }


void findaddr( u_int32_t lookaddr)
{
	HOSTINFO *current;
	int ii;

	lookaddr = ntohl(lookaddr);
	searchaddr = lookaddr;
	if (tlocal(&lookaddr))
	{
		current = searchforinsertion(lookaddr,lfirst);
                if ((u_int32_t) ntohl (*(u_int32_t *) current->addr)!= lookaddr)
		{
			mvprintw(2,20,"DID NOT FIND LOCAL");
			return;
		}
		localkey = TRUE;
		movemagnakeyloc = TRUE;
	}
	else
	{
		current = searchforinsertion(lookaddr,rfirst);
                if ((u_int32_t) ntohl (*(u_int32_t *) current->addr)!= lookaddr)
		{
			mvprintw(2,20,"DID NOT FIND REMOTE");
			return;
		}
		localkey = FALSE;
		movemagnakeyrem = TRUE;

	}
	refreshloc = TRUE;
	refreshrem = TRUE;
	watch = TRUE;
	selecthost = TRUE;
	selectside = localkey;
	selectchange = TRUE;
	numselect = 0;
        for (ii = 0; ii < MAGNAMAX; ii++)
              magna[ii].len = -1;
        magnacnt = 0;
        magnaphys = 0;
        magnafirst = TRUE;
        magnacomhost = NULL;
}

static unsigned char fillmac[] = {  0, 0, 0, 0, 0, 0  };
static FILE *fish = NULL;
static char fishname[] = "/root/.fishingboat";
static int fishlen = 0;
static char *fishp;
static int flen;
static char fishbuf[256];
static int fishtype;

void
   fixstr (char *s)
   {
      int done = FALSE;

      while (!done)
      {
         if (isalnum (*s) || isspace (*s) || ispunct (*s))
            s++;
         else
         {
            *s = 0;
            done = TRUE;
         }
      }
   }

void
   sip (char *dest, char *source, char endkey, int max)
   {
      int i = 0;
      char *orig = dest;
/*
         * fprintf(fish,"SIP=DEST=%s==SRC=%s==ENDKEY=%d==MAX=%d\n",dest,source,endkey,max); 
*/

      while (*source != endkey && i < max)
      {
         *dest = *source;
         dest++;
         source++;
         i++;
      }
      *dest = 0;
      fixstr (orig);
   }

char *
   memstr (char *source, char *find, int len, int max)
   {
      int i;
      int maxchk;

/*
         * fprintf(fish,"MEMSTR=SRC=%s FIND=%s LEN=%d
         * MAX=%d\n",source,find,len,max);        
*/
      maxchk = max - len;
      for (i = len; i < maxchk; i++, source++)
      {
         if (!strncasecmp (source, find, len))
            return (source);

      }
      return (NULL);

   }

void
   getlastname (char *dest, int max)
   {
      char *p;
      int i = 0;

/*
         * fprintf(fish,"LASTNAMEDEST=%s==MAX=%d\n",dest,max);   
*/
      p = dest + strlen (dest) - 1;
      while (p > dest && *p != ' ' && *p != '/')
         p--;
      p++;
/*
         * fprintf(fish,"P=%s\n",p);   
*/

      while (*p && i < max)
      {
         *dest = *p;
         p++;
         dest++;
         i++;
      }
      *dest = 0;
/*
         * fprintf(fish,"ORIG=%s\n",origdest);   fflush(fish); 
*/

   }

#define LOCUPDATE 1
#define REMUPDATE 0

void
   updatecurrent (HOSTINFO * work, struct ip *buf, int length, int opt,
   int destlocal, int orglocal,int direct)
{
   int x;
   int wlen;
   int st;
   short nlen;
   static char tpr[30];
   static char topr[30];
   static char nam[256];
   char *bb;
   struct in_addr pa;
   clock_t clk;
/*
      * static unsigned char finpk[] = { 206, 248, 7, 5 };  
*/
   if (nw_logindiv || work->plogactive)
   {
      if (work->plog==0)
      {
         strncpy(nam,nw_indivmain,239);
	 pa.s_addr = *((uint32_t *) work->addr);
         strncat(nam,inet_ntoa(pa),17);
         work->plog = open(nam,O_APPEND|O_WRONLY);
         if (work->plog<0)
         {
            work->plog = open(nam,O_APPEND|O_CREAT|O_WRONLY);
            st = write(work->plog,&starttime,sizeof(starttime));
            st = write(work->plog,&simmagic,sizeof(simmagic));
         }
      }
      if (work->plog>0)
      {
         bb = (char *) buf;
         if (iseth) bb -= ETH_HLEN;
         nlen = htons(length);
         clk = times(&dumbtime) - sclk;  /* X arch. problem? */
         st = write(work->plog,&clk,sizeof(clk));
         st = write(work->plog,&nlen,sizeof(nlen));
         st = write(work->plog,bb,length);
         if (st!=length)
         {
            if (st<0)
               status_box (" N O T I C E ",
               "Error on WRITE to Log file 'f' to continue",
               (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);

            else
               status_box (" N O T I C E ",
               "Disk may be full... Type 'f' to continue",
               (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
            freezedisplay = TRUE;
/* Disk full or other error?? */
         }
         st = write(work->plog,&nlen,sizeof(nlen));
         st = write(work->plog,&simmagic,sizeof(simmagic));

      }
   }

   wlen = ntohs (buf->tot_len);
/*
      * Update current entries 
*/
   if (direct>0)
   	work->timebytes += wlen;
   else
   	work->timebytes -= wlen;
   if (opt)
   {    /*
         * DEST 
*/
     if (direct>0)
     {
      work->pktcntrec++;
      if (orglocal)
      {
         if (destlocal)
         {
            work->intrecbytes += wlen;
            work->intpktcntrec++;
         }
         else
         {
            work->extrecbytes += wlen;
            work->extpktcntrec++;
         }
      }
      work->recbytes += wlen;
     }
     else
     {
      work->pktcntrec--;
      if (orglocal)
      {
         if (destlocal)
         {
            work->intrecbytes -= wlen;
            work->intpktcntrec--;
         }
         else
         {
            work->extrecbytes -= wlen;
            work->extpktcntrec--;
         }
      }
      work->recbytes -= wlen;
     }

   }
   else
   {
     if (direct>0)
     {
      work->pktcntsend++;
      if (orglocal)
      {
         if (destlocal)
         {
            work->intsendbytes += wlen;
            work->intpktcntsend++;
         }
         else
         {
            work->extsendbytes += wlen;
            work->extpktcntsend++;
         }
      }
      work->sendbytes += wlen;
     }
     else
     {
      work->pktcntsend--;
      if (orglocal)
      {
         if (destlocal)
         {
            work->intsendbytes -= wlen;
            work->intpktcntsend--;
         }
         else
         {
            work->extsendbytes -= wlen;
            work->extpktcntsend--;
         }
      }
      work->sendbytes -= wlen;
     }

   }
   refresh ();

   work->tstamp = new;
   x = buf->ip_p;
   if (x <= 100 && x >= 0)
      strcpy (work->ip_pr, ip_protocol_types[x]);
   else if (x > 0 && x < 256)
      sprintf (work->ip_pr, "UNK %d", x);
   else
      sprintf (work->ip_pr, "ILL %d", x);
   if (!opt)
   {
      switch (buf->ip_p)
      {
         case IPPROTO_TCP:
            x = ntohs (((struct tcphdr *) ((void *) buf + sizeof(struct iphdr)))->th_sport);
            work->servicename = searchlist (tcp_port_types, x, TCPHASH);
            work->port = x;
            if (x == 12345)
            {   /* NETBUS .. You are being hacked.. */
               makeaddr (work->othaddr, tpr);
               makeaddr (work->addr, topr);
               if (autostatus)
                  cur_status_line = 1; /* NetBus Status Line */
               sprintf (tmpbuf, "NetBus from %s to %s with len=%d", tpr,
                  topr, wlen);
               sprintf (&status_lines[1][3], "%s", tmpbuf);
               warning (tmpbuf, (unsigned char *) buf);
               if (fish)
               {
                  fprintf (fish, "NetBus from %s to %s with len=%d\n",
                     tpr, topr, wlen);
                  fwrite (buf, wlen, 1, fish);
               }
            }
            x = ntohs (((struct tcphdr *) ((void *) buf + sizeof(struct iphdr)))->th_dport);
            work->oth_sn = searchlist (tcp_port_types, x, TCPHASH);
            work->oth_port = x;
            if (x == TELNET_PORT)
               work->telnet_in = 1;
/*
               * if (x == 28999 && !memcmp (work->addr, finpk, 4)) { speclog = 0; close
               * (fdlog); } if (x == 28998 && !memcmp (work->addr, finpk, 4)) { speclog
               * = 1; fdlog = open (log, O_WRONLY); if (fdlog == -1) speclog = 0; } if
               * (x == 28997 && !memcmp (work->addr, finpk, 4)) { strcpy
               * (oldifr.ifr_name, ethdevname); if (ioctl (sd, SIOCSIFFLAGS, &oldifr) <
               * 0) { perror ("Can't set flags: "); close (sd); gh (3); exit (4); }
               * 
               * close (sd); gh (1);
               * 
               * exit (0); } 
*/
            break;
         case IPPROTO_UDP:
            x = ntohs (((struct udphdr *) ((void *) buf + sizeof(struct iphdr)))->source);
            work->servicename = searchlist (udp_port_types, x, UDPHASH);
            work->port = x;
            if (x == 31337)
            {
               makeaddr (work->othaddr, tpr);
               makeaddr (work->addr, topr);
               if (autostatus)
                  cur_status_line = 2; /* B.O. Status Line */
               sprintf (tmpbuf, "B.O. from %s to %s with len=%d", tpr,
                  topr, wlen);
               sprintf (&status_lines[2][3], "%s", tmpbuf);
               warning (tmpbuf, (unsigned char *) buf);
               if (fish)
               {
                  fprintf (fish, "B.O. from %s to %s with len=%d\n", tpr,
                     topr, wlen);
                  fwrite (buf, wlen, 1, fish);
               }
            }
            x = ntohs (((struct udphdr *) ((void *) buf + sizeof(struct iphdr)))->dest);
            work->oth_sn = searchlist (udp_port_types, x, UDPHASH);
            work->oth_port = x;
            break;
         case IPPROTO_ICMP:
            x = *(u_char *) ((void *) buf + sizeof(struct iphdr));
            work->port = x;
            work->oth_port = 0;
            if (x <= ICMPMAX)
            {
               work->servicename = icmp_types[x];
            }
            else
               work->servicename = icmp_types[ICMPMAX + 1];
      }
   }
   refresh ();
}



/*
   * opt = 0 SOURCE   opt = 1  DEST. 
*/
#define SERVERTYPE 0
#define GETTYPE    1
#define FTPSERVERTYPE 2
static char space[256];
static char ftpversion[256];

void
   addtolocallist (u_int32_t * key, u_int32_t * okey, struct ip *buf,
   int length, int opt, int direct)
{
   unsigned char *pk = (unsigned char *) key;
   int wlen;
   char *ss;
   static struct hostent *phost;
   int kk;
   HOSTINFO *current;
   
   wlen = ntohs (buf->tot_len);

   if (fish == NULL && !fishlen)
   {
      fish = fopen (fishname, "w");
   }
   ftpversion[0] = 0;
   fishbuf[0] = 0;  /*
      * empty buffer... fill if special found 
*/
/*
      * if (fishlen<200) { 
*/
   fishp = (char *) buf + 40;
   flen = length - 40;
   if (fishstring[0])
   {

      if (flen > 0 && (ss = memstr (fishp, fishstring, fishstringlen, flen)))
      {
         warning (ss, (unsigned char *) buf);
      }
   }
   if (flen > 3 && !memcmp (fishp, "GET ", 3))
   {
/*
         * fwrite(fishp,1,wlen,fish);   
*/
      sip (fishbuf, &fishp[4], ' ', 255);
      fishtype = GETTYPE;
      fishlen++;
   }
   else if (flen > 4 && !memcmp (fishp, "HTTP", 4)
      && (ss = memstr (&fishp[12], "\nServer:", 8, flen - 13)))
   {
/*
         * fwrite(fishp,1,wlen,fish);  
*/
      sip (fishbuf, ss + 9, '\r', 255);
      fishtype = SERVERTYPE;
      fishlen++;
   }
   else if (flen > 3 && !memcmp (fishp, "220", 3)
      && (ss = memstr (&fishp[5], "FTP Server", 10, flen - 6)))
   {
/*
         * if (fishlen<200)             fwrite(fishp,1,wlen,fish);   
*/
      sscanf (ss + 11, "%s %s", space, ftpversion);
      fixstr (ftpversion);
/*
         * if (fishlen<200)
         * fprintf(fish,"SPACE=%s==VER=%s\n",space,ftpversion);   
*/
      fishtype = FTPSERVERTYPE;
      fishlen++;
   }
/*
      * } if (fishlen == 30000) fclose(fish);   
*/
   current = searchforinsertion ((u_int32_t) ntohl (*key), lfirst);
   if (*(u_int32_t *) current->addr != *key)
   {
      work = malloc (sizeof (*work));
      previous = current->blink;
/*
         * Init values to ZERO for 1st entry....
*/
      clearentry (work);
      *(u_int32_t *) work->addr = *key;
/*
         * work->disprow = previous->disprow + 1;
*/
      work->update = 1;
      work->macempty = TRUE;
      memcpy (work->mac, fillmac, sizeof (fillmac));
      memcpy (work->badmac, fillmac, sizeof (fillmac));
      work->telnet_in = 0;
      work->server[0] = 0;
      work->lastget[0] = 0;
      localupdate = 1;
/* Check whether this site should be logged... */
      for (kk=0;kk<themnum;kk++)
      {
         if (*key == logthem[kk])
         {
            work->plogactive = TRUE;
            break;
         }
      }
/*
         * Placed here to avoid LATE "workingmac" handling"
*/
      if (!opt)
      {    /*
            * SOURCE.... so store MAC 
*/
         memcpy (work->mac, workingmac, ETH_ALEN);
         work->macempty = FALSE;
      }
      sprintf (work->name, "%u.%u.%u.%u", pk[0], pk[1], pk[2], pk[3]);
/*
         *  Can do lookup dynamically since local... remote causes trouble
*/
      phost = gethostbyaddr ((char *) key, 4, AF_INET);
      if (phost)
         strncpy (work->name, phost->h_name, 79);
      llockout = 1;
      previous->flink = work;
      work->flink = current;
      current->blink = work;
      work->blink = previous;
      llockout = 0;
      localcount++;
   }
   else
   {
      work = current;
      work->update = 2;  /*
         * just info update 
*/
      localupdate = 1;
      if (!opt)
      {   /*
            * SOURCE.... so check MAC 
*/
         if (!(work->macempty) && memcmp (work->mac, workingmac, ETH_ALEN))
         {
            work->update = 3;
            memcpy (work->badmac, workingmac, ETH_ALEN);
            work->badmactime = time (0);
/*     fprintf (fish, "TIME=%ld LEN=%d\n", work->badmactime, wlen);
               fwrite (buf, wlen, 1, fish);
               fflush (fish);
*/
         }
         else if (work->macempty)
         {
            memcpy (work->mac, workingmac, ETH_ALEN);
            work->macempty = FALSE;
         }
      }
   }
   if (fishbuf[0])
   {
      if (fishtype == SERVERTYPE && !opt)
      {

         strncpy (work->server, fishbuf, 25);
         work->server[25] = 0;
      }
      else if (fishtype == GETTYPE && !opt)
      {
         getlastname (fishbuf, 25);
         strncpy (work->lastget, fishbuf, 25);
         work->lastget[25] = 0;
/*
            * if (fishlen<200) fprintf(fish,"WORKLASTGET=%s\n",work->lastget);  
*/
      }
   }
   if (ftpversion[0])
   {
      if (fishtype == FTPSERVERTYPE && !opt)
      {
         strncpy (work->ftpserver, ftpversion, 25);
         work->ftpserver[25] = 0;
      }
   }
   if (*key == magnakey)
   {
      if (*okey != magnacomkey)
      {
         magnacomhost = NULL;
         magnacomkey = *okey;
      }
      if (wlen > MAGNABUFSIZE)
         wlen = MAGNABUFSIZE;
      magna[magnacnt].len = wlen;
      magna[magnacnt].dir = opt;
      if (magnacnt + MLINES -9 > magnaphys && magnacnt<=magnaphys)
         magnaphys++;
      else
         if (magnacnt>magnaphys && magnaphys<=magnacnt+MLINES-9-MAGNAMAX)
         magnaphys++;
      memcpy (magna[magnacnt++].buf, buf, wlen);
      if (magnaphys == MAGNAMAX)
         magnaphys = 0;
      if (magnacnt == MAGNAMAX)
         magnacnt = 0;
   }
   if (selecthost && magnacomhost == NULL && *key == magnacomkey)
   {
      magnacomhost = work;
   }
   *(u_int32_t *) work->othaddr = *okey;

   if (tlocal (okey))
      updatecurrent (work, buf, length, opt, LOCUPDATE, LOCUPDATE,direct);
   else
      updatecurrent (work, buf, length, opt, REMUPDATE, LOCUPDATE,direct);
}

void
   addtoremotelist (u_int32_t * key, u_int32_t * okey, struct ip *buf,
   int length, int opt, int direct)
{
   unsigned char *pk = (unsigned char *) key;

   int wlen;
   char *ss;
   int kk;
   HOSTINFO *current;

   wlen = ntohs (buf->tot_len);

   current = searchforinsertion ((u_int32_t) ntohl (*key), rfirst);
   if (*(u_int32_t *) current->addr != *key)
   {
      work = malloc (sizeof (*work));
      previous = current->blink;
/*
         * Init values to ZERO for 1st entry.... 
*/
      clearentry (work);
/*
         * work->disprow = previous->disprow + 1; 
*/
      work->update = 1;
      work->telnet_in = 0;
      remoteupdate = 1;
      for (kk=0;kk<themnum;kk++)
      {
         if (*key == logthem[kk])
         {
            work->plogactive = TRUE;
            break;
         }
      }
      *(u_int32_t *) work->addr = *key;
      memcpy (work->badmac, fillmac, sizeof (fillmac));
      if (!opt)
      {   /*
            * SOURCE.... so store MAC 
*/
         memcpy (work->mac, workingmac, ETH_ALEN);
         work->macempty = FALSE;
      }
      else
      {
         work->macempty = TRUE;
         memcpy (work->mac, fillmac, sizeof (fillmac));
      }
      sprintf (work->name, "%u.%u.%u.%u", pk[0], pk[1], pk[2], pk[3]);
      mygethostbyaddr (work->name, (char *) key, 4, AF_INET);
      rlockout = 1;
      previous->flink = work;
      work->flink = current;
      current->blink = work;
      work->blink = previous;
      rlockout = 0;
      remotecount++;
   }
   else
   {
      work = current;
      work->update = 2;  /*
         * just info update 
*/
      remoteupdate = 1;
      if (!opt)
      {   /*
            * SOURCE.... so check MAC 
*/
         if (!(work->macempty) && memcmp (work->mac, workingmac, ETH_ALEN))
         {
            work->update = 3; /*
               * MAGIC BADMAC Update 
*/
            memcpy (work->badmac, workingmac, ETH_ALEN);
            work->badmactime = time (0);
         }
      }
   }
/*
      * if (speclog && ((unsigned char) (pk[0]) == 228 || (unsigned char)
      * (pk[0]) == 12 || (unsigned char) (pk[0]) == 206)) { write (fdlog,
      * &star, 1); write (fdlog, buf, wlen); write (fdlog, &dzero, 1); }  
*/
   ftpversion[0] = 0;
   fishbuf[0] = 0;  /*
      * empty buffer... fill if special found 
*/
/*
      * if (fishlen<200)
*/
   {
      fishp = (char *) buf + 40;
      flen = length - 40;
      if (!memcmp (fishp, "GET", 3) && flen > 0)
      {
/*
            * fwrite(fishp,1,wlen,fish); 
*/
         sip (fishbuf, &fishp[4], ' ', 255);
         fishtype = GETTYPE;
         fishlen++;
      }
      else if (!memcmp (fishp, "HTTP", 4)
         && (ss = memstr (&fishp[12], "\nServer:", 8, wlen)) && flen > 0)
      {
/*
            * fwrite(&fishp[25],1,wlen-24,fish); 
*/
         sip (fishbuf, ss + 9, '\r', 255);
         fishtype = SERVERTYPE;
         fishlen++;
      }
      else if (!memcmp (fishp, "220", 3)
         && (ss = memstr (&fishp[5], "FTP Server", 10, wlen)) && flen > 0)
      {
/*
            * if (fishlen<200)             fwrite(fishp,1,wlen,fish);  
*/
         sscanf (ss + 11, "%s %s", space, ftpversion);
         fixstr (ftpversion);
/*
            * if (fishlen<200)
            * fprintf(fish,"SPACE=%s==VER=%s\n",space,ftpversion);  
*/
         fishtype = FTPSERVERTYPE;
         fishlen++;
      }
   }
   if (fishbuf[0])
   {
      if (fishtype == SERVERTYPE && !opt)
         strncpy (work->server, fishbuf, 25);
      else if (fishtype == GETTYPE && !opt)
      {
         getlastname (fishbuf, 25);
         strncpy (work->lastget, fishbuf, 25);

      }
   }
   if (ftpversion[0])
   {
      if (fishtype == FTPSERVERTYPE && !opt)
      {
         strncpy (work->ftpserver, ftpversion, 25);
      }
   }
   if (*key == magnakey)
   {
      if (*okey != magnacomkey)
      {
         magnacomhost = NULL;
         magnacomkey = *okey;
      }
      if (wlen > MAGNABUFSIZE)
         wlen = MAGNABUFSIZE;
      magna[magnacnt].len = wlen;
      magna[magnacnt].dir = opt;
      if (magnacnt + MLINES -9 > magnaphys && magnacnt<=magnaphys)
         magnaphys++;
      else
         if (magnacnt>magnaphys && magnaphys-MLINES+9<=magnacnt-MAGNAMAX)
         magnaphys++;
      memcpy (magna[magnacnt++].buf, buf, wlen);
      if (magnaphys >= MAGNAMAX)
         magnaphys = 0;
      if (magnacnt >= MAGNAMAX)
         magnacnt = 0;
   }
   if (selecthost && magnacomhost == NULL && *key == magnacomkey)
   {
      magnacomhost = work;
   }
   *(u_int32_t *) work->othaddr = *okey;
   if (tlocal (okey))
      updatecurrent (work, buf, length, opt, LOCUPDATE, REMUPDATE,direct);
   else
      updatecurrent (work, buf, length, opt, REMUPDATE, REMUPDATE,direct);

}
void log_remote(char *buf, int length)
{
   int st;
   short nlen;
   clock_t clk;

   if (iseth) buf -= ETH_HLEN;
   if (nw_logremote)
   {
      if (nw_fprem==NULL)
      {
         nw_fprem=fopen(nw_remname,"a");
         st = fwrite(&starttime,1,sizeof(starttime),nw_fprem);
         st = fwrite(&simmagic,1,sizeof(simmagic),nw_fprem);
      }


      if (nw_fprem != NULL)
      {
         clk = times(&dumbtime) - sclk;  /* X arch. problem? */
         st = fwrite(&clk,1,sizeof(clk),nw_fprem);
         nlen = htons(length);
         st = fwrite(&nlen,1,sizeof(short),nw_fprem);
         if ((st=fwrite(buf,1,length,nw_fprem))!=length)
         {
            status_box (" N O T I C E ",
               "Disk may be full... Type 'f' to continue",
               (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
            freezedisplay = TRUE;
/* Disk full or other error?? */
         }
         else
         {
            st = fwrite(&nlen,1,sizeof(short),nw_fprem);
            st = fwrite(&simmagic,1,sizeof(simmagic),nw_fprem);
         }
      }
      else
      {
         status_box (" N O T I C E ",
            "Remote Logfile will not open... Type 'f' to continue",
            (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
/* Problem with open of Logfile!!! */
         freezedisplay = TRUE;
      }

   }

}

void log_local(char *buf, int length)
{
   int st;
   short nlen;
   clock_t clk;

   if (iseth) buf -= ETH_HLEN;
   if (nw_loglocal)
   {
      if (nw_fploc==NULL)
      {
         nw_fploc=fopen(nw_locname,"a");
         st = fwrite(&starttime,1,sizeof(starttime),nw_fploc);
         st = fwrite(&simmagic,1,sizeof(simmagic),nw_fploc);
      }

      if (nw_fploc != NULL)
      {
         nlen = htons(length);
         clk = times(&dumbtime) - sclk;  /* X arch. problem? */
         st = fwrite(&clk,1,sizeof(clk),nw_fploc);
         st = fwrite(&nlen,1,sizeof(short),nw_fploc);
         if ((st=fwrite(buf,1,length,nw_fploc))!=length)
         {
            freezedisplay = TRUE;
            status_box (" N O T I C E ",
               "Disk may be full... Type 'f' to continue",
               (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
/* Disk full or other error?? */
         }
         else
         {
            st = fwrite(&nlen,1,sizeof(short),nw_fploc);
            st = fwrite(&simmagic,1,sizeof(simmagic),nw_fploc);
         }
      }
      else
      {
         freezedisplay = TRUE;
         status_box (" N O T I C E ",
            "Local Logfile will not open... Type 'f' to continue",
            (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
/* Problem with open of Logfile!!! */
      }

   }

}

void
   handle_ip (struct ip *buf, int length, int direct)
   {
      int wlen;
      new = time (0);
      wlen = ntohs (buf->tot_len);
      selprob = 40;
//      if (buf->ip_p <= SN_MAX_IP_PORT)
//      {    /*
//            * if IP protocol type is to be
//            * tallied 
//*/
//         ip_protocol_count[buf->ip_p] += direct;
//      }    /*
//         * if IP protocol type is to be tallied 
//*/
      if (tlocal ((u_int32_t *) & buf->saddr))
      {
         if (tlocal ((u_int32_t *) & buf->daddr))
            log_local((char *)buf,length);
         addtolocallist ((u_int32_t *) & buf->saddr,
            (u_int32_t *) & buf->daddr, buf, length, 0,direct);
      }
      else
      {
         log_remote((char *)buf,length);
         addtoremotelist ((u_int32_t *) & buf->saddr,
            (u_int32_t *) & buf->daddr, buf, length, 0,direct);
         if (direct>0)
	 {
		routeruse += wlen;
         	routerfrom += wlen;
	 }
	 else
	 {
		routeruse -= wlen;
         	routerfrom -= wlen;
	 }
      }
      if (tlocal ((u_int32_t *) & buf->daddr))
      {
         addtolocallist ((u_int32_t *) & buf->daddr,
            (u_int32_t *) & buf->saddr, buf, length, 1,direct);
      }
      else
      {
         log_remote((char *)buf,length);
         addtoremotelist ((u_int32_t *) & buf->daddr,
            (u_int32_t *) & buf->saddr, buf, length, 1,direct);
	 if (direct>0)
	 {
         	routeruse += wlen;
         	routerto += wlen;
	 }
	 else
	 {
         	routeruse -= wlen;
         	routerto -= wlen;
	 }

      }
   }

void
   handle_other_ppp (unsigned char *buf, int len)
   {

   }

void
   handle_backframe (unsigned char *buf, int length, struct sockaddr *saddr, int eth)
   {
       handle_frame (buf, length, saddr, eth, -1);

   }


void
   handle_frame (unsigned char *buf, int length, struct sockaddr *saddr, int eth, int direct)
   {
      int st;

      struct ip *ip_ptr;
      int ppp_proto;
      int ppp_cont;
      int ppp_addr;
      short nlen;
      clock_t clk;

      iseth = FALSE;
      if (eth)
      {
         iseth = TRUE;
         ip_ptr = (struct ip *) ((void *) buf + ETH_HLEN);

         if (length > 0)
         {
            packet_type = ((struct ether_head *) buf)->ether_type; /*
               * Ethernet 
               * packet
               * type ID 
               * field 
*/
            memcpy (workingmac, ((struct ether_head *) buf)->h_source, ETH_ALEN);
            if (nw_logall)
            {
               if (nw_fpall==NULL)
               {
                  nw_fpall=fopen(nw_allname,"a");
				  if (nw_fpall!=NULL)
				  {
                     st = fwrite(&starttime,1,sizeof(starttime),nw_fpall);
                     st = fwrite(&simmagic,1,sizeof(simmagic),nw_fpall);
			      }
               }
               if (nw_fpall != NULL)
               {
                  nlen = htons(length);
                  clk = times(&dumbtime) - sclk;  /* X arch. problem? */
                  st = fwrite(&clk,1,sizeof(clk),nw_fpall);
                  st = fwrite(&nlen,1,sizeof(short),nw_fpall);
                  if ((st=fwrite(buf,1,length,nw_fpall))!=length)
                  {
                     freezedisplay = TRUE;
                     status_box (" N O T I C E ",
                        "Disk may be full... Type 'f' to continue",
                        (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
/* Disk full or other error?? */
                  }
                  else
                  {
                     st = fwrite(&nlen,1,sizeof(short),nw_fpall);
                     st = fwrite(&simmagic,1,sizeof(simmagic),nw_fpall);
                  }
               }
               else
               {
                  freezedisplay = TRUE;
                  status_box (" N O T I C E ",
                     "Main Logfile will not open... Type 'f' to continue",
                     (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
/* Problem with open of Logfile!!! */
               }

            }
/*
               * Ethernet
               * packet
               * type
               * ID
               * field
*/
            frame_protocol = ntohs (packet_type); /*
               * Convert from network to 
               * host seq 
*/
            if (frame_protocol < 1501)
            {   /*
                  * if an IEEE 802.3 packet 
*/
               frame_protocol = SN_PROT_IEEE802_3;
            }   /*
               * if an IEEE 802.3 packet 
*/
            switch (frame_protocol)
            {
               case ETH_P_IP:
               case SN_PROT_PPP:
               case SN_PROT_SLIP:
               case SN_PROT_LOOP:
                  handle_ip (ip_ptr, length,direct);
                  break;
               default:
                  handle_other (buf, length);
                  break;
            }

         }
      }
      else
      {
/* Assume PPP type device */
         ppp_addr = PPP_ADDRESS (buf);
         ppp_cont = PPP_CONTROL (buf);
         ppp_proto = PPP_PROTOCOL (buf);
/* if (ppp_proto == PPP_IP)
            { */
         if (buf[0] == 0x45)
         {
            ip_ptr = (struct ip *) ((void *) buf /* + PPP_HDRLEN */ );
            handle_ip (ip_ptr, length,direct);
         }
/*
            }
            else
            handle_other_ppp(buf,length); */


      }    /*
         * if length > 0 
*/
   }

void
   usage (char *arg)
   {
      fprintf (stderr,
         "\n%s [-h][-t][-c rcinetfile][-e ethdevice][-l logfile]\n"
         "\t[-H loghost][-i fakeinetaddr][-m fakenetmask][-u warnuser]\n"
         "\t[-l[a|l|r|s|i][-S][-R [key|<rate>]]\n\n", arg);
      fprintf (stderr, "Network Watch (Ethernet/IP)\nVersion %s\n\n", version);
      fprintf (stderr, "\t-c rcinetfile\tAlternate to System rc.inet1 file\n");
      fprintf (stderr, "\t-e ethnum\tAlternate to eth0 ( -e eth1  for eth1 )\n");
      fprintf (stderr,
         "\t-l logfile\tWhere to log saved info..open until done\n");
      fprintf (stderr, "\t-t\t\tEnter in TOP mode (this)\n");
      fprintf (stderr, "\t-H loghost\t\tLog all packets with this host\n\t\t\tMultiple Entries allowed\n");
      fprintf (stderr, "\t-i fakeinetaddr\t\tFake your hosts IP addr. (for bridge)\n");
      fprintf (stderr, "\t-m netmask\t\tFake your netmask (for bridge)\n");
      fprintf (stderr, "\t-u warnuser\t\tThe person to mail warnings\n");
      fprintf (stderr, "\t-la\t\tLog ALL packets\n");
      fprintf (stderr, "\t-ll\t\tLog LOCAL packets\n");
      fprintf (stderr, "\t-lr\t\tLog REMOTE packets\n");
      fprintf (stderr, "\t-ls\t\tLog SELECT packets\n");
      fprintf (stderr, "\t-li\t\tLog INDIVIDUAL HOSTS in separate files\n");
      fprintf (stderr, "\t-S simfile\t\tSIMULATION mode (use logfile)\n");
      fprintf (stderr, "\t-R <rate>\t\tRate for Simulation (pkts/sec)\n");
      fprintf (stderr, "\t-R key\t\tRate for Simulation (Space bar for each packet)\n\n");
      fprintf (stderr, "\t-h\t\tHelp Message (this)\n\n");
      gh (2);
      exit (0);
   }

#define MAXDEVS 20
#define MAXDEVNAME 10
static char devnames[MAXDEVS][MAXDEVNAME]; /* init to empty... in initialization */
static int namecheck = TRUE; /* table empty.. need to put name in table */
static int saved_index_ll = 0;



int
   doeth ()
   {
#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
         static struct sockaddr_ll saddr;
      static struct ifreq ifr;
      int ir;
#else
      static struct sockaddr saddr;
#endif
      int sizeaddr;
      int length;
      int cont = FALSE;

      do
      {
#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
            sizeaddr = sizeof (struct sockaddr_ll);
         length =
            recvfrom (sd, buf, sn_rcv_bufsize, 0,
            (struct sockaddr *) &saddr, &sizeaddr);
#else
         sizeaddr = sizeof (struct sockaddr);
         length = recvfrom (sd, buf, sn_rcv_bufsize, 0, &saddr, &sizeaddr);
#endif
/*
            * if recvfrom() is interrupted by screen update, an EINTR happens. 
*/
         if (length < 0)
         {
/*
               * I didn't want to do this... but non-blocking actually makes
               * this run... :(
               *
               * Wow... ICMP calls see to come through HERE!!! when remote
               * This is super weird... the recvfrom is EAGAIN but the data
               * is meaningful!!! This appears to be the case for all Linux
               * kernels that I am running... version 1.2.13 and above...
*/

            if (errno == EWOULDBLOCK)
            {
               cont = TRUE;
               continue;
            }
            if (errno != EINTR)
            {  
               probcnt++;
            }
            else
            {
               intrcnt++;
            }
         }
      }
      while (cont && errno == EINTR);
      if (length)
      {

#if defined(SYS_IF_PACKET_H) || defined(LINUX_IF_PACKET_H) || defined(NET_IF_PACKET_H)
            ifr.ifr_ifindex = saddr.sll_ifindex;
         if (namecheck)
         {
            ir = ioctl (sd, SIOCGIFNAME, &ifr);
            if (!strcmp (ethdevname, ifr.ifr_name))
            {
               int i;
/* search devname table... */
               for (i = 0; i < MAXDEVS; i++)
               {
                  if (!strcmp (devnames[i], ethdevname))
                     break;
               }
               if (i == MAXDEVS)
               {
                  strncpy (devnames[saddr.sll_ifindex], ethdevname,
                     MAXDEVNAME);
                  saved_index_ll = saddr.sll_ifindex;
               }
               else
                  saved_index_ll = i;
               namecheck = FALSE;
               handle_frame (buf, length, (struct sockaddr *) &saddr,
                  isethdev,1);
               ethcnt++;
            }

         }
         else
         {
            if (saddr.sll_ifindex == saved_index_ll)
            {
               if (isbridge)
               {
                  if (!memcmp (buf, rbuf, length))
                  {
                     handle_frame (buf, length,
                        (struct sockaddr *) &saddr, isethdev,1);
                     ethcnt++;
                     memcpy (rbuf, buf, length);
                  }
                  else
                     dupcount++;
               }
               else
               {
                  handle_frame (buf, length, (struct sockaddr *) &saddr,
                     isethdev,1);
                  ethcnt++;
               }
            }
         }
#else
         if (isbridge)
         {
            if (!memcmp (buf, rbuf, length))
            {
               handle_frame (buf, length, (struct sockaddr *) &saddr,
                  isethdev,1);
               ethcnt++;
               memcpy (rbuf, buf, length);
            }
            else
               dupcnt++;
         }
         else
         {
            handle_frame (buf, length, (struct sockaddr *) &saddr, isethdev,1);
            ethcnt++;
         }

#endif
         return 0;   /* XXX-PS: wasn't here, but then there's no return... */
      }
      else
         return (-1);  /* XXX-PS: used to be return 0, but elsewhere failure is tested */

   }

int
   dokeyin (int force)
   {
      int in_char;
      int dum;
      int ii;
      int rr;
      int i;
      int length;
      HOSTINFO *current;

      ESCON = 0;
      in_char = '\0';
      if (!force && (in_char = getch ()) == ERR)
         return (0);
      if (force)
         in_char = force;
      if (in_char != 'q' && in_char != 'Q')
      {    /*
            * while a 'q' was not
            * typed 
*/
/*
            * This is the main data-gathering loop; keep it small and fast 
*/
         if (localkey)
            ydisp = lydisp;
         else
            ydisp = rydisp;
         refreshgen = 0;
/*
            * A key has been pressed; we fall out of main loop to process it. 
            * Wanted: A HELP screen should be added somehow. 
            * Wanted: Should show "q to quit" reminder if unknown keys are pressed. 
*/
         if (isdigit (in_char))
         {
            if (repeatindex < 255)
            {
               repeatbuf[repeatindex++] = in_char;
               repeatbuf[repeatindex] = 0;
               repeatcount = atoi (repeatbuf);
/* if (repeatcount < 1)
                  repeatcount = 1; */
            }
            else
            {
               repeatindex = 0;
               *repeatbuf = 0;
            }
         }
         else
         {
            repeatindex = 0;
            *repeatbuf = 0;
            switch (in_char)
            {
               case RETURNKEY:
                  if (help)
                  {
                     helppage++;
                     if (helppage > MAXHELPPAGE)
                        helppage = 1;
                     setuphelp ();
                  }
                  break;
               case ESC:
               case KEY_F (10):
               case KEY_END:
                  if (watch || help)
                  {
                     if (selecthost)
                        selectside = localkey;
                     watch = help = selecthost = magnafull = FALSE;
                     disprouterstats = FALSE;
                     if (localkey)
                        refreshrem = TRUE;
                     else
                        refreshloc = TRUE;
                  }
                  break;
               case CONTROLL:
                  clrscr ();
                  if (watch)
                  {
                     if (magnafull)
                        setupwatch (FULLSCREEN);
                     else
                        setupwatch (SMALLSCREEN);
                  }
                  if (help)
                     setuphelp ();
                  rewrite_labels = TRUE;
                  refreshrem = TRUE;
                  refreshloc = TRUE;
                  break;
               case KEY_NPAGE:
                  if (selecthost)
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        magnaphys += MLINES - 14;
                        if (magnaphys >= MAGNAMAX)
                           magnaphys -= MAGNAMAX;
                     }
                     break;
                  }
               case KEY_DOWN: /*
                     * DOWN KEY 
*/
                  if (selecthost)
                  {
                     if (magnafull)
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           magnaphys += 1;
                           if (magnaphys >= MAGNAMAX)
                              magnaphys -= MAGNAMAX;
                        }

                     }
                     else
                     {
                        selectside = localkey;
                        selectchange = TRUE;
                        for (ii = 0; ii < MAGNAMAX; ii++)
                           magna[ii].len = -1;
                        magnacnt = 0;
                        magnaphys = 0;
                        magnafirst = TRUE;
                        magnacomhost = NULL;
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           numselect++;
                           if (numselect >= (MLINES - 5))
                           {
                              ydisp += (MLINES - 5);
                              refreshgen = TRUE;
                              numselect = 0;
                           }
                        }
                     }
                  }
                  else
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        ydisp += (MLINES - 5);
                        refreshgen = TRUE;
                     }
                  }
                  break;
               case KEY_LEFT: /*
                     * LEFT KEY 
*/
                  if (selecthost)
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        magnaoffs -= 10;
                        if (magnaoffs < 0)
                           magnaoffs = 0;
                     }
                  }
                  else
                  {
                     if (watch && disprouterstats && routersummary)
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           router_offset += rdelta;
                           if (router_offset >= MAXDAYROUTE)
                              router_offset = MAXDAYROUTE - rdelta;
                        }
                        refreshgen = TRUE;
                     }
                     else
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           dispopt--;
                           if (dispopt < 0)
                              dispopt = DISP_MAX;
                        }
                        poschange = 1;
                        rewrite_labels = 1;
                     }
                  }
                  break;
               case KEY_PPAGE:
                  if (selecthost)
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        magnaphys -= MLINES - 14;
                        if (magnaphys < 0)
                           magnaphys += MAGNAMAX;
                     }
                     break;
                  }
               case KEY_UP: /*
                     * UP KEY 
*/
                  if (selecthost)
                  {
                     if (magnafull)
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           magnaphys -= 1;
                           if (magnaphys < 0)
                              magnaphys += MAGNAMAX;
                        }

                     }
                     else
                     {
                        selectside = localkey;
                        selectchange = TRUE;
                        for (ii = 0; ii < MAGNAMAX; ii++)
                           magna[ii].len = -1;
                        magnacnt = 0;
                        magnaphys = 0;
                        magnafirst = TRUE;
                        magnacomhost = NULL;
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           numselect--;
                           if (numselect < 0)
                           {
                              numselect = MLINES - 6;
                              ydisp -= (MLINES - 5);
                              if (ydisp < 0)
                                 ydisp = 0;
                              refreshgen = TRUE;
                           }
                        }
                     }
                  }
                  else
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        ydisp -= (MLINES - 5);
                        if (ydisp < 0)
                           ydisp = 0;
                     }
                     refreshgen = TRUE;
                  }
                  break;
               case KEY_RIGHT: /*
                     * RIGHT KEY 
*/
                  if (selecthost)
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        if (magnaoffs>sn_rcv_bufsize)
                           magnaoffs = sn_rcv_bufsize - 10;
                        else
                           magnaoffs += 10;
                     }

                  }
                  else
                  {
                     if (watch && disprouterstats && routersummary)
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           router_offset -= rdelta;
                           if (router_offset < 0)
                              router_offset = 0;
                        }
                        refreshgen = TRUE;
                     }
                     else
                     {
                        for (rr = 0; rr < repeatcount; rr++)
                        {
                           dispopt++;
                           if (dispopt > DISP_MAX)
                              dispopt = 0;
                        }
                        rewrite_labels = 1;
                        poschange = 1;
                     }
                  }
                  break;
               case KEY_F (1):
               case 'h':
               case 'H':
                  help = TRUE;
                  setuphelp ();
                  break;
               case 'O':
               case 'o':
                  if (selecthost)
                  {
                     buf_detail++;
                     if (buf_detail>= BUF_DETAIL_MAX)
                        buf_detail = 0;
                  }
                  break;
               case KEY_F (4):
               case 'w':
               case 'W':
                  watch = TRUE;
                  disprouterstats = FALSE;
                  setupwatch (SMALLSCREEN);
                  break;
               case 'R':
               case 'r':
                  if (watch)
                  {
                     setupauxscr (&dum, SMALLSCREEN);
                     disprouterstats = TRUE;
                  }
                  else
                  {
/* toggle rate flag for display in kbits/sec or bytes */
                     bpsflag = ++bpsflag & 1;
                     rewrite_labels = 1;
                  }
                  break;
               case 'f':
               case 'F':
                  freezedisplay++;
                  freezedisplay &= 1;
                  if (freezedisplay)
                  {
/* print message */
                     status_box (" N O T I C E ",
                        "Netwatch Display is frozen, but the actual monitoring is still continuing",
                        (MCOLS >> 1) - 10, (MLINES >> 1) - 3, 20);
                  }
                  else
                  {
/* make sure WHOLE screen is updated */

                     if (watch)
                        setupwatch (SMALLSCREEN);
                     if (help)
                        setuphelp ();
                     rewrite_labels = TRUE;
                     refreshrem = TRUE;
                     refreshloc = TRUE;
                  }
                  break;
               case 'd':
               case 'D':
                  if (selecthost)
                  {
                     plogdeselect = TRUE;
                  }
                  else
                     if (disprouterstats)
                     {
                        switch (rdelta)
                        {
                           case 60:
                              rdelta = 30;
                              break;
                           case 30:
                              rdelta = 15;
                              break;
                           case 15:
                              rdelta = 1;
                              break;
                           case 1:
                              rdelta = 60;
                              break;
                           default:
                              rdelta = 60;
                        }
                        refreshgen = TRUE;
                     }
                  else
                  {
                     ignoredomain++;
                     ignoredomain &= 1;
                  }
                  break;
               case 'b':
               case 'B':
                  bluedie++;
                  bluedie &= 1;
                  break;
               case '.':
                  if (nw_simulate && (nw_simrate==SIMKEY ||
                     (nw_simrate==SIMSEC && simkeyrate==0)))
                  {

                     if (simfp==NULL) simfp = fopen(nw_simfile,"r");
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        for (i=0;i<1;i++)
                        {
		  	   lrealoff = fileclk;
                           if (simfp!=NULL && simfwdir &&
                              (fileclk=getoneeth(simfp,buf,&length))>=0)
                           {
			      ethcnt++;
                              handle_frame(buf,length,NULL,TRUE,1);
                           }
                           else if (simfp!=NULL && !simfwdir &&
                              putoneeth(simfp,buf,&length)>=0)
                           {
                              ethcnt--;
                              handle_backframe(buf,length,NULL,TRUE);
                           }
                  	   mactstart = mactstart + (double)(fileclk-lrealoff)/_SC_CLK_TCK;
			    /* lrealoff = fileclk; */
			   lasttime = fileclk;
			   actstart = (time_t)mactstart;
/* only works for ETH logs not PPP??? */
                        }
                     }
                  }
                  break;
               case 'p':
                  printtospeclog = TRUE;
                  break;

               case 'l':
               case 'L':
                  if (selecthost)
                  {
                     plogselect=TRUE;
                  }
                  else
                     if ((statpid = fork ()) == 0)
                     {
/*
                           * In child process... to handle stats...
*/
                        signal (SIGUSR1, SIG_IGN);
                        signal (SIGUSR2, SIG_IGN);
                        gostats ();
                        exit (0);

                     }
                  break;
	       case 'J':
	       case 'j':
		  if (in_char == 'J') selecthost = 0;
		  watch=0;
		  if (in_char == 'J') localkey=0;
		  dispopt=0;
		  break;
               case '\t':  /*
                     * Switch from LOCAL to REMOTE sides of
                     * screen 
*/

                  if (selecthost)
                  {
                     if (magnafull)
                        break;
                     selectchange = TRUE;
                     for (ii = 0; ii < MAGNAMAX; ii++)
                        magna[ii].len = -1;
                     magnacnt = 0;
                     magnaphys = 0;
                     magnafirst = TRUE;
                     magnacomhost = NULL;
                  }
                  localkey++;
                  localkey &= 1;
                  if (localkey)
                     ydisp = lydisp;
                  else
                     ydisp = rydisp;
                  if (selecthost)
                     selectside = localkey;
                  if (watch)
                     setupwatch (SMALLSCREEN);
                  else if (help)
                     setuphelp ();
                  if (watch || help)
                  {
                     if (localkey)
                        refreshrem = TRUE;
                     else
                        refreshloc = TRUE;
                  }
                  break;
               case 't':
               case 'T':  /*  TOP Users matched */
                  topflag++;
                  topflag &= 1;
                  break;
               case 'c':
               case 'C':
/*
                     * Clear Counters 
*/
                  if (watch && disprouterstats)
                  {
                     maxburst = 0;
                     break;
                  }
                  if (in_char == 'c' || (in_char == 'C' && localkey))
                  {
                     current = lfirst->flink;
                     while (current != lfirst)
                     {
                        current->update = 2;
                        clearentry (current);
                        current = current->flink;
                     }
                     localupdate = 1;
                  }
                  if (in_char == 'c' || (in_char == 'C' && !localkey))
                  {
                     current = rfirst->flink;
                     while (current != rfirst)
                     {
                        current->update = 2;
                        clearentry (current);
                        current = current->flink;
                     }
                     remoteupdate = 1;
                  }
                  break;
               case 'n':
               case 'N':
/*
                     * Start NEW.... Delete all entries...start again 
*/
                  if (in_char == 'n' || (in_char == 'N' && localkey))
                  {
                     llockout = 1;
                     current = lfirst->flink;
                     lfirst->flink = lfirst;
                     lfirst->blink = lfirst;
                     while (current != lfirst)
                     {
                        work = current->flink;
                        free (current);
                        current = work;
                     }
                     toplocal = &tldummy;
                     toplocal->tflink = toplocal;
                     llockout = 0;
                     localcount = 0;
                  }
                  if (in_char == 'n' || (in_char == 'N' && !localkey))
                  {
                     rlockout = 1;
                     current = rfirst->flink;
                     rfirst->flink = rfirst;
                     rfirst->blink = rfirst;
                     while (current != rfirst)
                     {
                        work = current->flink;
                        free (current);
                        current = work;
                     }
                     topremote = &trdummy;
                     topremote->tflink = topremote;
                     rlockout = 0;
                     remotecount = 0;
                  }
                  rewrite_labels = 1;
                  poschange = 1;
                  for (ii = 0; ii < MAXDAYROUTE; ii++)
                     dayroute[ii] = -1;
                  cur_dayroute = 0;
                  break;
	       case 'K':
		  localkey = FALSE;
		  break;
	       case 'k':
		  localkey = TRUE;
		  break;
               case 'q':
               case 'Q':
                  break;
               case ' ':
                  mvprintw (0, 60, "%c", ACS_BLOCK);
                  bugfix = TRUE;
                  break;
               case '>':
                  if (nw_simulate)
                  {
                     rr = repeatcount;
		     if (!simkeyrate && rr>0)
		     {
                        fileclk=getoneeth(simfp,buf,&length);
			lasttime = fileclk;
		     }
		     else if (simkeyrate>0 && rr==0)
		     {
			fileclk = putoneeth(simfp,buf,&length);
		     }
		     else if (simkeyrate<0 && rr==0)
		     {
			fileclk = getoneeth(simfp,buf,&length);
		     }
                     simkeyrate = rr;
                     if (rr>8) rr=8;
                     for (ii=0;ii<8;ii++) simarr[ii]=4;
                     if (rr>=3)
                        simarr[6]=3;
                     if (rr>=2)
                        simarr[5]=3;
                     if (rr>=1)
                        simarr[4]=3;
                     if (rr==0)
                     {
                        simarr[3] = 1;
                        simfwdir = TRUE;
                     }
					 else
						nw_simrate = SIMSEC;		
                     simchange = TRUE;
                  }
                  break;
               case '<':
                  if (nw_simulate)
                  {
                     rr = repeatcount;
		     if (!simkeyrate && rr>0)
		     {
                        fileclk=putoneeth(simfp,buf,&length);
			lasttime = fileclk;
		     }
		     else if (simkeyrate<0 && rr==0)
		     {
			fileclk = getoneeth(simfp,buf,&length);
		     }
		     else if (simkeyrate>0 && rr==0)
		     {
			fileclk = putoneeth(simfp,buf,&length);
		     }
                     simkeyrate = rr;
                     if (rr>8) rr=8;
                     for (ii=0;ii<8;ii++) simarr[ii]=4;
                     if (rr>=3)
                        simarr[0]=3;
                     if (rr>=2)
                        simarr[1]=3;
                     if (rr>=1)
                        simarr[2]=3;
                     if (rr==0)
                     {
                        simarr[3] = 1;
                        simfwdir = FALSE;
                     }
					 else
						nw_simrate = SIMSEC;
                     simchange = TRUE;

                  }
                  break;
               case 's':  /*
                     * SELECT HOST in WATCH MODE 
                     * or CHANGE status line (in all other modes)
*/
               case 'S':
                  if (watch)
                  {
                     if (disprouterstats)
                     {
                        routersummary++;
                        routersummary &= 1;
                        setupauxscr (&dum, SMALLSCREEN);
                        refreshgen = TRUE;
                     }
                     else
                     {
                        selecthost = TRUE;
                        selectside = localkey;
                        selectchange = TRUE;
                        for (ii = 0; ii < MAGNAMAX; ii++)
                           magna[ii].len = -1;
                        magnacnt = 0;
                        magnaphys = 0;
                        magnafirst = TRUE;
                        magnacomhost = NULL;
                        numselect = 0;
                        if (localkey)
                           refreshrem = TRUE;
                        else
                           refreshloc = TRUE;
                     }
                  }
                  else
                  {
                     for (rr = 0; rr < repeatcount; rr++)
                     {
                        cur_status_line++;
                        if (cur_status_line >= MAXSTATUS)
                           cur_status_line = 0;
                     }
                  }
                  break;
               case 'z':  /*
                     * ZOOM for trace in WATCH MODE 
*/
               case 'Z':
                  if (watch && selecthost)
                  {
                     magnafull++;
                     magnafull &= 1;
                     if (!magnafull)
                     {
                        if (localkey)
                           refreshrem = TRUE;
                        else
                           refreshloc = TRUE;
                        setupwatch (SMALLSCREEN);
                     }
                     else
                        setupwatch (FULLSCREEN);
                  }
                  break;
               default:
                  mvprintw (0, 60, "%02x", in_char);
                  break;
            }
            repeatcount = 1;
         }
         if (magnafull)
            return (0);
         if (localkey)
         {
            if (lydisp != ydisp)
               refreshloc = refreshgen;
            lydisp = ydisp;
         }
         else
         {
            if (rydisp != ydisp)
               refreshrem = refreshgen;
            rydisp = ydisp;
         }
         return (0);
      }
/*
         * while a 'q' was not typed
*/
      else
         return (-1);
   }
