#!/usr/bin/perl
# $Id: kismet2pcap.pl 9 2008-02-13 21:00:07Z chris $

# See http://svn.kismetwireless.net/code/trunk/packetstream.h
# and http://wiki.wireshark.org/Development/LibpcapFileFormat


use strict;
use warnings;

use Carp;

die "Usage $0 infile outfile.pcap" unless (scalar @ARGV == 2);

my ($FHin, $FHout);

if ($ARGV[0] eq "-") { $FHin = *STDIN; } else { open ($FHin, "<", $ARGV[0]); }
if ($ARGV[1] eq "-") { $FHout = *STDOUT; } else { open ($FHout, ">", $ARGV[1]); }

# Magic, Major Version, Minor Version, TZ, Timestamp Accuracy, Packet Size, Data Link Type (105 is IEEE 802.11) 
print $FHout pack("Nn2N4", 0xa1b2c3d4, 2, 4, 0, 0, 65536, 105);

while (!eof($FHin)) {
    # stream_frame_header
    read($FHin, my $stream_frame_header, 9);
 
    my ($frame_sentinel, $frame_type, $frame_len) = unpack("NCN", $stream_frame_header);

    if ($frame_sentinel != 0xdecafbad) {
	croak "Lost sync";
    } elsif ($frame_type != 2) {
	if ($frame_type != 1) {
	    carp "Unknown frame type, $frame_type";
	}
	# Read rather than seek in case we're dealing with a pipe
	read($FHin, my $tmp, $frame_len);
	next;
    }

    # stream_packet_header
    read($FHin, my $stream_packet, $frame_len);
    my ($header_len, $drone_version, $len, $caplen, undef, $tv_sec, undef, $tv_usec) = unpack ("NnN6", $stream_packet);

    if ($header_len + $caplen > length $stream_packet) {
	carp "Skipping truncated packet";
    } else {
	print $FHout pack("N4", $tv_sec, $tv_usec, $len, $caplen);
	print $FHout substr($stream_packet, $header_len);
    }
}
