Logo Search packages:      
Sourcecode: netdiag version File versions

netwatch.c

/*
 * 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 program 
 */
#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 <unistd.h>
#include <sys/types.h>
/*
 * #include <sys/socket.h> 
 */
#include <sys/wait.h>
#include <time.h>
#include <sys/time.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
#ifndef LINUX_IP_OPTIONS
#define ip_options options
#endif
#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 = "0.9g";
char *iv = "pre2";
char progtitle[60];
char log[MAXFILENAME] = "/root/.log";
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 (sizeof(struct ip_options))
int ipoptsz = IPOPTSIZE;
#define TCPHEADSIZE (sizeof(struct tcphdr))
int tcpheadsz = TCPHEADSIZE;
#define SN_RCV_BUF_SIZE (sizeof(struct ether_head)+ \
                         sizeof(struct ip)+ \
                                 sizeof(struct ip_options)+ \
                         sizeof(struct tcphdr)+4)
#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. 
 */
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;

#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 13
#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 400
#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 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 + 20];


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 
                         */

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);
void handle_ip (struct ip *buf, int length);
void processinetrc (unsigned char *netmask, unsigned char *local, int *peth);
void warning( char s[], unsigned char *buf);


typedef void (*sigfunc) (int);

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

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;

      if ((fp=fopen(specconfigfile,"r")))
      {
            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,"autostatus",10))
                                    autostatus = TRUE;
                              else if (!strncasecmp(w1,"noresolve",9))
                                    noresolv = TRUE;
                              else if (!strncasecmp(w1,"resolve",7))
                                    noresolv = 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,"statsoption",11))
                              {
                                    if (!strncasecmp(w2,"append",6))
                                          statsappend = TRUE;
                                    else if (!strncasecmp(w2,"date",4))
                                          statsappend = FALSE;
                              }     
                              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 (*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;


}

/*
 * 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);
/*
 * 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;
    }
}

/*
 * 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;


  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;
/*
 * 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++;
            }
          }
        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[])
{

  {                     /*
                         * Compound statement to make initializers 
                         * vanish after init. 
                         */
    int op;
    long int mask;

    starttime = time (0);
    gh (0);
    for (op = 0; op < MAGNAMAX; op++)
      magna[op].len = -1;
    magnamatch[0] = 0;
    strcpy (progtitle, "NETWATCH Program Version ");
    strcat (progtitle, version);
    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 ("/usr/lib/netdiag/netresolv", "netresolv", NULL);
      perror ("exec /usr/lib/netdiag/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, "zs:l:hu:tc:e:")) != EOF)
      {
      switch (op)
        {
        case 'z':       /*
                         * No screen display 
                         */
          noscreen = 1;
          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 ':':
          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);
      }
/*
 * 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 ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
      {
      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 (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));
    }
/*
 * Should this be rewritten to cooperate with other net tools? 
 */
    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! 
                               */
  }                     /*
                         * Compound statement to make initializer
                         * variables vanish after init. 
                         */
/*
 * 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 (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);
      }
/*
 * 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();
      /*
       * newtm.it_value.tv_sec = 1; newtm.it_value.tv_usec = 0;
       * setitimer (ITIMER_REAL, &newtm, &oldtm); 
       *//*
         * first screen update in 1 sec (exact) 
       */
    }
  process ();

/*
 * TERMINATE 
 */

/*
 */
      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);
/*
 * 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);
}


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);
}

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

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 x;
  int wlen;
  static char tpr[30];
  static char topr[30];
/*
 * static unsigned char finpk[] = { 206, 248, 7, 5 };  
 */

  wlen =  ntohs (buf->tot_len);
