/*   Ethernet Monitor Program   */

/* Must be compiled with HUGE memory model */

#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#include <dos.h>
#include <alloc.h>
#include <io.h>

#define ACCESS_TYPE 2
#define RELEASE_TYPE 3
#define SET_RCV_MODE 20
#define TERMINATE 5

#define MAXETHB 1522
#define MINETHB 59

typedef struct {

 unsigned char t;
 unsigned char p;

 } screenchar;

typedef struct {

 screenchar c[25][80];

 } screen;

screen far *video;

struct SREGS sregs;
union REGS inregs, outregs;

unsigned int handle;

int capture;

extern unsigned char CHECK1[6], CHECK2[6];

extern int CHECKFLG;

extern void far RECEIVER();

extern void huge *FIRST, huge *IN, huge *HIGH, huge *LIMIT;

struct {

   unsigned char source[6];
   unsigned char dest[6];
   unsigned long packets;
   unsigned long bytes;
   int changed;

   } traffic[20];

int trafficnext = 0;
int trafficold = 0;

unsigned long totpackets = 0;
unsigned long totbytes = 0;
int totchanged = 0;

unsigned long lostcount = 0;
unsigned long runtcount = 0;


int convhex(arg, addr)

char *arg;
unsigned char *addr;

{

int i, v, ec;

unsigned char *pnt;
char *ipnt;

pnt = addr;
ipnt = arg;
ec = 0;

for (i = 0; i < 6; i++) {

   if(*ipnt >= '0' && *ipnt <= '9') {v = *ipnt - '0';}

     else if (*ipnt >= 'a' && *ipnt <= 'f') {v = *ipnt - 'a' + 10;}

        else if(*ipnt >= 'A' && *ipnt <= 'F') {v = *ipnt - 'A' + 10;}

        else {ec = 1;}

   v = v*16;
   ipnt++;

   if(*ipnt >= '0' && *ipnt <= '9') {v = v + *ipnt - '0';}

     else if (*ipnt >= 'a' && *ipnt <= 'f') {v = v + *ipnt - 'a' + 10;}

        else if(*ipnt >= 'A' && *ipnt <= 'F') {v = v + *ipnt - 'A' + 10;}

        else {ec = 1;}

   *pnt = v;

   ipnt++;
   pnt++;

   }

if (*ipnt) ec = 1;

return (ec);

}

unsigned long fp2addr(void huge *point )

{

return ((((unsigned long) FP_SEG(point)) << 4) +
         ((unsigned long) FP_OFF(point)));

}

void huge *addr2fp(unsigned long addr)

{

return MK_FP((unsigned int) ((addr >> 4) & 0xffff),
              (unsigned int) (addr & 0xf));

}

printhead(pnt)

void huge *pnt;

{

unsigned char far *work;

int i, j;

work = (unsigned char far *) pnt;

printf(" Dest ");

for (i = 0; i < 6 ; i++) {

   j = *work;

   printf("%2.2x ", j);

   work++;

   }

printf("  Source ");

for (i = 0; i < 6; i++) {

   j = *work;

   printf("%2.2x ", j);

   work++;

   }

printf("  Type ");

for (i = 0; i < 2; i++) {

   j = *work;

   printf("%2.2x", j);

   work++;

   }

printf("\n");

}

void putulong(val, line, col)

unsigned long val;
int line,col;

{

   int i,j,k;
   unsigned long ival, jval;
   screenchar far *place;

   place = &(video->c[line][col+9]);
   ival = val;

   for (i = 9; i >= 0; i--) {

      jval = ival / 10L;
      j = ival - jval * 10L;
      place->t = j + '0';
      if (jval == 0L) break;
      ival=jval;
      place--;
      }

/*   for (i--; i >= 0; i--) video->c[line][col+i].t = ' '; */

}

void placetext(text, line, col)

char *text;
int line,col;

{

   screenchar far *place;
   char far *nextchar;

   place = &(video->c[line][col]);
   nextchar = text;

   while (*nextchar != 0) {

      place->t = *nextchar;
      place++;
      nextchar++;

   }

}

void putethaddr(addr, line, col)

unsigned char addr[6];

int line,col;

{

   screenchar far *place;
   int i;
   unsigned char v;

   place = &(video->c[line][col]);

   for (i = 0; i < 6; i++) {

      v = (addr[i] >> 4) & 0xf;
      place->t = (v > 9) ? v + 'A' - 10 : v + '0';
      place++;
      v = addr[i] & 0xf;
      place->t = (v > 9) ? v + 'A' - 10 : v + '0';
      if (i == 5) break;
      place++;
      place->t = ':';
      place++;

   }

}



main(argc, argv)

int argc;
char *argv[];

{

unsigned long heapleft, len, testfirst, testlimit;

unsigned int far *lenpt;

unsigned int lenr;

unsigned char huge *out, far *testout;

unsigned int segleft, firstseg;

unsigned char far *sender;
unsigned char far *receiver;

int i, j;

if (argc > 1) {

   if ((capture = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY)) < 0) {
      puts("Cannot open capture file");
      exit(1);
      }

   }

if (argc > 2) {

   if(convhex(argv[2], &CHECK1[0])) {
      puts("Illegal address");
      exit(1);
      }
   CHECKFLG = 1;
   }

if (argc > 3) {

   if(convhex(argv[3], &CHECK2[0])) {
      puts("Illegal address");
      exit(1);
      }
   CHECKFLG = 2;
   }

