Simple NetFlow v5 packet parser

 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
#!/usr/bin/perl
###################################
# #
# Simple NetFlow v5 packet parser #
# for ipt_NETFLOW #
# by Alexander Ptitsyn #
# modified by Fd #
# v0.001 (c) 2009 #
# #
###################################
use strict;
use warnings;
use IO::Socket;
my ($packet, $sourceAddress, $sourcePort, $sourceMaskPrefix, $destinationAddress, $destinationPort,
$destinationMaskPrefix, $packets, $octets, $proto, $tcpFlags, $typeOfService, $sourceAS,
$destinationAS, $nextHop, $snmpIn, $snmpOut, $systemUptimeFlowStart, $systemUptimeFlowStop);
my %config = (
hostname => 'localhost',
port => 2055,
proto => 'udp',
headerTemplate => 'nnNNNNCCn',
footerTemplate => 'NNNnnNNNNnnCCCCnnCCn',
);
my $sockObj = IO::Socket::INET->new(
LocalHost => $config{hostname},
LocalPort => $config{port},
Proto => $config{proto},
) || die "Can't open socket: $!";
while ($sockObj->recv($packet,1464)) {
my @header = unpack $config{headerTemplate}, $packet;
my ($flowVersion, $flowCount, $flowSysUptime, $flowUnixSeconds, $flowUnixNanoseconds,
$flowSequence, $flowEngineType, $flowEngineID, $flowSamplingInterval) = (@header)[0..8];
die $! if $flowVersion != 5 && ($flowCount < 0 || $flowCount > 30);
my $Template = $config{headerTemplate};
$Template .= $config{footerTemplate} for 0 .. $flowCount;
my @flow = unpack $Template, $packet;
if ($flowCount > 0) {
for (my $i = 0; $i < $flowCount; $i++) {
$sourceAddress = ip_to_str($flow[9+$i*20]);
$sourcePort = $flow[18+$i*20];
$sourceMaskPrefix = $flow[26+$i*20];
$destinationAddress = ip_to_str($flow[10+$i*20]);
$destinationPort = $flow[19+$i*20];
$destinationMaskPrefix = $flow[27+$i*20];
$packets = $flow[14+$i*20];
$octets = $flow[15+$i*20];
$proto = $flow[22+$i*20];
$tcpFlags = $flow[21+$i*20];
$typeOfService = $flow[23+$i*20];
$sourceAS = $flow[24+$i*20];
$destinationAS = $flow[25+$i*20];
$nextHop = $flow[11+$i*20];
$snmpIn = $flow[12+$i*20];
$snmpOut = $flow[13+$i*20];
$systemUptimeFlowStart = $flow[16+$i*20];
$systemUptimeFlowStop = $flow[17+$i*20];
}
}
}
sub ip_to_str { inet_ntoa( pack( 'N', shift )); }