From 1521d3de58250a9c475995f611bd2cae14741fb2 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Wed, 20 Oct 2010 13:44:52 +0200 Subject: Add helper script pcap2ulog This script uses the Net::Pcap Perl library to parse an pcap file and send packets to ulogd2 throught the UNIXSOCK input module. Signed-off-by: Pierre Chifflier --- contrib/pcap2ulog | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 contrib/pcap2ulog 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 +# +# 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); + + + -- cgit v1.2.3