/*
 * Update current entries 
 */
  work->timebytes += wlen;
  if (opt)
    {                   /*
                         * DEST 
                         */
      work->pktcntrec++;
      if (orglocal)
      {
        if (destlocal)
          {
            work->intrecbytes += wlen;
            work->intpktcntrec++;
          }
        else
          {
            work->extrecbytes += wlen;
            work->extpktcntrec++;
          }
      }
      work->recbytes += 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 + 20))->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 + 20))->th_dport);
        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 + 20))->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);
            }
          }
        break;
      case IPPROTO_ICMP:
        x = *(u_char *) ((void *) buf + 20);
        work->port = x;
        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)
{
  unsigned char *pk = (unsigned char *) key;
  int wlen;
  char *ss;
  static struct hostent *phost;

  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 (ss=memstr(fishp,fishstring,fishstringlen,flen))
  {
      warning(ss,(unsigned char *)buf);
  }
 }
  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,1,wlen,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 (fishlen == 30000) fclose(fish);   
 */
  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;
      /*
       * 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;
      memcpy (magna[magnacnt++].buf, buf, wlen);
      magnaphys++;
      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);
  else
    updatecurrent (work, buf, length, opt, REMUPDATE, LOCUPDATE);
}

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

  int wlen;
  char *ss;

  wlen = ntohs (buf->tot_len);

  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;
      *(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;
      memcpy (magna[magnacnt++].buf, buf, wlen);
      magnaphys++;
      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);
  else
    updatecurrent (work, buf, length, opt, REMUPDATE, REMUPDATE);

}

void
  handle_ip (struct ip *argbuf, int length)
{
  int wlen;
  struct ip bufstruct, *buf = &bufstruct;

  memcpy(buf, argbuf, sizeof(struct ip)); /* to fix unaligned accesses */
  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]++;
    }                   /*
                         * if IP protocol type is to be tallied 
                         */
  if (tlocal ((u_int32_t *) &buf->saddr))
    addtolocallist ((u_int32_t *) &buf->saddr, (u_int32_t *) &buf->daddr, buf, length, 0);
  else
    {
      addtoremotelist ((u_int32_t *) &buf->saddr, (u_int32_t *) &buf->daddr, buf, length, 0);
      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);
  else
    {
      addtoremotelist ((u_int32_t *) &buf->daddr, (u_int32_t *) &buf->saddr, buf, length, 1);
      routeruse += wlen;
      routerto += wlen;
    }
}

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

}

void
  handle_frame (unsigned char *buf, int length, struct sockaddr *saddr,int eth)
{
  struct ip *ip_ptr;
  int ppp_proto;
  int ppp_cont;
  int ppp_addr;

  if (eth)
  {
  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);   /*
                                                             * 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);
        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);
      }
/*
      }
      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\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\n");
  fprintf (stderr, "\t-h\t\tHelp Message (this)\n\n");
  gh (2);
  exit (0);
}

int
  doeth ()
{
  static struct sockaddr saddr;
  int sizeaddr;
  /*
   * static unsigned char buf[SN_RCV_BUF_SIZE + 400]; 
   */
  int length;
  int cont = FALSE;

  do
    {
      sizeaddr = sizeof (struct sockaddr);
      length = recvfrom (sd, buf, sn_rcv_bufsize, 0, &saddr, &sizeaddr);
/*
 * 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)
          {
            handle_frame (buf, sn_rcv_bufsize, NULL,isethdev);
            ethcnt++;
            cont = TRUE;
            continue;
          }
        if (errno != EINTR)
          {             /*
                         * if error detected and error is
                         * not expected type 
                         */
            probcnt++;
          }
        else
          {
            intrcnt++;
          }
      }
    }
  while (cont && errno == EINTR);
  if (length)
    {
      handle_frame (buf, length, &saddr,isethdev);
      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;

  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;
/*
 * sn_rcv_bufsize = SN_RCV_BUF_SIZE; 
 */

            disprouterstats = FALSE;
            if (localkey)
            refreshrem = TRUE;
            else
            refreshloc = TRUE;
          }
        break;
      case CONTROLL:
        clrscr ();
        if (watch)
          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 - 9;
                  if (magnaphys == MAGNAMAX)
                     magnaphys -= MAGNAMAX;
                  break;
            }
           }
      case KEY_DOWN:          /*
                         * DOWN KEY 
                         */
        if (selecthost)
          {
            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 - 9;
            if (magnaphys<0) magnaphys += MAGNAMAX;
            }
            break;
         }
      case KEY_UP:            /*
                         * UP KEY 
                         */
        if (selecthost)
          {
            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)
          {
            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 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;
          }
        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 (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 'p':
        printtospeclog = TRUE;
        break;

      case 'l':
      case 'L':
        if ((statpid = fork ()) == 0)
          {
            /*
             * In child process... to handle stats... 
             */
            signal(SIGUSR1,SIG_IGN);
            signal(SIGUSR2,SIG_IGN);
            gostats ();
            exit (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;
          }
        current = lfirst->flink;
        while (current != lfirst)
          {
            current->update = 2;
            clearentry (current);
            current = current->flink;
          }
        localupdate = 1;
        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 'q':
      case 'Q':
        break;
      case ' ':
        mvprintw (0, 60, "%c", ACS_BLOCK);
        bugfix = 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
            {
                        sn_rcv_bufsize = SN_RCV_BIGBUFSIZE;
                        selecthost = 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);
}

Generated by  Doxygen 1.6.0   Back to index