/*
 *   avm2pcap - convert AVM capture format to libpcap dump format
 *
 *   Copyright (C) 2004  Enrik Berkhan <Enrik.Berkhan@inka.de>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/* compile with "gcc -W -Wall avm2pcap.c -o avm2pcap -lpcap" */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <pcap.h>

char errbuf[PCAP_ERRBUF_SIZE];
char buf[2000];

struct cap_head {
  uint16_t magic;
  uint16_t type;
  unsigned char desc[12];
};

struct packet_head {
  uint16_t magic;
  uint16_t type;
  uint32_t f1, f2, f3;
  uint32_t sec, usec;   /* time since boot? */
  uint32_t len, caplen; /* not sure what is what, identical in my dumps */
};

int
main(int argc, char *argv[])
{
  size_t res;
  struct cap_head *head;
  struct packet_head *packet;
  struct pcap_pkthdr pcaphdr;
  size_t readlen;
  pcap_t *pcap;
  pcap_dumper_t *dumper;

  errbuf[0] = 0;
  pcap = pcap_open_dead(DLT_EN10MB, 1514);
  if (!pcap) {
    perror(errbuf);
    return(1);
  }
  if (strlen(errbuf)) {
    fprintf(stderr, "pcap warning: %s\n", errbuf);
  }
  errbuf[0] = 0;
  dumper = pcap_dump_open(pcap, "-");
  if (!dumper) {
    perror(errbuf);
    return(1);
  }
  if (strlen(errbuf)) {
    fprintf(stderr, "pcap warning: %s\n", errbuf);
  }

  if ((res = fread(buf, 64, 1, stdin)) < 1) {
    if (feof(stdin)) {
      fprintf(stderr, "short read\n");
      return(1);
    }
    perror("fread");
    return(1);
  }
  head = (struct cap_head *)buf;
  if (head->magic != 0x4711 || head->type != 0x0 ||
      strcmp(head->desc, "AVM Capture")) {
    fprintf(stderr, "bad file header\n");
    return(1);
  }
  while (!feof(stdin) && !ferror(stdin)) {
    if ((res = fread(buf, 64, 1, stdin)) < 1)
      continue;
    packet = (struct packet_head *)buf;
    if (packet->magic != 0x4711 || packet->type != 0x40) {
      fprintf(stderr, "unknown packet: magic %x, type %x\n",
	      packet->magic, packet->type);
      pcap_dump_close(dumper);
      return(1);
    }
    /* this should be relative to the fbox's boot time */
    pcaphdr.ts.tv_sec = packet->sec;
    pcaphdr.ts.tv_usec = packet->usec;
    pcaphdr.caplen = packet->caplen;
    pcaphdr.len = packet->len;
    readlen = (((packet->caplen+15)/16)*16);
    if ((res = fread(buf, readlen, 1, stdin)) < 1)
      continue;
    pcap_dump((u_char*)dumper, &pcaphdr, buf);
  }
  pcap_dump_close(dumper);
  if (ferror(stdin)) {
    perror("fread");
    return(1);
  }
  return 0;
}

