#! /usr/bin/perl -w

#
# Accept intercept data from l2tpns, write to a file in pcap format
# (http://wiki.ethereal.com/Development/LibpcapFileFormat) suffixed
# with timestamp.  Killing the process with SIGHUP causes a new file
# to be opened.
#

use strict;
use IO::File;
use IO::Socket;
use Time::HiRes 'gettimeofday';

(my $cmd = $0) =~ s!.*/!!;

die "Usage: $cmd PREFIX PORT\n" unless @ARGV == 2 and $ARGV[1] =~ /^\d+$/;

my ($prefix, $port) = @ARGV;
my $sock = IO::Socket::INET->new(
    LocalPort	=> $port,
    Proto	=> 'udp',
    Type	=> SOCK_DGRAM,
) or die "$cmd: can't bind to port $port ($!)\n";

my $restart = 0;
$SIG{HUP} = sub { $restart++ };

my $header = pack LSSlLLL =>
    0xa1b2c3d4,	# magic no
    2,		# version maj
    4,		# version min
    0,		# timezone offset (GMT)
    0,		# timestamp accuracy
    65536,	# snaplen
    12;		# link type (RAW_IP)

my $cap;
my $buf;
my $file;
for (;;)
{
    unless ($cap)
    {
	$file = $prefix . time;
	$cap = IO::File->new("> $file")
	    or die "$0: can't create capture file $file ($!)\n";

	$cap->print($header)
	    or die "$0: error writing to $file ($!)\n";
    }

    while ($sock->recv($buf, 1600))
    {
	$cap->print(
	    # packet header: sec, usec, included size, original size
	    (pack LLLL => (gettimeofday), (length $buf) x 2),
	    $buf
	) or die "$0: error writing to $file ($!)\n";
    }

    if ($restart)
    {
	$restart = 0;
	$cap->close;
	undef $cap;
    }
}
