#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pcap/pcap.h>
#include <arpa/inet.h>

#define B	4096

int out;
int npkts = 0;

struct qtag {
  uint16_t tpid;
  uint16_t tci;
  uint16_t et;
};
struct ether {
  uint8_t dst[6];
  uint8_t src[6];
  union {
    struct qtag q;
    uint16_t et;
  };
};

char *ether_addr(uint8_t addr[], char *buf)
{
  sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
	  addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
  return buf;
}


void ether(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
  char bufsrc[20], bufdst[20];
  struct ether e;
  uint16_t etype;
  uint32_t crc;

  if (h->caplen > h->len) fprintf(stderr,"Truncated packet\n");
  memcpy(&e, bytes, sizeof(e));
  etype = ntohs(e.et);
  if (etype == 0x8100) {
    fprintf(stderr,"VLan tag encountered.\n");
    etype = ntohs(e.q.et);
  }
  if (h->len < 1900) return;
  printf(" ether: %s -> %s (%d/%d)\n", ether_addr(e.src,bufsrc), ether_addr(e.dst,bufdst), h->caplen, h->len);
  npkts++;
}

int main(int argc, char *argv[])
{
  char buf[B];
  pcap_t *p;
  
  if (argc < 2) {
    fprintf(stderr,"Usage: pc <savefile>\n");
    exit(0);
  }
//   out = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666);
//   if (out < 0) {
//     fprintf(stderr,"Error creating output file.\n");
//     exit(1);
//   }
  p = pcap_open_offline(argv[1], buf);
  if (p == NULL) {
    fprintf(stderr,"Error opening pcap savefile: %s\n", buf);
    exit(1);
  }
  pcap_set_snaplen(p, 65535);
  pcap_loop(p, -1, ether, NULL);

  printf("Processed %d packets.\n", npkts);
}