summaryrefslogtreecommitdiffstats
path: root/contrib/pcap2ulog
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pcap2ulog')
-rwxr-xr-xcontrib/pcap2ulog166
1 files changed, 166 insertions, 0 deletions
diff --git a/contrib/pcap2ulog b/contrib/pcap2ulog
new file mode 100755
index 0000000..d4cd3dc
--- /dev/null
+++ b/contrib/pcap2ulog
@@ -0,0 +1,166 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2009-2010 Pierre Chifflier <chifflier@inl.fr>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the same terms as Perl itself, either Perl version 5.8.4 or,
+# at your option, any later version of Perl 5 you may have available.
+
+use strict;
+
+use IO::Socket;
+use Net::Pcap;
+
+my $ULOGD_SOCKET_MARK = 0x41c90fd4;
+
+my $dumpfile = shift or die "Unable to open pcap file";
+my($pcap_t, $err);
+my($ulogd_client);
+my $socketfile = "/var/run/ulogd2.sock";
+my $data_buffer;
+my $linktype;
+my $proto_offset;
+
+my %linktype_to_offset = (
+ Net::Pcap::DLT_LINUX_SLL => 14,
+ Net::Pcap::DLT_EN10MB => 12,
+);
+
+sub connect_ulogd2 {
+ (-S $socketfile) or die "ulogd2 socket $socketfile does not exist - is ulogd running ?";
+
+ $ulogd_client = IO::Socket::UNIX->new(Peer => $socketfile,
+ Type => SOCK_STREAM ) or die $!;
+ $ulogd_client->autoflush(0);
+}
+
+sub print_padding
+{
+ my ($offset) = @_;
+ my $padding;
+ my $align = 8;
+ my $data;
+
+ $padding = ($align - ($offset % $align)) % $align;
+ #print "offset: $offset padding $padding\n";
+
+ $data = "\0" x $padding;
+ $data_buffer .= $data;
+}
+
+sub process_pkt {
+ my($user, $hdr, $pkt) = @_;
+
+ if (($user ne "xyz") or !defined($hdr) or !defined($pkt)) {
+ print("Bad args passed to callback\n");
+ print("Bad user data\n"), if ($user ne "xyz");
+ print("Bad pkthdr\n"), if (!defined($hdr));
+ print("Bad pkt data\n"), if (!defined($pkt));
+ print("not ok\n");
+ exit;
+ }
+
+ #print "Header: len $hdr->{len}\n";
+ #my $len = length $pkt;
+ #print "Packet length: $len\n";
+
+ my $size = length($pkt) - ($proto_offset+2);
+
+ #my $pcaphdr = unpack ("H*", substr ($pkt, 0, 16));
+ #printf("pcap hdr: $pcaphdr\n");
+ my $proto = unpack ("H*", substr ($pkt, $proto_offset, 2));
+ #printf("proto: $proto\n");
+
+ if ($proto ne "0800") {
+ print "ignoring packet with proto $proto\n";
+ return;
+ }
+
+ #my $ip_firstbyte = unpack ("H*", substr ($pkt, $proto_offset+2, 2));
+ #printf("ip_firstbyte: $ip_firstbyte\n");
+
+ # decode packet for a SLL:
+ # packet type (sent by us: 4)
+ # link layer address type: 1
+ # link layer address length: 6
+ # src dst
+ # protocol (IP, ARP, PPP, SNMP ...)
+ # data
+ my $srcmac = substr ($pkt, 6, 6);
+
+ (my $hex_src = unpack("H*", $srcmac)) =~ s/(..)/$1:/g;
+ chop $hex_src;
+ #printf "source mac: $hex_src\n";
+
+ my $hex_dst = "\0";
+
+ # format data
+ my $data;
+
+ $data_buffer = undef;
+
+ # ulogd packet signature
+ $data = pack ('N', $ULOGD_SOCKET_MARK);
+
+ $data_buffer .= $data;
+
+ my $options_num=2;
+ my $options_len=length($hex_src) + length($hex_dst);
+ # total length (will be filled later)
+ my $total_size = 0;
+ $data = pack ('n', $total_size);
+ $data_buffer .= $data;
+
+ # reserved + payload length + payload
+ $data = pack ('Nna*', 0, $size, substr($pkt,$proto_offset+2,$size));
+ $data_buffer .= $data;
+ print_padding($size);
+
+ # options
+ my $OOB_IN = 2;
+ $data = pack ('NNa*', $OOB_IN, length($hex_src), $hex_src);
+ $data_buffer .= $data;
+ print_padding(length($hex_src));
+ my $OOB_OUT = 3;
+ $data = pack ('NNa*', $OOB_OUT, length($hex_dst), $hex_dst);
+ $data_buffer .= $data;
+ print_padding(length($hex_dst));
+
+ # replace total size in buffer
+ my $l = length($data_buffer) - 4;
+ substr($data_buffer, 4, 2) = pack('n', $l);
+
+ #(my $hex = unpack("H*", $data_buffer)) =~ s/(..)/$1 /g;
+ #print "$l will be encoded as " . unpack("H*", pack('n', $l)) . "\n";
+ #print $hex, "\n";
+
+ print $ulogd_client $data_buffer;
+
+ $ulogd_client->flush;
+
+ #exit;
+}
+
+
+connect_ulogd2 or die $!;
+
+$pcap_t = Net::Pcap::open_offline($dumpfile, \$err);
+if (!defined($pcap_t)) {
+ print("Net::Pcap::dump_open failed: ", Net::Pcap::geterr($pcap_t), "\n");
+ exit;
+}
+
+$linktype = Net::Pcap::pcap_datalink($pcap_t);
+
+if (not exists $linktype_to_offset{$linktype}) {
+ print("Unsupported link type ", Net::Pcap::pcap_datalink_val_to_name($linktype), "\n");
+ exit 1;
+}
+
+$proto_offset = $linktype_to_offset{$linktype};
+
+Net::Pcap::loop($pcap_t, -1, \&process_pkt, "xyz");
+Net::Pcap::close($pcap_t);
+
+
+