segleft = allocmem(0xa000, &firstseg);

if (allocmem(segleft, &firstseg) != -1) {
   puts("Unable to allocate memory");
   exit(1);
   }

FIRST = MK_FP(firstseg, 0);

heapleft = (long) segleft * (long) 16;

video = (screen far *) MK_FP(0xb800, 0);

for (i = 0; i < 25; i++) {

   for (j = 0; j < 80; j++) {

      video->c[i][j].p = 7;
      video->c[i][j].t = ' ';

      }

   }

placetext("Packets", 0, 0);
placetext("Avg 10s", 0, 20);
placetext(".", 0, 35);
placetext("Bytes", 0, 40);
placetext("Avg 10s", 0, 58);
placetext(".", 0, 73);
placetext("Source", 3, 6);
placetext("Destination", 3, 25);
placetext("Packets", 3, 46);
placetext("Bytes", 3, 63);
placetext("Runt Packets", 24, 23);
placetext("from", 24, 48);

IN = FIRST;
HIGH = FIRST;
testfirst = fp2addr(FIRST);
testlimit = testfirst + heapleft;
LIMIT = addr2fp(testlimit);

segread(&sregs);

inregs.h.ah = ACCESS_TYPE;
inregs.h.al = 1;
inregs.x.bx = 0xffff;
inregs.h.dl = 0;
inregs.x.cx = 0;
inregs.x.di = FP_OFF(&RECEIVER);
sregs.es = FP_SEG(&RECEIVER);

int86x(0x60, &inregs, &outregs, &sregs);

handle = outregs.x.ax;

inregs.h.ah = SET_RCV_MODE;
inregs.x.bx = handle;
inregs.x.cx = 6;

int86(0x60, &inregs, &outregs);

out = FIRST;

loop:

if (out != IN) {

  if ((HIGH != FIRST) && (out == HIGH)) {

     out = FIRST;

     goto loop;

     }

  lenpt = (int far *) out;
  lenr = *lenpt;
  testout = out;
  testout += lenr + 6;
  lenpt = (int far *) testout;

  if ((*lenpt != lenr) || (lenr == 0)) {

     placetext("Lost count", 24, 0);
     lostcount++;
     putulong(lostcount, 24, 11);

     out = IN;

     goto loop;

     }

  if(lenr < MINETHB) {

     runtcount++;
     putulong(runtcount, 24, 36);

     if(lenr >= 14) putethaddr(out + 12, 24, 53);

     }

  if(lenr < 14) {

     out += lenr + 8;

     goto loop;

     }

  totbytes += lenr;
  totpackets++;
  totchanged = 1;

  for (i = 0; i < trafficnext; i++) {

     sender = out + 17;
     receiver = out + 11;

     for (j = 5; j >= 0; j--) {

        if(*sender != traffic[i].source[j] ||
           *receiver != traffic[i].dest[j]) goto trynext;

        sender--;
        receiver--;

        }

     traffic[i].packets++;
     traffic[i].bytes += lenr;
     traffic[i].changed = 1;

     goto conndone;

  trynext: ;

     }

  if (trafficnext < 20) {

     for (i = 0; i < 6; i++) {

        traffic[trafficnext].source[i] = *(out + 12 + i);
        traffic[trafficnext].dest[i] = *(out + 6 + i);

        }

     traffic[trafficnext].packets = 1;
     traffic[trafficnext].bytes = lenr;
     traffic[trafficnext].changed = 1;

     trafficnext++;

     }

conndone:

  out += 6;



  out += lenr;

  out += 2;

  goto loop;

  }

if(totchanged != 0) {

   putulong(totpackets, 0, 8);
   putulong(totbytes, 0, 46);
   totchanged = 0;

   for (i = trafficold; i < trafficnext; i++) {

      putethaddr(&traffic[i].source[0], i + 4, 0);
      putethaddr(&traffic[i].dest[0], i + 4, 22);

      }

   trafficold = trafficnext;

   for (i = 0; i < trafficnext; i++) {

      if(traffic[i].changed > 0) {

         putulong(traffic[i].packets, i + 4, 44);
         putulong(traffic[i].bytes, i + 4, 59);

         traffic[i].changed = 0;

         }

      }

   goto loop;

   }

if(kbhit()) goto done;
delay(20);

goto loop;

done:

inregs.h.ah = RELEASE_TYPE;
inregs.x.bx = handle;

int86(0x60, &inregs, &outregs);

if(argc > 1) {

   if (fp2addr(HIGH) > fp2addr(IN)) {

      len = 0;
      out = HIGH;

goback:

      lenpt = (int far *)addr2fp(fp2addr(HIGH) - len - 2);
      lenr = *lenpt;

      if ((fp2addr(HIGH) - len - lenr - 8) > fp2addr(IN)) {

         out = addr2fp(fp2addr(HIGH) - len - lenr - 8);
         len += lenr + 8;

         goto goback;

         }

      if (len > 0) {

         while (len > 1024) {

            write(capture, out, 1024);
            len -= 1024;
            out += 1024;

            }

         write(capture, out, len);

         }

      }

   if (fp2addr(IN) > fp2addr(FIRST)) {

      out = FIRST;
      len = fp2addr(IN) - fp2addr(FIRST);

      while(len > 1024) {

         write(capture, out, 1024);
         len -= 1024;
         out += 1024;

         }

      write(capture, out, len);

      }

   close(capture);

   }

freemem(firstseg);

}

