#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

#define SIMMAGIC 0xfafa
const unsigned short simmagic=SIMMAGIC;
time_t sotime;
clock_t one, start;
unsigned short length;
unsigned short nlength;
FILE *fp;
char name[256];
enum { FALSE, TRUE };
enum { OLD, NEW };
int tform = OLD;
unsigned char buf[2048];
int ppppkt = FALSE;
int count = 0;

void print_tcp( unsigned char **pdp, unsigned short *plen)
{
   unsigned char *dp = *pdp;
   unsigned short len = *plen;
   struct tcphdr *p = (struct tcphdr *)dp;
   printf("TCP DEST PORT: %d\n",ntohs(p->dest));
   printf("TCP SRC  PORT: %d\n",ntohs(p->source));
   printf("TCP SEQ      : %d\n",ntohl(p->seq));
   printf("TCP ACK      : %d\n",ntohl(p->ack_seq));
   printf("TCP WINDOW   : %d\n",ntohs(p->window));
   printf("TCP URG      : %d\n",ntohs(p->urg_ptr));
   *pdp += sizeof(struct tcphdr);
   *plen -= sizeof(struct tcphdr);
}

void print_udp( unsigned char **pdp, unsigned short *plen)
{
   unsigned char *dp = *pdp;
   unsigned short len = *plen;
   struct udphdr *p = (struct udphdr *)dp;
   printf("UDP DEST PORT: %d\n",ntohs(p->dest));
   printf("UDP SRC  PORT: %d\n",ntohs(p->source));
   *pdp += sizeof(struct udphdr);
   *plen -= sizeof(struct udphdr);
}


void print_icmp( unsigned char **pdp, unsigned short *plen)
{
   unsigned char *dp = *pdp;
   unsigned short len = *plen;
   struct icmphdr *p = (struct icmphdr *)dp;
   printf("ICMP TYPE= %d\n",p->type);
   printf("ICMP CODE= %d\n",p->code);
   printf("  either\n");
   printf("  ID=%d\n",ntohs(p->un.echo.id));
   printf("  SEQ=%d\n",ntohs(p->un.echo.sequence));
   printf("  or\n");
   printf("  GATEWAY=%s\n",inet_ntoa(p->un.gateway));
   printf("  or\n");
   printf("  FRAG MTU=%d\n",ntohs(p->un.frag.mtu));
   *pdp += sizeof(struct icmphdr);
   *plen -= sizeof(struct icmphdr);
}

void displaytime(clock_t m)
{
   printf("COUNT: %05d SEC=%5d\n",count,m/CLK_TCK);
}

void displaylength(unsigned int len)
{
   printf("ACT. READ LENGTH= %d\n",len);
}
void displaybuf( unsigned char b[], unsigned short len)
{
   int i;
   struct iphdr *p;
   struct ether_header *pe;
   unsigned char *dp;
   unsigned short left;
   int col;
   
   if (!ppppkt)
   {
      pe = (struct ether_header *)b;
      p = (struct iphdr *)( b + ETH_HLEN);
      printf("ETH DEST: %s\n",ether_ntoa((struct ether_addr *)pe->ether_dhost));
      printf("ETH SRC : %s\n",ether_ntoa((struct ether_addr *)pe->ether_shost)); 
      printf("ETH TYPE: %04X\n",pe->ether_type);
      
  } 
   else
      p = (struct iphdr *) b;
   printf("IP DEST: %s\n",inet_ntoa(p->daddr));
   printf("IP SRC : %s\n",inet_ntoa(p->saddr));
   printf("PROTOC : %d\n",p->protocol);
   printf("TTL    : %d\n",p->ttl);
   printf("TOS    : %d\n",p->tos);
   printf("HEADLEN: %d\n",p->ihl);
   printf("TOT_LEN: %d\n",ntohs(p->tot_len));
   printf("Struct Len=%d\n",sizeof(struct iphdr));
   dp = (unsigned char *)p + /*p->ihl*/  + sizeof(struct iphdr);
   left = length /* - p->ihl */ - sizeof(struct iphdr) ;
   switch (p->protocol)
   {
      case 6: /* TCP */
         printf("TCP PROTOCOL\n");
         print_tcp(&dp,&left);
         break;
      case 17: /* UDP */
         printf("UDP PROTOCOL\n");
         print_udp(&dp,&left);
         break;
      case 1:  /* ICMP */
         printf("ICMP PROTOCOL\n");
         print_icmp(&dp,&left);
         break;
      default:
         printf("Unusual Protocol\n");
         
   }
   col = 0;
   for (i=0;i<left;i++)
   {
      if (isprint(dp[i]))
         putchar(dp[i]);
      else
         putchar('.');
      col++;
      if (col>=72)
      {
         putchar('\n');
         col = 0;
      }
   }
   printf("\n*************************************\n");
}

int main(int argc, char *argv[])
{
   int st;
   int done = FALSE;
   if (argc<2)
   {
      printf("Please give filename for ethernet data on command line\n");
      return(1);
   }
   if ((fp = fopen(argv[1],"r"))==NULL)
   {
      perror(argv[1]);
      return(2);
   }
      /* Read start time??? or offset time... based on NEW or OLD format
      
      */
   fread(&sotime,1,sizeof(sotime),fp);
   fread(&nlength,1,sizeof(nlength),fp);
   length = ntohs(nlength);
   if (nlength == simmagic)
   {
         /* New format.... Mark as such... */
      printf("NEW FILE FORMAT\n");
      printf("TIME=%s\n",ctime(&sotime));
      tform = NEW;
      fread(&start,1,sizeof(sotime),fp);
      fread(&nlength,1,sizeof(nlength),fp);
      length = ntohs(nlength);
   }
   else
      start = (clock_t)sotime;
   displaytime(start);
   displaylength(length);
   while (!done)
   {
      /* Read buf */
      st = fread(buf,1,length,fp);
      if (st<0)
      {
         perror("Read file");
         break;
      }
      if (st!=length)
      {
         printf("At end of file...\n");
         done = TRUE;
      }
      displaybuf(buf,length);
      fflush(stdout);
      if (tform==NEW)
      {
         fread(&nlength,1,sizeof(nlength),fp);
         fread(&length,1,sizeof(length),fp); /* SIMMAGIC READ */
         if (length!=simmagic)
            printf("FILE FORMAT ERROR\n");
      }
      fread(&sotime,1,sizeof(sotime),fp);
      fread(&nlength,1,sizeof(nlength),fp);
      length = ntohs(nlength);
      count++;
      displaytime(sotime);  
      displaylength(length);
   }
   return (0);
}
   
