1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 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);
|