File Coverage

blib/lib/Net/sFlow.pm
Criterion Covered Total %
statement 372 1252 29.7
branch 0 292 0.0
condition 0 18 0.0
subroutine 124 151 82.1
pod 1 1 100.0
total 497 1714 29.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #
3             #
4             # My first perl project ;)
5             # Elisa Jasinska
6             # With many thanks to Tobias Engel for his help and support!
7             #
8             #
9             # sFlow.pm - 2009/01/20
10             #
11             # Please send comments or bug reports to
12             #
13             #
14             # sFlow v4 RFC 3176
15             # http://www.ietf.org/rfc/rfc3176.txt
16             # Dataformat: http://jasinska.de/sFlow/sFlowV4FormatDiagram/
17             #
18             # sFlow v5 Memo
19             # http://sflow.org/sflow_version_5.txt
20             # Dataformat: http://jasinska.de/sFlow/sFlowV5FormatDiagram/
21             #
22             #
23             # Copyright (c) 2006 - 2009 AMS-IX B.V.
24             #
25             # This package is free software and is provided "as is" without express
26             # or implied warranty. It may be used, redistributed and/or modified
27             # under the terms of the Perl Artistic License (see
28             # http://www.perl.com/perl/misc/Artistic.html)
29             #
30              
31              
32             package Net::sFlow;
33              
34              
35 1     1   39216 use strict;
  1         3  
  1         39  
36 1     1   5 use warnings;
  1         2  
  1         27  
37 1     1   1121 use bytes;
  1         13  
  1         4  
38              
39             require Exporter;
40             # 64bit integers
41 1     1   8837 use Math::BigInt;
  1         31039  
  1         8  
42              
43              
44             our $VERSION = '0.11';
45             our @EXPORT_OK = qw(decode);
46              
47              
48             # constants
49              
50 1     1   22731 use constant SFLOWv4 => 4;
  1         2  
  1         55  
51 1     1   6 use constant SFLOWv5 => 5;
  1         2  
  1         40  
52              
53 1     1   5 use constant UNKNOWNIPVERSION => 0;
  1         3  
  1         58  
54 1     1   4 use constant IPv4 => 1;
  1         2  
  1         39  
55 1     1   7 use constant IPv6 => 2;
  1         2  
  1         43  
56              
57             # sFlow v4 constants
58              
59 1     1   7 use constant FLOWSAMPLE_SFLOWv4 => 1;
  1         1  
  1         36  
60 1     1   5 use constant COUNTERSAMPLE_SFLOWv4 => 2;
  1         2  
  1         34  
61              
62 1     1   5 use constant HEADERDATA_SFLOWv4 => 1;
  1         2  
  1         37  
63 1     1   7 use constant IPv4DATA_SFLOWv4 => 2;
  1         2  
  1         53  
64 1     1   13 use constant IPv6DATA_SFLOWv4 => 3;
  1         2  
  1         40  
65              
66 1     1   5 use constant SWITCHDATA_SFLOWv4 => 1;
  1         1  
  1         33  
67 1     1   5 use constant ROUTERDATA_SFLOWv4 => 2;
  1         1  
  1         51  
68 1     1   5 use constant GATEWAYDATA_SFLOWv4 => 3;
  1         1  
  1         41  
69 1     1   5 use constant USERDATA_SFLOWv4 => 4;
  1         1  
  1         32  
70 1     1   4 use constant URLDATA_SFLOWv4 => 5;
  1         1  
  1         38  
71              
72 1     1   5 use constant GENERICCOUNTER_SFLOWv4 => 1;
  1         2  
  1         32  
73 1     1   4 use constant ETHERNETCOUNTER_SFLOWv4 => 2;
  1         2  
  1         39  
74 1     1   4 use constant TOKENRINGCOUNTER_SFLOWv4 => 3;
  1         2  
  1         41  
75 1     1   5 use constant FDDICOUNTER_SFLOWv4 => 4;
  1         2  
  1         31  
76 1     1   5 use constant VGCOUNTER_SFLOWv4 => 5;
  1         1  
  1         45  
77 1     1   5 use constant WANCOUNTER_SFLOWv4 => 6;
  1         1  
  1         39  
78 1     1   5 use constant VLANCOUNTER_SFLOWv4 => 7;
  1         1  
  1         48  
79              
80             # sFlow v5 constants
81              
82 1     1   6 use constant FLOWSAMPLE_SFLOWv5 => 1;
  1         2  
  1         39  
83 1     1   6 use constant COUNTERSAMPLE_SFLOWv5 => 2;
  1         1  
  1         33  
84 1     1   13 use constant EXPANDEDFLOWSAMPLE_SFLOWv5 => 3;
  1         1  
  1         42  
85 1     1   5 use constant EXPANDEDCOUNTERSAMPLE_SFLOWv5 => 4;
  1         1  
  1         40  
86 1     1   6 use constant FOUNDRY_ACL_SFLOWv5 => 1991;
  1         1  
  1         39  
87              
88 1     1   13 use constant HEADERDATA_SFLOWv5 => 1;
  1         2  
  1         43  
89 1     1   4 use constant ETHERNETFRAMEDATA_SFLOWv5 => 2;
  1         2  
  1         55  
90 1     1   5 use constant IPv4DATA_SFLOWv5 => 3;
  1         2  
  1         41  
91 1     1   5 use constant IPv6DATA_SFLOWv5 => 4;
  1         19  
  1         38  
92 1     1   5 use constant SWITCHDATA_SFLOWv5 => 1001;
  1         2  
  1         42  
93 1     1   4 use constant ROUTERDATA_SFLOWv5 => 1002;
  1         2  
  1         39  
94 1     1   5 use constant GATEWAYDATA_SFLOWv5 => 1003;
  1         2  
  1         43  
95 1     1   5 use constant USERDATA_SFLOWv5 => 1004;
  1         1  
  1         46  
96 1     1   5 use constant URLDATA_SFLOWv5 => 1005;
  1         2  
  1         45  
97 1     1   5 use constant MPLSDATA_SFLOWv5 => 1006;
  1         1  
  1         39  
98 1     1   5 use constant NATDATA_SFLOWv5 => 1007;
  1         1  
  1         32  
99 1     1   5 use constant MPLSTUNNEL_SFLOWv5 => 1008;
  1         1  
  1         38  
100 1     1   5 use constant MPLSVC_SFLOWv5 => 1009;
  1         1  
  1         33  
101 1     1   4 use constant MPLSFEC_SFLOWv5 => 1010;
  1         2  
  1         49  
102 1     1   5 use constant MPLSLVPFEC_SFLOWv5 => 1011;
  1         1  
  1         42  
103 1     1   5 use constant VLANTUNNEL_SFLOWv5 => 1012;
  1         1  
  1         54  
104              
105 1     1   5 use constant GENERICCOUNTER_SFLOWv5 => 1;
  1         1  
  1         39  
106 1     1   5 use constant ETHERNETCOUNTER_SFLOWv5 => 2;
  1         1  
  1         31  
107 1     1   5 use constant TOKENRINGCOUNTER_SFLOWv5 => 3;
  1         1  
  1         38  
108 1     1   4 use constant VGCOUNTER_SFLOWv5 => 4;
  1         2  
  1         39  
109 1     1   4 use constant VLANCOUNTER_SFLOWv5 => 5;
  1         2  
  1         32  
110 1     1   5 use constant PROCESSORCOUNTER_SFLOWv5 => 1001;
  1         2  
  1         46  
111              
112             # ethernet header constants
113              
114 1     1   5 use constant ETH_TYPE_UNK => '0000';
  1         2  
  1         44  
115 1     1   11 use constant ETH_TYPE_XNS_IDP => '0600';
  1         1  
  1         42  
116 1     1   4 use constant ETH_TYPE_IP => '0800';
  1         3  
  1         41  
117 1     1   4 use constant ETH_TYPE_X25L3 => '0805';
  1         2  
  1         37  
118 1     1   5 use constant ETH_TYPE_ARP => '0806';
  1         2  
  1         46  
119 1     1   5 use constant ETH_TYPE_VINES_IP => '0bad';
  1         1  
  1         209  
120 1     1   5 use constant ETH_TYPE_VINES_ECHO => '0baf';
  1         2  
  1         36  
121 1     1   4 use constant ETH_TYPE_TRAIN => '1984';
  1         2  
  1         41  
122 1     1   3 use constant ETH_TYPE_CGMP => '2001';
  1         2  
  1         41  
123 1     1   5 use constant ETH_TYPE_CENTRINO_PROMISC => '2452';
  1         8  
  1         36  
124 1     1   4 use constant ETH_TYPE_3C_NBP_DGRAM => '3c07';
  1         1  
  1         47  
125 1     1   4 use constant ETH_TYPE_EPL_V1 => '3e3f';
  1         2  
  1         37  
126 1     1   5 use constant ETH_TYPE_DEC => '6000';
  1         2  
  1         49  
127 1     1   4 use constant ETH_TYPE_DNA_DL => '6001';
  1         2  
  1         40  
128 1     1   5 use constant ETH_TYPE_DNA_RC => '6002';
  1         1  
  1         34  
129 1     1   5 use constant ETH_TYPE_DNA_RT => '6003';
  1         1  
  1         38  
130 1     1   5 use constant ETH_TYPE_LAT => '6004';
  1         1  
  1         47  
131 1     1   5 use constant ETH_TYPE_DEC_DIAG => '6005';
  1         2  
  1         38  
132 1     1   5 use constant ETH_TYPE_DEC_CUST => '6006';
  1         2  
  1         41  
133 1     1   5 use constant ETH_TYPE_DEC_SCA => '6007';
  1         2  
  1         33  
134 1     1   5 use constant ETH_TYPE_ETHBRIDGE => '6558';
  1         1  
  1         39  
135 1     1   4 use constant ETH_TYPE_RAW_FR => '6559';
  1         1  
  1         34  
136 1     1   5 use constant ETH_TYPE_RARP => '8035';
  1         1  
  1         42  
137 1     1   4 use constant ETH_TYPE_DEC_LB => '8038';
  1         2  
  1         40  
138 1     1   38 use constant ETH_TYPE_DEC_LAST => '8041';
  1         2  
  1         38  
139 1     1   5 use constant ETH_TYPE_APPLETALK => '809b';
  1         2  
  1         49  
140 1     1   5 use constant ETH_TYPE_SNA => '80d5';
  1         1  
  1         58  
141 1     1   5 use constant ETH_TYPE_AARP => '80f3';
  1         2  
  1         93  
142 1     1   5 use constant ETH_TYPE_VLAN => '8100';
  1         2  
  1         45  
143 1     1   4 use constant ETH_TYPE_IPX => '8137';
  1         1  
  1         35  
144 1     1   4 use constant ETH_TYPE_SNMP => '814c';
  1         1  
  1         42  
145 1     1   4 use constant ETH_TYPE_WCP => '80ff';
  1         1  
  1         108  
146 1     1   4 use constant ETH_TYPE_STP => '8181';
  1         2  
  1         37  
147 1     1   4 use constant ETH_TYPE_ISMP => '81fd';
  1         2  
  1         42  
148 1     1   5 use constant ETH_TYPE_ISMP_TBFLOOD => '81ff';
  1         1  
  1         35  
149 1     1   4 use constant ETH_TYPE_IPv6 => '86dd';
  1         2  
  1         42  
150 1     1   5 use constant ETH_TYPE_WLCCP => '872d';
  1         2  
  1         50  
151 1     1   5 use constant ETH_TYPE_MAC_CONTROL => '8808';
  1         2  
  1         48  
152 1     1   5 use constant ETH_TYPE_SLOW_PROTOCOLS => '8809';
  1         2  
  1         48  
153 1     1   5 use constant ETH_TYPE_PPP => '880b';
  1         1  
  1         44  
154 1     1   4 use constant ETH_TYPE_COBRANET => '8819';
  1         2  
  1         54  
155 1     1   5 use constant ETH_TYPE_MPLS => '8847';
  1         2  
  1         34  
156 1     1   4 use constant ETH_TYPE_MPLS_MULTI => '8848';
  1         2  
  1         55  
157 1     1   5 use constant ETH_TYPE_FOUNDRY => '885a';
  1         2  
  1         43  
158 1     1   4 use constant ETH_TYPE_PPPOED => '8863';
  1         1  
  1         35  
159 1     1   5 use constant ETH_TYPE_PPPOES => '8864';
  1         2  
  1         52  
160 1     1   5 use constant ETH_TYPE_INTEL_ANS => '886d';
  1         1  
  1         36  
161 1     1   4 use constant ETH_TYPE_MS_NLB_HEARTBEAT => '886f';
  1         9  
  1         41  
162 1     1   5 use constant ETH_TYPE_CDMA2000_A10_UBS => '8881';
  1         2  
  1         44  
163 1     1   5 use constant ETH_TYPE_EAPOL => '888e';
  1         2  
  1         35  
164 1     1   5 use constant ETH_TYPE_PROFINET => '8892';
  1         1  
  1         48  
165 1     1   5 use constant ETH_TYPE_HYPERSCSI => '889a';
  1         1  
  1         1474  
166 1     1   7 use constant ETH_TYPE_CSM_ENCAPS => '889b';
  1         1  
  1         42  
167 1     1   5 use constant ETH_TYPE_TELKONET => '88a1';
  1         2  
  1         39  
168 1     1   4 use constant ETH_TYPE_AOE => '88a2';
  1         2  
  1         38  
169 1     1   5 use constant ETH_TYPE_EPL_V2 => '88ab';
  1         2  
  1         38  
170 1     1   5 use constant ETH_TYPE_BRDWALK => '88ae';
  1         1  
  1         39  
171 1     1   4 use constant ETH_TYPE_IEEE802_OUI_EXTENDED => '88b7';
  1         2  
  1         37  
172 1     1   4 use constant ETH_TYPE_IEC61850_GOOSE => '88b8';
  1         2  
  1         36  
173 1     1   4 use constant ETH_TYPE_IEC61850_GSE => '88b9';
  1         2  
  1         37  
174 1     1   4 use constant ETH_TYPE_IEC61850_SV => '88ba';
  1         2  
  1         37  
175 1     1   5 use constant ETH_TYPE_TIPC => '88ca';
  1         1  
  1         44  
176 1     1   5 use constant ETH_TYPE_RSN_PREAUTH => '88c7';
  1         2  
  1         43  
177 1     1   5 use constant ETH_TYPE_LLDP => '88cc';
  1         2  
  1         42  
178 1     1   4 use constant ETH_TYPE_3GPP2 => '88d2';
  1         2  
  1         36  
179 1     1   5 use constant ETH_TYPE_MRP => '88e3';
  1         1  
  1         50  
180 1     1   5 use constant ETH_TYPE_LOOP => '9000';
  1         1  
  1         43  
181 1     1   5 use constant ETH_TYPE_RTMAC => '9021';
  1         2  
  1         44  
182 1     1   5 use constant ETH_TYPE_RTCFG => '9022';
  1         2  
  1         59  
183 1     1   5 use constant ETH_TYPE_LLT => 'cafe';
  1         2  
  1         45  
184 1     1   4 use constant ETH_TYPE_FCFT => 'fcfc';
  1         2  
  1         12180  
185              
186              
187              
188             #############################################################################
189             sub decode {
190             #############################################################################
191              
192 0     0 1   my $sFlowDatagramPacked = shift;
193 0           my %sFlowDatagram = ();
194 0           my @sFlowSamples = ();
195 0           my @errors = ();
196 0           my $error = undef;
197 0           my $subProcessed = undef;
198              
199 0           my $offset = 0;
200              
201 0           ($sFlowDatagram{sFlowVersion},
202             $sFlowDatagram{AgentIpVersion}) =
203             unpack('NN', $sFlowDatagramPacked);
204              
205 0           $offset += (2 * 4);
206              
207 0           ($subProcessed, $error) =
208             &_decodeIpAddress(
209             \$offset,
210             \$sFlowDatagramPacked,
211             \%sFlowDatagram,
212             undef,
213             \@sFlowSamples,
214             $sFlowDatagram{AgentIpVersion},
215             'AgentIp',
216             1,
217             );
218              
219 0 0         unless ($subProcessed) {
220 0           push @errors, $error;
221 0           %sFlowDatagram = ();
222 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
223             }
224              
225              
226             ####### sFlow V4 #######
227              
228 0 0         if ($sFlowDatagram{sFlowVersion} <= SFLOWv4) {
    0          
229              
230             (undef,
231 0           $sFlowDatagram{datagramSequenceNumber},
232             $sFlowDatagram{agentUptime},
233             $sFlowDatagram{samplesInPacket}) =
234             unpack("a$offset N3", $sFlowDatagramPacked);
235              
236 0           $offset += (3 * 4);
237              
238             # boundcheck for $sFlowDatagram{samplesInPacket}
239             # $sFlowDatagram{samplesInPacket} * 4
240             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
241              
242 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
243             $sFlowDatagram{samplesInPacket} * 4) {
244              
245             # error $sFlowDatagram{samplesInPacket} too big
246 0           $error = "ERROR: [sFlow.pm] Datagram: Samples in packet count too big "
247             . "- rest of the datagram skipped";
248              
249 0           push @errors, $error;
250 0           pop @sFlowSamples;
251 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
252              
253             } elsif ($sFlowDatagram{samplesInPacket} < 0) {
254              
255             # error $sFlowDatagram{samplesInPacket} too small
256 0           $error = "ERROR: [sFlow.pm] Datagram: Samples in packet count too small "
257             . "- rest of the datagram skipped";
258              
259 0           push @errors, $error;
260 0           pop @sFlowSamples;
261 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
262              
263             } else {
264              
265             # parse samples
266 0           for my $samplesCount (0 .. $sFlowDatagram{samplesInPacket} - 1) {
267              
268 0           my %sFlowSample = ();
269 0           push @sFlowSamples, \%sFlowSample;
270              
271             (undef,
272 0           $sFlowSample{sampleType}) =
273             unpack("a$offset N", $sFlowDatagramPacked);
274              
275 0           $offset += 4;
276              
277              
278             # FLOWSAMPLE
279 0 0         if ($sFlowSample{sampleType} == FLOWSAMPLE_SFLOWv4) {
    0          
280              
281             (undef,
282 0           $sFlowSample{sampleSequenceNumber}) =
283             unpack("a$offset N", $sFlowDatagramPacked);
284              
285 0           $offset += 4;
286              
287 0           my $sourceId = undef;
288              
289             (undef,
290 0           $sourceId,
291             $sFlowSample{samplingRate},
292             $sFlowSample{samplePool},
293             $sFlowSample{drops},
294             $sFlowSample{inputInterface},
295             $sFlowSample{outputInterface},
296             $sFlowSample{packetDataType}) =
297             unpack("a$offset N7", $sFlowDatagramPacked);
298              
299 0           $offset += 28;
300              
301 0           $sFlowSample{sourceIdType} = $sourceId >> 24;
302 0           $sFlowSample{sourceIdIndex} = $sourceId & 2 ** 24 - 1;
303              
304             # packet data type: header
305 0 0         if ($sFlowSample{packetDataType} == HEADERDATA_SFLOWv4) {
    0          
    0          
306              
307 0           ($subProcessed, $error) =
308             &_decodeHeaderData(
309             \$offset,
310             \$sFlowDatagramPacked,
311             \%sFlowDatagram,
312             \%sFlowSample,
313             \@sFlowSamples,
314             );
315              
316 0 0         unless ($subProcessed) {
317 0           push @errors, $error;
318             }
319             }
320              
321             # packet data type: IPv4
322             elsif ($sFlowSample{packetDataType} == IPv4DATA_SFLOWv4) {
323 0           &_decodeIPv4Data(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
324             }
325              
326             # packet data type: IPv6
327             elsif ($sFlowSample{packetDataType} == IPv6DATA_SFLOWv4){
328 0           &_decodeIPv6Data(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
329             }
330              
331             else {
332            
333 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp}, "
334             . "Datagram: $sFlowDatagram{datagramSequenceNumber} - Unknown packet data type: "
335             . "$sFlowSample{packetDataType} - rest of the datagram skipped";
336            
337 0           push @errors, $error;
338 0           pop @sFlowSamples;
339 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
340             }
341              
342             (undef,
343 0           $sFlowSample{extendedDataInSample}) =
344             unpack("a$offset N", $sFlowDatagramPacked);
345              
346 0           $offset += 4;
347              
348             # boundcheck for $sFlowSample{extendedDataInSample}
349             # $sFlowSample{extendedDataInSample} * 4
350             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
351              
352 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
353             $sFlowSample{extendedDataInSample} * 4) {
354              
355             # error $sFlowSample{extendedDataInSample} too big
356 0           $error = "ERROR: [sFlow.pm] Datagram: Extended data in sample count too big "
357             . "- rest of the datagram skipped";
358              
359 0           push @errors, $error;
360 0           pop @sFlowSamples;
361 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
362              
363             } elsif ($sFlowSample{extendedDataInSample} < 0) {
364              
365             # error $sFlowSample{extendedDataInSample} too small
366 0           $error = "ERROR: [sFlow.pm] Datagram: Extended data in sample count too small "
367             . "- rest of the datagram skipped";
368              
369 0           push @errors, $error;
370 0           pop @sFlowSamples;
371 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
372              
373             } else {
374              
375 0           for my $extendedDataCount (0 .. $sFlowSample{extendedDataInSample} - 1){
376              
377 0           my $extendedDataType = undef;
378              
379 0           (undef, $extendedDataType) = unpack("a$offset N", $sFlowDatagramPacked);
380 0           $offset += 4;
381              
382             # extended data: switch
383 0 0         if ($extendedDataType == SWITCHDATA_SFLOWv4) {
    0          
    0          
    0          
    0          
384 0           &_decodeSwitchData(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
385             }
386              
387             # extended data: router
388             elsif ($extendedDataType == ROUTERDATA_SFLOWv4) {
389            
390 0           ($subProcessed, $error) =
391             &_decodeRouterData(
392             \$offset,
393             \$sFlowDatagramPacked,
394             \%sFlowDatagram,
395             \%sFlowSample,
396             \@sFlowSamples,
397             );
398              
399 0 0         unless ($subProcessed) {
400 0           push @errors, $error;
401 0           pop @sFlowSamples;
402 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
403             }
404              
405             }
406              
407             # extended data: gateway
408             elsif ($extendedDataType == GATEWAYDATA_SFLOWv4) {
409              
410 0           ($subProcessed, $error) =
411             &_decodeGatewayData(
412             \$offset,
413             \$sFlowDatagramPacked,
414             \%sFlowDatagram,
415             \%sFlowSample,
416             \@sFlowSamples,
417             );
418              
419 0 0         unless ($subProcessed) {
420 0           push @errors, $error;
421 0           pop @sFlowSamples;
422 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
423             }
424            
425             }
426            
427             # extended data: user
428             elsif ($extendedDataType == USERDATA_SFLOWv4) {
429              
430 0           ($subProcessed, $error) =
431             &_decodeUserData(
432             \$offset,
433             \$sFlowDatagramPacked,
434             \%sFlowDatagram,
435             \%sFlowSample,
436             );
437              
438 0 0         unless ($subProcessed) {
439 0           push @errors, $error;
440 0           pop @sFlowSamples;
441 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
442             }
443              
444             }
445              
446             # extended data: url
447             # added in v.3.
448             elsif ($extendedDataType == URLDATA_SFLOWv4) {
449              
450 0           ($subProcessed, $error) =
451             &_decodeUrlData(
452             \$offset,
453             \$sFlowDatagramPacked,
454             \%sFlowDatagram,
455             \%sFlowSample,
456             );
457              
458 0 0         unless ($subProcessed) {
459 0           push @errors, $error;
460 0           pop @sFlowSamples;
461 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
462             }
463            
464             }
465              
466             else {
467            
468 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp}, "
469             . "Datagram: $sFlowDatagram{datagramSequenceNumber} - Unknown extended data type: "
470             . "$extendedDataType - rest of the datagram skipped";
471            
472 0           push @errors, $error;
473 0           pop @sFlowSamples;
474 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
475             }
476            
477             }
478            
479             }
480              
481             }
482              
483             # COUNTERSAMPLE
484             elsif ($sFlowSample{sampleType} == COUNTERSAMPLE_SFLOWv4) {
485              
486 0           my $sourceId = undef;
487              
488             (undef,
489 0           $sFlowSample{sampleSequenceNumber},
490             $sourceId,
491             $sFlowSample{counterSamplingInterval},
492             $sFlowSample{countersVersion}) =
493             unpack("a$offset N4", $sFlowDatagramPacked);
494              
495 0           $offset += 16;
496            
497 0           $sFlowSample{sourceIdType} = $sourceId >> 24;
498 0           $sFlowSample{sourceIdIndex} = $sourceId & 2 ** 24 - 1;
499              
500             # counterstype: generic
501 0 0         if ($sFlowSample{countersVersion} == GENERICCOUNTER_SFLOWv4) {
    0          
    0          
    0          
    0          
    0          
    0          
502 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
503             }
504              
505             # counterstype: ethernet
506             elsif ($sFlowSample{countersVersion} == ETHERNETCOUNTER_SFLOWv4) {
507 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
508 0           &_decodeCounterEthernet(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
509             }
510              
511             # counterstype: tokenring
512             elsif ($sFlowSample{countersVersion} == TOKENRINGCOUNTER_SFLOWv4) {
513 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
514 0           &_decodeCounterTokenring(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
515             }
516              
517             # counterstype: fddi
518             elsif ($sFlowSample{countersVersion} == FDDICOUNTER_SFLOWv4) {
519 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
520             }
521              
522             # counterstype: vg
523             elsif ($sFlowSample{countersVersion} == VGCOUNTER_SFLOWv4) {
524 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
525 0           &_decodeCounterVg(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
526             }
527              
528             # counterstype: wan
529             elsif ($sFlowSample{countersVersion} == WANCOUNTER_SFLOWv4) {
530 0           &_decodeCounterGeneric(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
531             }
532            
533             # counterstype: vlan
534             elsif ($sFlowSample{countersVersion} == VLANCOUNTER_SFLOWv4) {
535 0           &_decodeCounterVlan(\$offset, \$sFlowDatagramPacked, \%sFlowSample);
536             }
537              
538             else {
539            
540 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp}, "
541             . "Datagram: $sFlowDatagram{datagramSequenceNumber} - Unknown counters type: "
542             . "$sFlowSample{countersVersion} - rest of the datagram skipped";
543            
544 0           push @errors, $error;
545 0           pop @sFlowSamples;
546 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
547             }
548              
549             }
550              
551             else {
552              
553 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp}, "
554             . "Datagram: $sFlowDatagram{datagramSequenceNumber} - Unknown sample type: "
555             . "$sFlowSample{sampleType} - rest of the datagram skipped";
556              
557 0           push @errors, $error;
558 0           pop @sFlowSamples;
559 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
560             }
561              
562             }
563              
564             }
565              
566             }
567              
568             ####### sFlow V5 #######
569              
570             elsif ($sFlowDatagram{sFlowVersion} >= SFLOWv5) {
571              
572             # v5 also provides a sub agent id
573             (undef,
574 0           $sFlowDatagram{subAgentId}) =
575             unpack("a$offset N", $sFlowDatagramPacked);
576              
577 0           $offset += 4;
578              
579             (undef,
580 0           $sFlowDatagram{datagramSequenceNumber},
581             $sFlowDatagram{agentUptime},
582             $sFlowDatagram{samplesInPacket}) =
583             unpack("a$offset N3", $sFlowDatagramPacked);
584              
585 0           $offset += 12;
586              
587             # boundcheck for $sFlowDatagram{samplesInPacket}
588             # $sFlowDatagram{samplesInPacket} * 4
589             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
590              
591 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
592             $sFlowDatagram{samplesInPacket} * 4) {
593              
594             # error $sFlowDatagram{samplesInPacket} too big
595 0           $error = "ERROR: [sFlow.pm] Datagram: Samples in packet count too big "
596             . "- rest of the datagram skipped";
597              
598 0           push @errors, $error;
599 0           pop @sFlowSamples;
600 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
601              
602             } elsif ($sFlowDatagram{samplesInPacket} < 0) {
603              
604             # error $sFlowDatagram{samplesInPacket} too small
605 0           $error = "ERROR: [sFlow.pm] Datagram: Samples in packet count too small "
606             . "- rest of the datagram skipped";
607              
608 0           push @errors, $error;
609 0           pop @sFlowSamples;
610 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
611              
612             } else {
613              
614             # parse samples
615 0           for my $samplesCount (0 .. $sFlowDatagram{samplesInPacket} - 1) {
616              
617 0           my %sFlowSample = ();
618 0           push @sFlowSamples, \%sFlowSample;
619              
620 0           my $sampleType = undef;
621              
622             (undef,
623 0           $sampleType,
624             $sFlowSample{sampleLength}) =
625             unpack("a$offset NN", $sFlowDatagramPacked);
626              
627 0           $offset += 8;
628              
629 0           $sFlowSample{sampleTypeEnterprise} = $sampleType >> 12;
630 0           $sFlowSample{sampleTypeFormat} = $sampleType & 2 ** 12 - 1;
631              
632 0           my $sourceId = undef;
633              
634 0 0 0       if ($sFlowSample{sampleTypeEnterprise} == 0
    0 0        
    0 0        
    0 0        
    0 0        
635             and $sFlowSample{sampleTypeFormat} == FLOWSAMPLE_SFLOWv5) {
636              
637             (undef,
638 0           $sFlowSample{sampleSequenceNumber},
639             $sourceId,
640             $sFlowSample{samplingRate},
641             $sFlowSample{samplePool},
642             $sFlowSample{drops},
643             $sFlowSample{inputInterface},
644             $sFlowSample{outputInterface},
645             $sFlowSample{flowRecordsCount}) =
646             unpack("a$offset N8", $sFlowDatagramPacked);
647              
648 0           $offset += 32;
649              
650 0           $sFlowSample{sourceIdType} = $sourceId >> 24;
651 0           $sFlowSample{sourceIdIndex} = $sourceId & 2 ** 24 - 1;
652              
653             # boundcheck for $sFlowSample{flowRecordsCount}
654             # $sFlowSample{flowRecordsCount} * 4
655             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
656              
657 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
658             $sFlowSample{flowRecordsCount} * 4) {
659              
660             # error $sFlowSample{flowRecordsCount} too big
661 0           $error = "ERROR: [sFlow.pm] Datagram: Flow records count too big "
662             . "for this packet length - rest of the datagram skipped";
663              
664 0           push @errors, $error;
665 0           pop @sFlowSamples;
666 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
667              
668             } elsif ($sFlowSample{flowRecordsCount} < 0) {
669              
670             # error $sFlowSample{flowRecordsCount} too small
671 0           $error = "ERROR: [sFlow.pm] Datagram: Flow records count too small "
672             . "- rest of the datagram skipped";
673              
674 0           push @errors, $error;
675 0           pop @sFlowSamples;
676 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
677              
678             } else {
679              
680 0           for my $flowRecords (0 .. $sFlowSample{flowRecordsCount} - 1) {
681              
682 0           ($subProcessed, $error) =
683             &_decodeFlowRecord(
684             \$offset,
685             \$sFlowDatagramPacked,
686             \%sFlowDatagram,
687             \%sFlowSample,
688             \@sFlowSamples,
689             \@errors,
690             );
691              
692 0 0         unless ($subProcessed) {
693 0           push @errors, $error;
694 0           pop @sFlowSamples;
695 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
696             }
697              
698             }
699              
700             }
701              
702             }
703              
704             elsif ($sFlowSample{sampleTypeEnterprise} == 0
705             and $sFlowSample{sampleTypeFormat} == COUNTERSAMPLE_SFLOWv5) {
706            
707             (undef,
708 0           $sFlowSample{sampleSequenceNumber},
709             $sourceId,
710             $sFlowSample{counterRecordsCount}) =
711             unpack("a$offset N3", $sFlowDatagramPacked);
712              
713 0           $offset += 12;
714              
715 0           $sFlowSample{sourceIdType} = $sourceId >> 24;
716 0           $sFlowSample{sourceIdIndex} = $sourceId & 2 ** 24 - 1;
717              
718             # boundcheck for $sFlowSample{counterRecordsCount}
719             # $sFlowSample{counterRecordsCount} * 4
720             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
721              
722 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
723             $sFlowSample{counterRecordsCount} * 4) {
724              
725             # error $sFlowSample{counterRecordsCount} too big
726 0           $error = "ERROR: [sFlow.pm] Datagram: Counter records count too big "
727             . "- rest of the datagram skipped";
728              
729 0           push @errors, $error;
730 0           pop @sFlowSamples;
731 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
732              
733             } elsif ($sFlowSample{counterRecordsCount} < 0) {
734              
735             # error $sFlowSample{counterRecordsCount} too small
736 0           $error = "ERROR: [sFlow.pm] Datagram: Counter records count too small "
737             . "- rest of the datagram skipped";
738              
739 0           push @errors, $error;
740 0           pop @sFlowSamples;
741 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
742              
743             } else {
744              
745 0           for my $counterRecords (0 .. $sFlowSample{counterRecordsCount} - 1) {
746              
747 0           ($subProcessed, $error) =
748             &_decodeCounterRecord(
749             \$offset,
750             \$sFlowDatagramPacked,
751             \%sFlowDatagram,
752             \%sFlowSample,
753             \@sFlowSamples,
754             );
755            
756 0 0         unless ($subProcessed) {
757 0           push @errors, $error;
758 0           pop @sFlowSamples;
759 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
760             }
761              
762             }
763              
764             }
765              
766             }
767              
768             elsif ($sFlowSample{sampleTypeEnterprise} == 0
769             and $sFlowSample{sampleTypeFormat} == EXPANDEDFLOWSAMPLE_SFLOWv5) {
770            
771             (undef,
772 0           $sFlowSample{sampleSequenceNumber},
773             $sFlowSample{sourceIdType},
774             $sFlowSample{sourceIdIndex},
775             $sFlowSample{samplingRate},
776             $sFlowSample{samplePool},
777             $sFlowSample{drops},
778             $sFlowSample{inputInterfaceFormat},
779             $sFlowSample{inputInterfaceValue},
780             $sFlowSample{outputInterfaceFormat},
781             $sFlowSample{outputInterfaceValue},
782             $sFlowSample{flowRecordsCount}) =
783             unpack("a$offset N11", $sFlowDatagramPacked);
784              
785 0           $offset += 44;
786              
787             # boundcheck for $sFlowSample{flowRecordsCount}
788             # $sFlowSample{flowRecordsCount} * 4
789             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
790              
791 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
792             $sFlowSample{flowRecordsCount} * 4) {
793              
794             # error $sFlowSample{flowRecordsCount} too big
795 0           $error = "ERROR: [sFlow.pm] Datagram: Flow records count too big "
796             . "for this packet length - rest of the datagram skipped";
797              
798 0           push @errors, $error;
799 0           pop @sFlowSamples;
800 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
801              
802             } elsif ($sFlowSample{flowRecordsCount} < 0) {
803              
804             # error $sFlowSample{flowRecordsCount} too small
805 0           $error = "ERROR: [sFlow.pm] Datagram: Flow records count too small"
806             . "- rest of the datagram skipped";
807              
808 0           push @errors, $error;
809 0           pop @sFlowSamples;
810 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
811              
812             } else {
813              
814 0           for my $flowRecords (0 .. $sFlowSample{flowRecordsCount} - 1) {
815              
816 0           ($subProcessed, $error) =
817             &_decodeFlowRecord(
818             \$offset,
819             \$sFlowDatagramPacked,
820             \%sFlowDatagram,
821             \%sFlowSample,
822             \@sFlowSamples,
823             \@errors,
824             );
825              
826 0 0         unless ($subProcessed) {
827 0           push @errors, $error;
828 0           pop @sFlowSamples;
829 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
830             }
831            
832             }
833            
834             }
835              
836             }
837              
838             elsif ($sFlowSample{sampleTypeEnterprise} == 0
839             and $sFlowSample{sampleTypeFormat} == EXPANDEDCOUNTERSAMPLE_SFLOWv5) {
840              
841             (undef,
842 0           $sFlowSample{sampleSequenceNumber},
843             $sFlowSample{sourceIdType},
844             $sFlowSample{sourceIdIndex},
845             $sFlowSample{counterRecordsCount}) =
846             unpack("a$offset N4", $sFlowDatagramPacked);
847              
848 0           $offset += 16;
849            
850             # boundcheck for $sFlowSample{counterRecordsCount}
851             # $sFlowSample{counterRecordsCount} * 4
852             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
853              
854 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
855             $sFlowSample{counterRecordsCount} * 4) {
856              
857             # error $sFlowSample{counterRecordsCount} too big
858 0           $error = "ERROR: [sFlow.pm] Datagram: Counter records count too big "
859             . "- rest of the datagram skipped";
860              
861 0           push @errors, $error;
862 0           pop @sFlowSamples;
863 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
864              
865             } elsif ($sFlowSample{counterRecordsCount} < 0) {
866              
867             # error $sFlowSample{counterRecordsCount} too small
868 0           $error = "ERROR: [sFlow.pm] Datagram: Counter records count too small "
869             . "- rest of the datagram skipped";
870              
871 0           push @errors, $error;
872 0           pop @sFlowSamples;
873 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
874              
875             } else {
876              
877 0           for my $counterRecords (0 .. $sFlowSample{counterRecordsCount} - 1) {
878              
879 0           ($subProcessed, $error) =
880             &_decodeCounterRecord(
881             \$offset,
882             \$sFlowDatagramPacked,
883             \%sFlowDatagram,
884             \%sFlowSample,
885             \@sFlowSamples,
886             );
887              
888 0 0         unless ($subProcessed) {
889 0           push @errors, $error;
890 0           pop @sFlowSamples;
891 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
892             }
893              
894             }
895              
896             }
897              
898             }
899              
900             elsif ($sFlowSample{sampleTypeEnterprise} == FOUNDRY_ACL_SFLOWv5
901             and $sFlowSample{sampleTypeFormat} == FLOWSAMPLE_SFLOWv5) {
902              
903             (undef,
904 0           $sFlowSample{FoundryFlags},
905             $sFlowSample{FoundryGroupID}) =
906             unpack("a$offset N2", $sFlowDatagramPacked);
907              
908 0           $offset += 8;
909              
910 0           $sFlowDatagram{samplesInPacket}++;
911 0           next;
912              
913             }
914              
915             else {
916              
917 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp} Datagram: "
918             . "$sFlowDatagram{datagramSequenceNumber} - Unknown sample enterprise: "
919             . "$sFlowSample{sampleTypeEnterprise} or format: $sFlowSample{sampleTypeFormat} "
920             . "- rest of the datagram skipped";
921            
922 0           push @errors, $error;
923 0           pop @sFlowSamples;
924 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
925             }
926              
927             }
928              
929             }
930              
931             }
932              
933             else {
934              
935 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram{AgentIp}, Datagram: "
936             . "$sFlowDatagram{datagramSequenceNumber} - Unknown sFlow Version: "
937             . "$sFlowDatagram{sFlowVersion}";
938              
939 0           push @errors, $error;
940 0           %sFlowDatagram = ();
941 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
942             }
943            
944 0           return (\%sFlowDatagram, \@sFlowSamples, \@errors);
945              
946             }
947              
948              
949             #### END sub decode() ######################################################
950              
951              
952              
953             #############################################################################
954             sub _bin2ip {
955             #############################################################################
956              
957             # _bin2ip is a copy of "to_dotquad" from NetPacket::IP.pm
958             # Copyright (c) 2001 Tim Potter.
959             # Copyright (c) 2001 Stephanie Wehner.
960              
961 0     0     my($net) = @_ ;
962 0           my($na, $nb, $nc, $nd);
963              
964 0           $na = $net >> 24 & 255;
965 0           $nb = $net >> 16 & 255;
966 0           $nc = $net >> 8 & 255;
967 0           $nd = $net & 255;
968              
969 0           return ("$na.$nb.$nc.$nd");
970             }
971              
972              
973             #############################################################################
974             sub _decodeIpAddress {
975             #############################################################################
976              
977 0     0     my $offsetref = shift;
978 0           my $sFlowDatagramPackedRef = shift;
979 0           my $sFlowDatagram = shift;
980 0           my $sFlowSample = shift;
981 0           my $sFlowSamples = shift;
982 0           my $IpVersion = shift;
983 0           my $keyName = shift;
984 0           my $DatagramOrSampleData = shift;
985              
986 0           my $error = undef;
987 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
988 0           my $offset = $$offsetref;
989              
990 0 0         if (defined($DatagramOrSampleData)) {
991              
992 0 0         if ($IpVersion == IPv4) {
    0          
993              
994             (undef,
995 0           $sFlowDatagram->{$keyName}) =
996             unpack("a$offset N", $sFlowDatagramPacked);
997              
998 0           $sFlowDatagram->{$keyName} = &_bin2ip($sFlowDatagram->{$keyName});
999 0           $offset += 4;
1000             }
1001              
1002             elsif ($IpVersion == IPv6) {
1003              
1004 0           $sFlowSample->{$keyName} =
1005             join(':', unpack("x$offset H4H4H4H4H4H4H4H4", $sFlowDatagramPacked));
1006              
1007 0           $offset += 16;
1008             }
1009             }
1010              
1011             else {
1012              
1013 0 0         if ($IpVersion == IPv4) {
    0          
1014              
1015             (undef,
1016 0           $sFlowSample->{$keyName}) =
1017             unpack("a$offset N", $sFlowDatagramPacked);
1018              
1019 0           $sFlowSample->{$keyName} = &_bin2ip($sFlowSample->{$keyName});
1020 0           $offset += 4;
1021             }
1022              
1023             elsif ($IpVersion == IPv6) {
1024              
1025 0           $sFlowSample->{$keyName} =
1026             join(':', unpack("x$offset H4H4H4H4H4H4H4H4", $sFlowDatagramPacked));
1027              
1028 0           $offset += 16;
1029             }
1030             }
1031              
1032 0 0 0       if ($IpVersion != IPv4 and $IpVersion != IPv6) {
1033              
1034 0 0         if (defined($DatagramOrSampleData)) {
1035              
1036             # unknown ip version added in v5
1037 0 0         if ($IpVersion == UNKNOWNIPVERSION) {
1038              
1039 0           $error = "ERROR: [sFlow.pm] AgentIP: Unknown agent ip version: "
1040             . "$IpVersion - rest of the datagram skipped";
1041              
1042 0           return (undef, $error);
1043             }
1044              
1045             else {
1046              
1047 0           $error = "ERROR: [sFlow.pm] AgentIP: Unknown agent ip version: "
1048             . "$IpVersion - rest of the datagram skipped";
1049              
1050 0           return (undef, $error);
1051             }
1052              
1053             }
1054              
1055             else {
1056              
1057             # unknown ip version added in v5
1058 0 0         if ($IpVersion == UNKNOWNIPVERSION) {
1059              
1060 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1061             . "Datagram: $sFlowDatagram->{datagramSequenceNumber}, Sample: "
1062             . "$sFlowSample->{sampleSequenceNumber} - Unknown ip version: "
1063             . "$IpVersion - rest of the datagram skipped";
1064              
1065 0           return (undef, $error);
1066             }
1067            
1068             else {
1069 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1070             . "Datagram: $sFlowDatagram->{datagramSequenceNumber}, Sample: "
1071             . "$sFlowSample->{sampleSequenceNumber} - Unknown ip version: "
1072             . "$IpVersion - rest of the datagram skipped";
1073              
1074 0           return (undef, $error);
1075             }
1076              
1077             }
1078              
1079             }
1080              
1081 0           $$offsetref = $offset;
1082 0           return (1, undef);
1083             }
1084              
1085              
1086             #############################################################################
1087             sub _decodeFlowRecord {
1088             #############################################################################
1089              
1090 0     0     my $offsetref = shift;
1091 0           my $sFlowDatagramPackedRef = shift;
1092 0           my $sFlowDatagram = shift;
1093 0           my $sFlowSample = shift;
1094 0           my $sFlowSamples = shift;
1095 0           my $errors = shift;
1096              
1097 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1098 0           my $offset = $$offsetref;
1099 0           my $flowType = undef;
1100 0           my $flowDataLength = undef;
1101 0           my $error = undef;
1102 0           my $subProcessed = undef;
1103              
1104             (undef,
1105 0           $flowType,
1106             $flowDataLength) =
1107             unpack("a$offset NN", $sFlowDatagramPacked);
1108              
1109 0           $offset += 8;
1110              
1111 0           my $flowTypeEnterprise = $flowType >> 12;
1112 0           my $flowTypeFormat = $flowType & 2 ** 12 - 1;
1113              
1114 0 0         if ($flowTypeEnterprise == 0) {
1115              
1116 0 0         if ($flowTypeFormat == HEADERDATA_SFLOWv5) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1117              
1118 0           ($subProcessed, $error) =
1119             &_decodeHeaderData(
1120             \$offset,
1121             $sFlowDatagramPackedRef,
1122             $sFlowDatagram,
1123             $sFlowSample,
1124             $sFlowSamples,
1125             );
1126              
1127 0 0         unless ($subProcessed) {
1128 0           push @{$errors}, $error;
  0            
1129             }
1130              
1131             }
1132              
1133             elsif ($flowTypeFormat == SWITCHDATA_SFLOWv5) {
1134 0           &_decodeSwitchData(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1135             }
1136              
1137             elsif ($flowTypeFormat == ETHERNETFRAMEDATA_SFLOWv5) {
1138 0           &_decodeEthernetFrameData(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1139             }
1140              
1141             elsif ($flowTypeFormat == IPv4DATA_SFLOWv5) {
1142 0           &_decodeIPv4Data(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1143             }
1144              
1145             elsif ($flowTypeFormat == IPv6DATA_SFLOWv5) {
1146 0           &_decodeIPv6Data(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1147             }
1148              
1149             elsif ($flowTypeFormat == ROUTERDATA_SFLOWv5) {
1150              
1151 0           ($subProcessed, $error) =
1152             &_decodeRouterData(
1153             \$offset,
1154             $sFlowDatagramPackedRef,
1155             $sFlowDatagram,
1156             $sFlowSample,
1157             $sFlowSamples,
1158             );
1159              
1160 0 0         unless ($subProcessed) {
1161 0           return (undef, $error);
1162             }
1163              
1164             }
1165              
1166             elsif ($flowTypeFormat == GATEWAYDATA_SFLOWv5) {
1167              
1168 0           ($subProcessed, $error) =
1169             &_decodeGatewayData(
1170             \$offset,
1171             $sFlowDatagramPackedRef,
1172             $sFlowDatagram,
1173             $sFlowSample,
1174             $sFlowSamples,
1175             );
1176              
1177 0 0         unless ($subProcessed) {
1178 0           return (undef, $error);
1179             }
1180              
1181             }
1182              
1183             elsif ($flowTypeFormat == USERDATA_SFLOWv5) {
1184              
1185 0           ($subProcessed, $error) =
1186             &_decodeUserData(
1187             \$offset,
1188             $sFlowDatagramPackedRef,
1189             $sFlowDatagram,
1190             $sFlowSample
1191             );
1192              
1193 0 0         unless ($subProcessed) {
1194 0           return (undef, $error);
1195             }
1196              
1197             }
1198              
1199             elsif ($flowTypeFormat == URLDATA_SFLOWv5) {
1200              
1201 0           ($subProcessed, $error) =
1202             &_decodeUrlData(
1203             \$offset,
1204             $sFlowDatagramPackedRef,
1205             $sFlowDatagram,
1206             $sFlowSample
1207             );
1208              
1209 0 0         unless ($subProcessed) {
1210 0           return (undef, $error);
1211             }
1212              
1213             }
1214              
1215             elsif ($flowTypeFormat == MPLSDATA_SFLOWv5) {
1216              
1217 0           ($subProcessed, $error) =
1218             &_decodeMplsData(
1219             \$offset,
1220             $sFlowDatagramPackedRef,
1221             $sFlowDatagram,
1222             $sFlowSample,
1223             $sFlowSamples,
1224             );
1225              
1226 0 0         unless ($subProcessed) {
1227 0           return (undef, $error);
1228             }
1229              
1230             }
1231              
1232             elsif ($flowTypeFormat == NATDATA_SFLOWv5) {
1233              
1234 0           ($subProcessed, $error) =
1235             &_decodeNatData(
1236             \$offset,
1237             $sFlowDatagramPackedRef,
1238             $sFlowDatagram,
1239             $sFlowSample,
1240             $sFlowSamples,
1241             );
1242              
1243 0 0         unless ($subProcessed) {
1244 0           return (undef, $error);
1245             }
1246              
1247             }
1248              
1249             elsif ($flowTypeFormat == MPLSTUNNEL_SFLOWv5) {
1250              
1251 0           ($subProcessed, $error) =
1252             &_decodeMplsTunnel(
1253             \$offset,
1254             $sFlowDatagramPackedRef,
1255             $sFlowSample
1256             );
1257              
1258 0 0         unless ($subProcessed) {
1259 0           return (undef, $error);
1260             }
1261              
1262             }
1263              
1264             elsif ($flowTypeFormat == MPLSVC_SFLOWv5) {
1265              
1266 0           ($subProcessed, $error) =
1267             &_decodeMplsVc(
1268             \$offset,
1269             $sFlowDatagramPackedRef,
1270             $sFlowSample
1271             );
1272              
1273 0 0         unless ($subProcessed) {
1274 0           return (undef, $error);
1275             }
1276              
1277             }
1278              
1279             elsif ($flowTypeFormat == MPLSFEC_SFLOWv5) {
1280              
1281 0           ($subProcessed, $error) =
1282             &_decodeMplsFec(
1283             \$offset,
1284             $sFlowDatagramPackedRef,
1285             $sFlowSample
1286             );
1287              
1288 0 0         unless ($subProcessed) {
1289 0           return (undef, $error);
1290             }
1291              
1292             }
1293              
1294             elsif ($flowTypeFormat == MPLSLVPFEC_SFLOWv5) {
1295 0           &_decodeMplsLpvFec(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1296             }
1297              
1298             elsif ($flowTypeFormat == VLANTUNNEL_SFLOWv5) {
1299              
1300 0           ($subProcessed, $error) =
1301             &_decodeVlanTunnel(
1302             \$offset,
1303             $sFlowDatagramPackedRef,
1304             $sFlowSample
1305             );
1306              
1307 0 0         unless ($subProcessed) {
1308 0           return (undef, $error);
1309             }
1310              
1311             }
1312              
1313             else {
1314              
1315 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1316             . "Datagram: $sFlowDatagram->{datagramSequenceNumber}, Sample: "
1317             . "$sFlowSample->{sampleSequenceNumber} - Unknown Flowdata format: "
1318             . "$flowTypeFormat - rest of the datagram skipped";
1319              
1320 0           return (undef, $error);
1321             }
1322              
1323             }
1324              
1325             else {
1326              
1327 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1328             . "Datagram: $sFlowDatagram->{datagramSequenceNumber} - Unknown Flowdata enterprise: "
1329             . "$flowTypeEnterprise - rest of the datagram skipped";
1330              
1331 0           return (undef, $error);
1332             }
1333              
1334 0           $$offsetref = $offset;
1335 0           return (1,undef);
1336             }
1337              
1338              
1339             #############################################################################
1340             sub _decodeCounterRecord {
1341             #############################################################################
1342              
1343 0     0     my $offsetref = shift;
1344 0           my $sFlowDatagramPackedRef = shift;
1345 0           my $sFlowDatagram = shift;
1346 0           my $sFlowSample = shift;
1347 0           my $sFlowSamples = shift;
1348              
1349 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1350 0           my $offset = $$offsetref;
1351 0           my $counterType = undef;
1352 0           my $counterDataLength = undef;
1353 0           my $error = undef;
1354              
1355             (undef,
1356 0           $counterType,
1357             $sFlowSample->{counterDataLength}) =
1358             unpack("a$offset NN", $sFlowDatagramPacked);
1359              
1360 0           $offset += 8;
1361              
1362 0           my $counterTypeEnterprise = $counterType >> 12;
1363 0           my $counterTypeFormat = $counterType & 2 ** 12 - 1;
1364              
1365 0 0         if ($counterTypeEnterprise == 0) {
1366              
1367 0 0         if ($counterTypeFormat == GENERICCOUNTER_SFLOWv5) {
    0          
    0          
    0          
    0          
    0          
1368 0           &_decodeCounterGeneric(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1369             }
1370              
1371             elsif ($counterTypeFormat == ETHERNETCOUNTER_SFLOWv5) {
1372 0           &_decodeCounterEthernet(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1373             }
1374              
1375             elsif ($counterTypeFormat == TOKENRINGCOUNTER_SFLOWv5) {
1376 0           &_decodeCounterTokenring(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1377             }
1378              
1379             elsif ($counterTypeFormat == VGCOUNTER_SFLOWv5) {
1380 0           &_decodeCounterVg(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1381             }
1382              
1383             elsif ($counterTypeFormat == VLANCOUNTER_SFLOWv5) {
1384 0           &_decodeCounterVlan(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1385             }
1386              
1387             elsif ($counterTypeFormat == PROCESSORCOUNTER_SFLOWv5) {
1388 0           &_decodeCounterProcessor(\$offset, $sFlowDatagramPackedRef, $sFlowSample);
1389             }
1390              
1391             else {
1392              
1393 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1394             . "Datagram: $sFlowDatagram->{datagramSequenceNumber} - Unknown counter data format: "
1395             . "$counterTypeFormat - rest of the datagram skipped";
1396 0           return (undef, $error);
1397             }
1398              
1399             }
1400              
1401             else {
1402              
1403 0           $error = "ERROR: [sFlow.pm] AgentIP: $sFlowDatagram->{AgentIp}, "
1404             . "Datagram: $sFlowDatagram->{datagramSequenceNumber} - Unknown counter data enterprise: "
1405             . "$counterTypeEnterprise - rest of the datagram skipped";
1406              
1407 0           return (undef, $error);
1408             }
1409              
1410 0           $$offsetref = $offset;
1411 0           return (1, undef);
1412              
1413             }
1414              
1415              
1416             #############################################################################
1417             sub _decodeHeaderData {
1418             #############################################################################
1419              
1420 0     0     my $offsetref = shift;
1421 0           my $sFlowDatagramPackedRef = shift;
1422 0           my $sFlowDatagram = shift;
1423 0           my $sFlowSample = shift;
1424 0           my $sFlowSamples = shift;
1425              
1426 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1427 0           my $offset = $$offsetref;
1428 0           my $vlanTag = 0;
1429 0           my $error = undef;
1430              
1431 0           $sFlowSample->{HEADERDATA} = 'HEADERDATA';
1432              
1433 0 0         if ($sFlowDatagram->{sFlowVersion} == SFLOWv5) {
1434              
1435             (undef,
1436 0           $sFlowSample->{HeaderProtocol},
1437             $sFlowSample->{HeaderFrameLength},
1438             $sFlowSample->{HeaderStrippedLength},
1439             $sFlowSample->{HeaderSizeByte}) =
1440             unpack("a$offset N4", $sFlowDatagramPacked);
1441              
1442 0           $offset += 16;
1443              
1444             } else {
1445              
1446             (undef,
1447 0           $sFlowSample->{HeaderProtocol},
1448             $sFlowSample->{HeaderFrameLength},
1449             $sFlowSample->{HeaderSizeByte}) =
1450             unpack("a$offset N3", $sFlowDatagramPacked);
1451              
1452 0           $offset += 12;
1453              
1454             }
1455              
1456             # check if $sFlowSample->{HeaderSizeByte} has a reasonable value
1457             # it cannot be more than 256 Byte
1458              
1459 0 0         if ($sFlowSample->{HeaderSizeByte} > 256) {
    0          
1460              
1461             # error: header size byte too long
1462 0           $error = "ERROR: [sFlow.pm] HeaderData: Header data too long";
1463              
1464 0           return (undef, $error);
1465              
1466             } elsif ($sFlowSample->{HeaderSizeByte} < 0) {
1467              
1468             # error: header size byte too small
1469 0           $error = "ERROR: [sFlow.pm] HeaderData: Header data too small";
1470              
1471 0           return (undef, $error);
1472              
1473             } else {
1474              
1475             # header size in bits
1476 0           $sFlowSample->{HeaderSizeBit} =
1477             $sFlowSample->{HeaderSizeByte} * 8;
1478              
1479 0           $sFlowSample->{HeaderBin} =
1480             substr ($sFlowDatagramPacked, $offset, $sFlowSample->{HeaderSizeByte});
1481              
1482             # we have to cut off a $sFlowSample->{HeaderSizeByte} mod 4 == 0 number of bytes
1483 0           my $tmp = 4 - ($sFlowSample->{HeaderSizeByte} % 4);
1484 0 0         $tmp == 4 and $tmp = 0;
1485              
1486 0           $offset += ($sFlowSample->{HeaderSizeByte} + $tmp);
1487              
1488 0           my $ipdata = undef;
1489              
1490 0           ($sFlowSample->{HeaderEtherDestMac},
1491             $sFlowSample->{HeaderEtherSrcMac},
1492             $sFlowSample->{HeaderType},
1493             $ipdata) =
1494             unpack('a6a6H4a*', $sFlowSample->{HeaderBin});
1495              
1496             # analyze ether type
1497 0 0         if ($sFlowSample->{HeaderType} eq ETH_TYPE_VLAN) {
1498              
1499 0           (undef, $sFlowSample->{HeaderType}, $ipdata) = unpack('nH4a*', $ipdata);
1500             # add 4 bytes to ethernet header length because of vlan tag
1501             # this is done later on, if $vlanTag is set to 1
1502 0           $vlanTag = 1;
1503              
1504             }
1505              
1506 0 0         if ($sFlowSample->{HeaderType} eq ETH_TYPE_IP) {
    0          
    0          
1507              
1508 0           (undef, $sFlowSample->{HeaderDatalen}) = unpack('nn', $ipdata);
1509             # add ethernet header length
1510 0           $sFlowSample->{HeaderDatalen} += 14;
1511             }
1512              
1513             elsif ($sFlowSample->{HeaderType} eq ETH_TYPE_IPv6) {
1514              
1515 0           (undef, $sFlowSample->{HeaderDatalen}) = unpack('Nn', $ipdata);
1516             # add v6 header (not included in v6)
1517 0           $sFlowSample->{HeaderDatalen} += 40;
1518             # add ethernet header length
1519 0           $sFlowSample->{HeaderDatalen} += 14;
1520             }
1521              
1522             elsif ($sFlowSample->{HeaderType} eq ETH_TYPE_ARP) {
1523             # ARP
1524 0           $sFlowSample->{HeaderDatalen} = 64;
1525             }
1526              
1527             else {
1528             # unknown
1529 0           $sFlowSample->{HeaderDatalen} = 64;
1530             }
1531              
1532             # add vlan tag length
1533 0 0         if ($vlanTag == 1) {
1534 0           $sFlowSample->{HeaderDatalen} += 4;
1535             }
1536              
1537 0 0         if ($sFlowSample->{HeaderDatalen} < 64) {
1538 0           $sFlowSample->{HeaderDatalen} = 64;
1539             }
1540              
1541             }
1542              
1543 0           $$offsetref = $offset;
1544 0           return (1, undef);
1545              
1546             }
1547              
1548              
1549             #############################################################################
1550             sub _decodeEthernetFrameData {
1551             #############################################################################
1552              
1553 0     0     my $offsetref = shift;
1554 0           my $sFlowDatagramPackedRef = shift;
1555 0           my $sFlowSample = shift;
1556              
1557 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1558 0           my $offset = $$offsetref;
1559 0           my $EtherSrcMac1 = undef;
1560 0           my $EtherSrcMac2 = undef;
1561 0           my $EtherDestMac1 = undef;
1562 0           my $EtherDestMac2 = undef;
1563              
1564 0           $sFlowSample->{ETHERNETFRAMEDATA} = 'ETHERNETFRAMEDATA';
1565              
1566             (undef,
1567 0           $sFlowSample->{EtherMacPacketlength},
1568             $EtherSrcMac1,
1569             $EtherSrcMac2,
1570             $EtherDestMac1,
1571             $EtherDestMac2,
1572             $sFlowSample->{EtherPackettype}) =
1573             unpack("a$offset N6", $sFlowDatagramPacked);
1574              
1575 0           $sFlowSample->{EtherSrcMac} = sprintf("%08x%04x", $EtherSrcMac1, $EtherSrcMac2);
1576 0           $sFlowSample->{EtherDestMac} = sprintf("%08x%04x", $EtherDestMac1, $EtherDestMac2);
1577              
1578 0           $offset += 24;
1579 0           $$offsetref = $offset;
1580              
1581             }
1582              
1583              
1584             #############################################################################
1585             sub _decodeIPv4Data {
1586             #############################################################################
1587              
1588 0     0     my $offsetref = shift;
1589 0           my $sFlowDatagramPackedRef = shift;
1590 0           my $sFlowSample = shift;
1591              
1592 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1593 0           my $offset = $$offsetref;
1594              
1595 0           $sFlowSample->{IPv4DATA} = 'IPv4DATA';
1596              
1597             (undef,
1598 0           $sFlowSample->{IPv4Packetlength},
1599             $sFlowSample->{IPv4NextHeaderProtocol},
1600             $sFlowSample->{IPv4srcIp},
1601             $sFlowSample->{IPv4destIp},
1602             $sFlowSample->{IPv4srcPort},
1603             $sFlowSample->{IPv4destPort},
1604             $sFlowSample->{IPv4tcpFlags},
1605             $sFlowSample->{IPv4tos}) =
1606             unpack("a$offset N2B32B32N4", $sFlowDatagramPacked);
1607              
1608 0           $sFlowSample->{IPv4srcIp} = &_bin2ip($sFlowSample->{IPv4srcIp});
1609 0           $sFlowSample->{IPv4destIp} = &_bin2ip($sFlowSample->{IPv4destIp});
1610              
1611 0           $offset += 32;
1612 0           $$offsetref = $offset;
1613              
1614             }
1615              
1616              
1617             #############################################################################
1618             sub _decodeIPv6Data {
1619             #############################################################################
1620              
1621 0     0     my $offsetref = shift;
1622 0           my $sFlowDatagramPackedRef = shift;
1623 0           my $sFlowSample = shift;
1624              
1625 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1626 0           my $offset = $$offsetref;
1627              
1628 0           $sFlowSample->{IPv6DATA} = 'IPv6DATA';
1629              
1630             (undef,
1631 0           $sFlowSample->{IPv6Packetlength},
1632             $sFlowSample->{IPv6NextHeaderProto}) =
1633             unpack("a$offset N2", $sFlowDatagramPacked);
1634              
1635 0           $sFlowSample->{IPv6srcIp} =
1636             join(':', unpack("x$offset H4H4H4H4H4H4H4H4", $sFlowDatagramPacked));
1637              
1638 0           $sFlowSample->{IPv6destIp} =
1639             join(':', unpack("x$offset H4H4H4H4H4H4H4H4", $sFlowDatagramPacked));
1640              
1641             (undef,
1642 0           $sFlowSample->{IPv6srcPort},
1643             $sFlowSample->{IPv6destPort},
1644             $sFlowSample->{IPv6tcpFlags},
1645             $sFlowSample->{IPv6Priority}) =
1646             unpack("a$offset N4", $sFlowDatagramPacked);
1647              
1648 0           $offset += 56;
1649 0           $$offsetref = $offset;
1650              
1651             }
1652              
1653              
1654             #############################################################################
1655             sub _decodeSwitchData {
1656             #############################################################################
1657              
1658 0     0     my $offsetref = shift;
1659 0           my $sFlowDatagramPackedRef = shift;
1660 0           my $sFlowSample = shift;
1661              
1662 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1663 0           my $offset = $$offsetref;
1664              
1665 0           $sFlowSample->{SWITCHDATA} = 'SWITCHDATA';
1666              
1667             (undef,
1668 0           $sFlowSample->{SwitchSrcVlan},
1669             $sFlowSample->{SwitchSrcPriority},
1670             $sFlowSample->{SwitchDestVlan},
1671             $sFlowSample->{SwitchDestPriority}) =
1672             unpack("a$offset N4", $sFlowDatagramPacked);
1673              
1674 0           $offset += 16;
1675 0           $$offsetref = $offset;
1676              
1677             }
1678              
1679              
1680             #############################################################################
1681             sub _decodeRouterData {
1682             #############################################################################
1683              
1684 0     0     my $offsetref = shift;
1685 0           my $sFlowDatagramPackedRef = shift;
1686 0           my $sFlowDatagram = shift;
1687 0           my $sFlowSample = shift;
1688 0           my $sFlowSamples = shift;
1689              
1690 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1691 0           my $offset = $$offsetref;
1692 0           my $subProcessed = undef;
1693 0           my $error = undef;
1694              
1695 0           $sFlowSample->{ROUTERDATA} = 'ROUTERDATA';
1696              
1697             (undef,
1698 0           $sFlowSample->{RouterIpVersionNextHopRouter}) =
1699             unpack("a$offset N", $sFlowDatagramPacked);
1700              
1701 0           $offset += 4;
1702              
1703 0           ($subProcessed, $error) =
1704             &_decodeIpAddress(
1705             \$offset,
1706             $sFlowDatagramPackedRef,
1707             $sFlowDatagram,
1708             $sFlowSample,
1709             $sFlowSamples,
1710             $sFlowSample->{RouterIpVersionNextHopRouter},
1711             'RouterIpAddressNextHopRouter',
1712             undef
1713             );
1714              
1715 0 0         unless ($subProcessed) {
1716 0           return (undef, $error);
1717             }
1718              
1719             (undef,
1720 0           $sFlowSample->{RouterSrcMask},
1721             $sFlowSample->{RouterDestMask}) =
1722             unpack("a$offset NN", $sFlowDatagramPacked);
1723              
1724 0           $offset += 8;
1725              
1726 0           $$offsetref = $offset;
1727 0           return (1, undef);
1728              
1729             }
1730              
1731              
1732             #############################################################################
1733             sub _decodeGatewayData {
1734             #############################################################################
1735              
1736 0     0     my $offsetref = shift;
1737 0           my $sFlowDatagramPackedRef = shift;
1738 0           my $sFlowDatagram = shift;
1739 0           my $sFlowSample = shift;
1740 0           my $sFlowSamples = shift;
1741              
1742 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1743 0           my $offset = $$offsetref;
1744 0           my $subProcessed = undef;
1745 0           my $error = undef;
1746              
1747 0           $sFlowSample->{GATEWAYDATA} = 'GATEWAYDATA';
1748              
1749 0 0         if ($sFlowDatagram->{sFlowVersion} == SFLOWv5) {
1750              
1751             (undef,
1752 0           $sFlowSample->{GatewayIpVersionNextHopRouter}) =
1753             unpack("a$offset N", $sFlowDatagramPacked);
1754              
1755 0           $offset += 4;
1756              
1757 0           ($subProcessed, $error) =
1758             &_decodeIpAddress(
1759             \$offset,
1760             $sFlowDatagramPackedRef,
1761             $sFlowDatagram,
1762             $sFlowSample,
1763             $sFlowSamples,
1764             $sFlowSample->{GatewayIpVersionNextHopRouter},
1765             'GatewayIpAddressNextHopRouter',
1766             undef,
1767             );
1768              
1769 0 0         unless ($subProcessed) {
1770 0           return (undef, $error);
1771             }
1772             }
1773              
1774             (undef,
1775 0           $sFlowSample->{GatewayAsRouter},
1776             $sFlowSample->{GatewayAsSource},
1777             $sFlowSample->{GatewayAsSourcePeer},
1778             $sFlowSample->{GatewayDestAsPathsCount}) =
1779             unpack("a$offset N4", $sFlowDatagramPacked);
1780              
1781 0           $offset += 16;
1782              
1783             # boundcheck for $sFlowSample->{GatewayDestAsPathsCount}
1784             # $sFlowSample->{GatewayDestAsPathsCount} * 4 (that will be the min)
1785             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
1786              
1787 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
1788             $sFlowSample->{GatewayDestAsPathsCount} * 4) {
1789              
1790             # error $sFlowSample->{GatewayDestAsPaths} too big
1791 0           $error = "ERROR: [sFlow.pm] GatewayDestAsPaths: Gateway destination AS paths count too big "
1792             . "- rest of the datagram skipped";
1793              
1794 0           return (undef, $error);
1795            
1796             } elsif ($sFlowSample->{GatewayDestAsPathsCount} < 0) {
1797            
1798             # error $sFlowSample->{GatewayDestAsPaths} too small
1799 0           $error = "ERROR: [sFlow.pm] GatewayDestAsPaths: Gateway destination AS paths count too small "
1800             . "- rest of the datagram skipped";
1801              
1802 0           return (undef, $error);
1803            
1804             } else {
1805              
1806             # array containing the single paths
1807 0           my @sFlowAsPaths = ();
1808              
1809             # reference to this array in extended data
1810 0           $sFlowSample->{GatewayDestAsPaths} = \@sFlowAsPaths;
1811              
1812 0           for my $destAsPathCount (0 .. $sFlowSample->{GatewayDestAsPathsCount} - 1) {
1813              
1814             # single path hash
1815 0           my %sFlowAsPath = ();
1816              
1817             # reference to this single path hash in the paths array
1818 0           push @sFlowAsPaths, \%sFlowAsPath;
1819              
1820 0 0         if ($sFlowDatagram->{sFlowVersion} >= SFLOWv4) {
1821              
1822             (undef,
1823 0           $sFlowAsPath{asPathSegmentType},
1824             $sFlowAsPath{lengthAsList}) =
1825             unpack("a$offset NN", $sFlowDatagramPacked);
1826              
1827 0           $offset += 8;
1828              
1829             } else {
1830              
1831 0           $sFlowAsPath{lengthAsList} = 1;
1832              
1833             }
1834              
1835             # boundcheck for $sFlowAsPath{lengthAsList}
1836             # $sFlowAsPath{lengthAsList} * 4
1837             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
1838              
1839 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
1840             $sFlowAsPath{lengthAsList} * 4) {
1841              
1842             # error $sFlowAsPath{lengthAsList} too big
1843 0           $error = "ERROR: [sFlow.pm] AsPath: Length AS list too big "
1844             . "- rest of the datagram skipped";
1845              
1846 0           return (undef, $error);
1847              
1848             } elsif ($sFlowAsPath{lengthAsList} < 0) {
1849              
1850             # error $sFlowAsPath{lengthAsList} too small
1851 0           $error = "ERROR: [sFlow.pm] AsPath: Length AS list too small "
1852             . "- rest of the datagram skipped";
1853              
1854 0           return (undef, $error);
1855              
1856             } else {
1857              
1858             # array containing the as numbers of a path
1859 0           my @sFlowAsNumber = ();
1860              
1861             # referece to this array in path hash
1862 0           $sFlowAsPath{AsPath} = \@sFlowAsNumber;
1863              
1864 0           for my $asListLength (0 .. $sFlowAsPath{lengthAsList} - 1) {
1865              
1866             (undef,
1867 0           my $asNumber) =
1868             unpack("a$offset N", $sFlowDatagramPacked);
1869              
1870             # push as number to array
1871 0           push @sFlowAsNumber, $asNumber;
1872 0           $offset += 4;
1873             }
1874              
1875             }
1876              
1877             }
1878              
1879             }
1880              
1881             # communities and localpref added in v.4.
1882 0 0         if ($sFlowDatagram->{sFlowVersion} >= SFLOWv4) {
1883              
1884             (undef,
1885 0           $sFlowSample->{GatewayLengthCommunitiesList}) =
1886             unpack("a$offset N", $sFlowDatagramPacked);
1887              
1888 0           $offset += 4;
1889              
1890             # boundcheck for $sFlowSample->{GatewayLengthCommunitiesList}
1891             # $sFlowSample->{GatewayLengthCommunitiesList} * 4
1892             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
1893              
1894 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
1895             $sFlowSample->{GatewayLengthCommunitiesList} * 4) {
1896              
1897             # error $sFlowSample->{GatewayLengthCommunitiesList} too big
1898 0           $error = "ERROR: [sFlow.pm] GatewayCommunitiesList: Gateway communities list count too big "
1899             . "- rest of the datagram skipped";
1900              
1901 0           return (undef, $error);
1902            
1903             # $sFlowSample->{GatewayLengthCommunitiesList} might very well be 0
1904             } elsif ($sFlowSample->{GatewayLengthCommunitiesList} < 0) {
1905              
1906             # error $sFlowSample->{GatewayLengthCommunitiesList} too small
1907 0           $error = "ERROR: [sFlow.pm] GatewayCommunitiesList: Gateway communities list count too small "
1908             . "- rest of the datagram skipped";
1909              
1910 0           return (undef, $error);
1911              
1912             } else {
1913              
1914 0           my @sFlowCommunities = ();
1915 0           $sFlowSample->{GatewayCommunities} = \@sFlowCommunities;
1916              
1917 0           for my $commLength (0 .. $sFlowSample->{GatewayLengthCommunitiesList} - 1) {
1918              
1919             (undef,
1920 0           my $community) =
1921             unpack("a$offset N", $sFlowDatagramPacked);
1922              
1923 0           $community = ($community >> 16) . ':' . ($community & 65535);
1924              
1925 0           push @sFlowCommunities, $community;
1926 0           $offset += 4;
1927             }
1928              
1929             }
1930              
1931             (undef,
1932 0           $sFlowSample->{localPref}) =
1933             unpack("a$offset N", $sFlowDatagramPacked);
1934              
1935 0           $offset += 4;
1936              
1937             }
1938              
1939 0           $$offsetref = $offset;
1940 0           return (1, undef);
1941              
1942             }
1943              
1944              
1945             #############################################################################
1946             sub _decodeUserData {
1947             #############################################################################
1948              
1949 0     0     my $offsetref = shift;
1950 0           my $sFlowDatagramPackedRef = shift;
1951 0           my $sFlowDatagram = shift;
1952 0           my $sFlowSample = shift;
1953              
1954 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
1955 0           my $offset = $$offsetref;
1956 0           my $error = undef;
1957              
1958 0           $sFlowSample->{USERDATA} = 'USERDATA';
1959              
1960 0 0         if ($sFlowDatagram->{sFlowVersion} == SFLOWv5) {
1961              
1962             (undef,
1963 0           $sFlowSample->{UserSrcCharset}) =
1964             unpack("a$offset N", $sFlowDatagramPacked);
1965              
1966 0           $offset += 4;
1967             }
1968              
1969             (undef,
1970 0           $sFlowSample->{UserLengthSrcString}) =
1971             unpack("a$offset N", $sFlowDatagramPacked);
1972              
1973 0           $offset += 4;
1974              
1975 0 0         if ($sFlowSample->{UserLengthSrcString} > length($sFlowDatagramPacked) - $offset) {
    0          
1976              
1977 0           $error = "ERROR: [sFlow.pm] UserData: UserLengthSrcString too big "
1978             . "- rest of the datagram skipped";
1979              
1980 0           return (undef, $error);
1981              
1982             } elsif ($sFlowSample->{UserLengthSrcString} < 0) {
1983              
1984 0           $error = "ERROR: [sFlow.pm] UserData: UserLengthSrcString too small "
1985             . "- rest of the datagram skipped";
1986              
1987 0           return (undef, $error);
1988              
1989             } else {
1990              
1991             (undef,
1992 0           $sFlowSample->{UserSrcString}) =
1993             unpack("a$offset A$sFlowSample->{UserLengthSrcString}", $sFlowDatagramPacked);
1994              
1995             # we have to cut off a $sFlowSample->{UserLengthSrcString} mod 4 == 0 number of bytes
1996 0           my $tmp = 4 - ($sFlowSample->{UserLengthSrcString} % 4);
1997 0 0         $tmp == 4 and $tmp = 0;
1998              
1999 0           $offset += ($sFlowSample->{UserLengthSrcString} + $tmp);
2000              
2001             }
2002              
2003 0 0         if ($sFlowDatagram->{sFlowVersion} == SFLOWv5) {
2004              
2005             (undef,
2006 0           $sFlowSample->{UserDestCharset}) =
2007             unpack("a$offset N", $sFlowDatagramPacked);
2008              
2009 0           $offset += 4;
2010             }
2011              
2012             (undef,
2013 0           $sFlowSample->{UserLengthDestString}) =
2014             unpack("a$offset N", $sFlowDatagramPacked);
2015              
2016 0           $offset += 4;
2017              
2018 0 0         if ($sFlowSample->{UserLengthDestString} > length($sFlowDatagramPacked) - $offset) {
    0          
2019              
2020 0           $error = "ERROR: [sFlow.pm] UserData: UserLengthDestString too big "
2021             . "- rest of the datagram skipped";
2022              
2023 0           return (undef, $error);
2024              
2025             } elsif ($sFlowSample->{UserLengthDestString} < 0) {
2026              
2027 0           $error = "ERROR: [sFlow.pm] UserData: UserLengthDestString too small "
2028             . "- rest of the datagram skipped";
2029              
2030 0           return (undef, $error);
2031              
2032             } else {
2033              
2034             (undef,
2035 0           $sFlowSample->{UserDestString}) =
2036             unpack("a$offset A$sFlowSample->{UserLengthDestString}", $sFlowDatagramPacked);
2037              
2038             # we have to cut off a $sFlowSample->{UserLengthDestString} mod 4 == 0 number of bytes
2039 0           my $tmp = 4 - ($sFlowSample->{UserLengthDestString} % 4);
2040 0 0         $tmp == 4 and $tmp = 0;
2041              
2042 0           $offset += ($sFlowSample->{UserLengthDestString} + $tmp);
2043              
2044             }
2045              
2046 0           $$offsetref = $offset;
2047 0           return (1, undef);
2048              
2049             }
2050              
2051              
2052             #############################################################################
2053             sub _decodeUrlData {
2054             #############################################################################
2055              
2056 0     0     my $offsetref = shift;
2057 0           my $sFlowDatagramPackedRef = shift;
2058 0           my $sFlowDatagram = shift;
2059 0           my $sFlowSample = shift;
2060              
2061 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2062 0           my $offset = $$offsetref;
2063 0           my $error = undef;
2064              
2065 0           $sFlowSample->{URLDATA} = 'URLDATA';
2066              
2067             (undef,
2068 0           $sFlowSample->{UrlDirection},
2069             $sFlowSample->{UrlLength}) =
2070             unpack("a$offset NN", $sFlowDatagramPacked);
2071              
2072 0           $offset += 8;
2073              
2074 0 0         if ($sFlowSample->{UrlLength} > length($sFlowDatagramPacked) - $offset) {
    0          
2075              
2076 0           $error = "ERROR: [sFlow.pm] UrlData: UrlLength too big "
2077             . "- rest of the datagram skipped";
2078              
2079 0           return (undef, $error);
2080              
2081             } elsif ($sFlowSample->{UrlLength} < 0) {
2082              
2083 0           $error = "ERROR: [sFlow.pm] UrlData: UrlLength too small "
2084             . "- rest of the datagram skipped";
2085              
2086 0           return (undef, $error);
2087              
2088             } else {
2089              
2090             (undef,
2091 0           $sFlowSample->{Url}) =
2092             unpack("a$offset A$sFlowSample->{UrlLength}", $sFlowDatagramPacked);
2093              
2094             # we have to cut off a $sFlowSample->{UrlLength} mod 4 == 0 number of bytes
2095 0           my $tmp = 4 - ($sFlowSample->{UrlLength} % 4);
2096 0 0         $tmp == 4 and $tmp = 0;
2097              
2098 0           $offset += ($sFlowSample->{UrlLength} + $tmp);
2099              
2100 0 0         if ($sFlowDatagram->{sFlowVersion} == SFLOWv5) {
2101              
2102             (undef,
2103 0           $sFlowSample->{UrlHostLength}) =
2104             unpack("a$offset N", $sFlowDatagramPacked);
2105              
2106 0           $offset += 4;
2107              
2108 0 0         if ($sFlowSample->{UrlHostLength} > length($sFlowDatagramPacked) - $offset) {
    0          
2109              
2110 0           $error = "ERROR: [sFlow.pm] UrlData: UrlHostLength too big "
2111             . "- rest of the datagram skipped";
2112              
2113 0           return (undef, $error);
2114              
2115             } elsif ($sFlowSample->{UrlHostLength} < 0) {
2116              
2117 0           $error = "ERROR: [sFlow.pm] UrlData: UrlHostLength too small "
2118             . "- rest of the datagram skipped";
2119              
2120 0           return (undef, $error);
2121              
2122             } else {
2123              
2124             (undef,
2125 0           $sFlowSample->{UrlHost}) =
2126             unpack("a$offset A$sFlowSample->{UrlHostLength}", $sFlowDatagramPacked);
2127              
2128             # we have to cut off a $sFlowSample->{UrlHostLength} mod 4 == 0 number of bytes
2129 0           my $tmp = 4 - ($sFlowSample->{UrlHostLength} % 4);
2130 0 0         $tmp == 4 and $tmp = 0;
2131              
2132 0           $offset += ($sFlowSample->{UrlHostLength} + $tmp);
2133              
2134             }
2135              
2136             }
2137              
2138             }
2139              
2140 0           $$offsetref = $offset;
2141 0           return (1, undef);
2142              
2143             }
2144              
2145              
2146             #############################################################################
2147             sub _decodeMplsData {
2148             #############################################################################
2149              
2150 0     0     my $offsetref = shift;
2151 0           my $sFlowDatagramPackedRef = shift;
2152 0           my $sFlowDatagram = shift;
2153 0           my $sFlowSample = shift;
2154 0           my $sFlowSamples = shift;
2155              
2156 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2157 0           my $offset = $$offsetref;
2158 0           my $subProcessed = undef;
2159 0           my $error = undef;
2160              
2161 0           $sFlowSample->{MPLSDATA} = 'MPLSDATA';
2162              
2163             (undef,
2164 0           $sFlowSample->{MplsIpVersionNextHopRouter}) =
2165             unpack("a$offset N", $sFlowDatagramPacked);
2166              
2167 0           $offset += 4;
2168              
2169 0           ($subProcessed, $error) =
2170             &_decodeIpAddress(
2171             \$offset,
2172             $sFlowDatagramPackedRef,
2173             $sFlowDatagram,
2174             $sFlowSample,
2175             $sFlowSamples,
2176             $sFlowSample->{MplsIpVersionNextHopRouter},
2177             'MplsIpVersionNextHopRouter',
2178             undef,
2179             );
2180              
2181 0 0         unless ($subProcessed) {
2182 0           return (undef, $error);
2183             }
2184              
2185             (undef,
2186 0           $sFlowSample->{MplsInLabelStackCount}) =
2187             unpack("a$offset N", $sFlowDatagramPacked);
2188              
2189 0           $offset += 4;
2190              
2191             # boundcheck for $sFlowSample->{MplsInLabelStackCount}
2192             # $sFlowSample->{MplsInLabelStackCount} * 4
2193             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
2194              
2195 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
2196             $sFlowSample->{MplsInLabelStackCount} * 4) {
2197              
2198             # error $sFlowSample->{MplsInLabelStack} too big
2199 0           $error = "ERROR: [sFlow.pm] MplsInLabel: Mpls in label stack count too big "
2200             . "- rest of the datagram skipped";
2201              
2202 0           return (undef, $error);
2203              
2204             } elsif ($sFlowSample->{MplsInLabelStackCount} < 0) {
2205              
2206             # error $sFlowSample->{MplsInLabelStack} too small
2207 0           $error = "ERROR: [sFlow.pm] MplsInLabel: Mpls in label stack count too small "
2208             . "- rest of the datagram skipped";
2209              
2210 0           return (undef, $error);
2211              
2212             } else {
2213              
2214 0           my @MplsInLabelStack = ();
2215 0           $sFlowSample->{MplsInLabelStack} = \@MplsInLabelStack;
2216              
2217 0           for my $MplsInLabelStackCount (0 .. $sFlowSample->{MplsInLabelStackCount} - 1) {
2218              
2219 0           (undef, my $MplsInLabel) = unpack("a$offset N", $sFlowDatagramPacked);
2220 0           push @MplsInLabelStack, $MplsInLabel;
2221 0           $offset += 4;
2222             }
2223              
2224             }
2225              
2226             (undef,
2227 0           $sFlowSample->{MplsOutLabelStackCount}) =
2228             unpack("a$offset N", $sFlowDatagramPacked);
2229              
2230 0           $offset += 4;
2231              
2232             # boundcheck for $sFlowSample->{MplsOutLabelStackCount}
2233             # $sFlowSample->{MplsOutLabelStackCount} * 4
2234             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
2235              
2236 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
2237             $sFlowSample->{MplsOutLabelStackCount} * 4) {
2238              
2239             # error $sFlowSample->{MplsOutLabelStack} too big
2240 0           $error = "ERROR: [sFlow.pm] MplsOutLabel: Mpls out label stack count too big "
2241             . "- rest of the datagram skipped";
2242              
2243 0           return (undef, $error);
2244              
2245             } elsif ($sFlowSample->{MplsOutLabelStackCount} < 0) {
2246              
2247             # error $sFlowSample->{MplsOutLabelStack} too small
2248 0           $error = "ERROR: [sFlow.pm] MplsOutLabel: Mpls out label stack count too small "
2249             . "- rest of the datagram skipped";
2250              
2251 0           return (undef, $error);
2252              
2253             } else {
2254              
2255 0           my @MplsOutLabelStack = ();
2256 0           $sFlowSample->{MplsOutLabelStack} = \@MplsOutLabelStack;
2257              
2258 0           for my $MplsOutLabelStackCount (0 .. $sFlowSample->{MplsOutLabelStackCount} - 1) {
2259              
2260 0           (undef, my $MplsOutLabel) = unpack("a$offset N", $sFlowDatagramPacked);
2261 0           push @MplsOutLabelStack, $MplsOutLabel;
2262 0           $offset += 4;
2263             }
2264              
2265             }
2266              
2267 0           $$offsetref = $offset;
2268 0           return (1, undef);
2269              
2270             }
2271              
2272              
2273             #############################################################################
2274             sub _decodeNatData {
2275             #############################################################################
2276              
2277 0     0     my $offsetref = shift;
2278 0           my $sFlowDatagramPackedRef = shift;
2279 0           my $sFlowDatagram = shift;
2280 0           my $sFlowSample = shift;
2281 0           my $sFlowSamples = shift;
2282              
2283 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2284 0           my $offset = $$offsetref;
2285 0           my $subProcessed = undef;
2286 0           my $error = undef;
2287              
2288 0           $sFlowSample->{NATDATA} = 'NATDATA';
2289              
2290             (undef,
2291 0           $sFlowSample->{NatIpVersionSrcAddress}) =
2292             unpack("a$offset N", $sFlowDatagramPacked);
2293              
2294 0           $offset += 4;
2295              
2296 0           ($subProcessed, $error) =
2297             &_decodeIpAddress(
2298             \$offset,
2299             $sFlowDatagramPackedRef,
2300             $sFlowDatagram,
2301             $sFlowSample,
2302             $sFlowSamples,
2303             $sFlowSample->{NatIpVersionSrcAddress},
2304             'NatIpVersionSrcAddress',
2305             undef,
2306             );
2307              
2308 0 0         unless ($subProcessed) {
2309 0           return (undef, $error);
2310             }
2311              
2312             (undef,
2313 0           $sFlowSample->{NatIpVersionDestAddress}) =
2314             unpack("a$offset N", $sFlowDatagramPacked);
2315              
2316 0           $offset += 4;
2317              
2318 0           ($subProcessed, $error) =
2319             &_decodeIpAddress(
2320             \$offset,
2321             $sFlowDatagramPackedRef,
2322             $sFlowDatagram,
2323             $sFlowSample,
2324             $sFlowSamples,
2325             $sFlowSample->{NatIpVersionDestAddress},
2326             'NatIpVersionDestAddress',
2327             undef,
2328             );
2329              
2330 0 0         unless ($subProcessed) {
2331 0           return (undef, $error);
2332             }
2333              
2334 0           $$offsetref = $offset;
2335 0           return (1, undef);
2336             }
2337              
2338              
2339             #############################################################################
2340             sub _decodeMplsTunnel {
2341             #############################################################################
2342              
2343 0     0     my $offsetref = shift;
2344 0           my $sFlowDatagramPackedRef = shift;
2345 0           my $sFlowSample = shift;
2346              
2347 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2348 0           my $offset = $$offsetref;
2349 0           my $error = undef;
2350              
2351 0           $sFlowSample->{MPLSTUNNEL} = 'MPLSTUNNEL';
2352              
2353             (undef,
2354 0           $sFlowSample->{MplsTunnelNameLength}) =
2355             unpack("a$offset N", $sFlowDatagramPacked);
2356              
2357 0           $offset += 4;
2358              
2359 0 0         if ($sFlowSample->{MplsTunnelNameLength} > length($sFlowDatagramPacked) - $offset) {
    0          
2360              
2361             # error $sFlowSample->{MplsTunnelLength} too big
2362 0           $error = "ERROR: [sFlow.pm] MplsTunnel: MplsTunnelNameLength too big "
2363             . "- rest of the datagram skipped";
2364              
2365 0           return (undef, $error);
2366              
2367             } elsif ($sFlowSample->{MplsTunnelNameLength} < 0) {
2368              
2369             # error $sFlowSample->{MplsTunnelLength} too small
2370 0           $error = "ERROR: [sFlow.pm] MplsTunnel: MplsTunnelNameLength too small "
2371             . "- rest of the datagram skipped";
2372              
2373 0           return (undef, $error);
2374              
2375             } else {
2376              
2377             (undef,
2378 0           $sFlowSample->{MplsTunnelName}) =
2379             unpack("a$offset A$sFlowSample->{MplsTunnelNameLength}", $sFlowDatagramPacked);
2380              
2381             # we have to cut off a $sFlowSample->{MplsTunnelLength} mod 4 == 0 number of bytes
2382 0           my $tmp = 4 - ($sFlowSample->{MplsTunnelNameLength} % 4);
2383 0 0         $tmp == 4 and $tmp = 0;
2384              
2385 0           $offset += ($sFlowSample->{MplsTunnelNameLength} + $tmp);
2386              
2387             (undef,
2388 0           $sFlowSample->{MplsTunnelId},
2389             $sFlowSample->{MplsTunnelCosValue}) =
2390             unpack("a$offset NN", $sFlowDatagramPacked);
2391              
2392 0           $offset += 8;
2393              
2394             }
2395              
2396 0           $$offsetref = $offset;
2397 0           return (1, undef);
2398              
2399             }
2400              
2401              
2402             #############################################################################
2403             sub _decodeMplsVc {
2404             #############################################################################
2405              
2406 0     0     my $offsetref = shift;
2407 0           my $sFlowDatagramPackedRef = shift;
2408 0           my $sFlowSample = shift;
2409              
2410 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2411 0           my $offset = $$offsetref;
2412 0           my $error = undef;
2413              
2414 0           $sFlowSample->{MPLSVC} = 'MPLSVC';
2415              
2416             (undef,
2417 0           $sFlowSample->{MplsVcInstanceNameLength}) =
2418             unpack("a$offset N", $sFlowDatagramPacked);
2419              
2420 0           $offset += 4;
2421              
2422 0 0         if ($sFlowSample->{MplsVcInstanceNameLength} > length($sFlowDatagramPacked) - $offset) {
    0          
2423              
2424             # error $sFlowSample->{MplsVcInstanceNameLength} too big
2425 0           $error = "ERROR: [sFlow.pm] MplsVc: MplsVcInstanceNameLength too big "
2426             . "- rest of the datagram skipped";
2427              
2428 0           return (undef, $error);
2429              
2430             } elsif ($sFlowSample->{MplsVcInstanceNameLength} < 0) {
2431              
2432             # error $sFlowSample->{MplsVcInstanceNameLength} too small
2433 0           $error = "ERROR: [sFlow.pm] MplsVc: MplsVcInstanceNameLength too small "
2434             . "- rest of the datagram skipped";
2435              
2436 0           return (undef, $error);
2437              
2438             } else {
2439              
2440             (undef,
2441 0           $sFlowSample->{MplsVcInstanceName}) =
2442             unpack("a$offset A$sFlowSample->{MplsVcInstanceNameLength}", $sFlowDatagramPacked);
2443              
2444             # we have to cut off a $sFlowSample->{MplsVcInstanceNameLength} mod 4 == 0 number of bytes
2445 0           my $tmp = 4 - ($sFlowSample->{MplsVcInstanceNameLength} % 4);
2446 0 0         $tmp == 4 and $tmp = 0;
2447              
2448 0           $offset += ($sFlowSample->{MplsVcInstanceNameLength} + $tmp);
2449              
2450             (undef,
2451 0           $sFlowSample->{MplsVcId},
2452             $sFlowSample->{MplsVcLabelCosValue}) =
2453             unpack("a$offset NN", $sFlowDatagramPacked);
2454              
2455 0           $offset += 8;
2456              
2457             }
2458              
2459 0           $$offsetref = $offset;
2460 0           return (1, undef);
2461              
2462             }
2463              
2464              
2465             #############################################################################
2466             sub _decodeMplsFec {
2467             #############################################################################
2468              
2469 0     0     my $offsetref = shift;
2470 0           my $sFlowDatagramPackedRef = shift;
2471 0           my $sFlowSample = shift;
2472              
2473 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2474 0           my $offset = $$offsetref;
2475 0           my $error = undef;
2476              
2477 0           $sFlowSample->{MPLSFEC} = 'MPLSFEC';
2478              
2479             (undef,
2480 0           $sFlowSample->{MplsFtnDescrLength}) =
2481             unpack("a$offset N", $sFlowDatagramPacked);
2482              
2483 0           $offset += 4;
2484              
2485 0 0         if ($sFlowSample->{MplsFtnDescrLength} > length($sFlowDatagramPacked) - $offset) {
    0          
2486              
2487             # error $sFlowSample->{{MplsFtnDescrLength} too big
2488 0           $error = "ERROR: [sFlow.pm] MplsFec: MplsFtnDescrLength too big "
2489             . "- rest of the datagram skipped";
2490              
2491 0           return (undef, $error);
2492              
2493             } elsif ($sFlowSample->{MplsFtnDescrLength} < 0) {
2494              
2495             # error $sFlowSample->{{MplsFtnDescrLength} too small
2496 0           $error = "ERROR: [sFlow.pm] MplsFec: MplsFtnDescrLength too small "
2497             . "- rest of the datagram skipped";
2498              
2499 0           return (undef, $error);
2500              
2501             } else {
2502              
2503             (undef,
2504 0           $sFlowSample->{MplsFtnDescr}) =
2505             unpack("a$offset A$sFlowSample->{MplsFtnDescrLength}", $sFlowDatagramPacked);
2506              
2507             # we have to cut off a $sFlowSample->{MplsFtrDescrLength} mod 4 == 0 number of bytes
2508 0           my $tmp = 4 - ($sFlowSample->{MplsFtrDescrLength} % 4);
2509 0 0         $tmp == 4 and $tmp = 0;
2510              
2511 0           $offset += ($sFlowSample->{MplsFtrDescrLength} + $tmp);
2512              
2513 0           (undef, $sFlowSample->{MplsFtnMask}) = unpack("a$offset N", $sFlowDatagramPacked);
2514 0           $offset += 4;
2515              
2516             }
2517              
2518 0           $$offsetref = $offset;
2519 0           return (1, undef);
2520              
2521             }
2522              
2523              
2524             #############################################################################
2525             sub _decodeMplsLpvFec {
2526             #############################################################################
2527              
2528 0     0     my $offsetref = shift;
2529 0           my $sFlowDatagramPackedRef = shift;
2530 0           my $sFlowSample = shift;
2531              
2532 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2533 0           my $offset = $$offsetref;
2534              
2535 0           $sFlowSample->{MPLSLPVFEC} = 'MPLSLPVFEC';
2536              
2537             (undef,
2538 0           $sFlowSample->{MplsFecAddrPrefixLength}) =
2539             unpack("a$offset N", $sFlowDatagramPacked);
2540              
2541 0           $offset += 4;
2542              
2543 0           $$offsetref = $offset;
2544             }
2545              
2546              
2547             #############################################################################
2548             sub _decodeVlanTunnel {
2549             #############################################################################
2550              
2551 0     0     my $offsetref = shift;
2552 0           my $sFlowDatagramPackedRef = shift;
2553 0           my $sFlowSample = shift;
2554              
2555 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2556 0           my $offset = $$offsetref;
2557 0           my $error = undef;
2558              
2559 0           $sFlowSample->{VLANTUNNEL} = 'VLANTUNNEL';
2560              
2561             (undef,
2562 0           $sFlowSample->{VlanTunnelLayerStackCount}) =
2563             unpack("a$offset N", $sFlowDatagramPacked);
2564              
2565 0           $offset += 4;
2566              
2567             # boundcheck for $sFlowSample->{VlanTunnelLayerStackCount}
2568             # $sFlowSample->{VlanTunnelLayerStackCount} * 4
2569             # cannot be longer than the number of $sFlowDatagramPacked byte - $offset
2570              
2571 0 0         if (length($sFlowDatagramPacked) - $offset <
    0          
2572             $sFlowSample->{VlanTunnelLayerStackCount} * 4) {
2573              
2574             # error $sFlowSample->{VlanTunnelLayerStackCount} too big
2575 0           $error = "ERROR: [sFlow.pm] VlanTunnel: Vlan tunnel stack count too big "
2576             . "- rest of the datagram skipped";
2577              
2578 0           return (undef, $error);
2579              
2580             } elsif ($sFlowSample->{VlanTunnelLayerStackCount} < 0) {
2581              
2582             # error $sFlowSample->{VlanTunnelLayerStackCount} too small
2583 0           $error = "ERROR: [sFlow.pm] VlanTunnel: Vlan tunnel stack count too small "
2584             . "- rest of the datagram skipped";
2585              
2586 0           return (undef, $error);
2587              
2588             } else {
2589              
2590 0           my @VlanTunnelLayerStack = ();
2591 0           $sFlowSample->{VlanTunnelLayerStack} = \@VlanTunnelLayerStack;
2592              
2593 0           for my $VlanTunnelLayerCount (0 .. $sFlowSample->{VlanTunnelLayerStackCount} - 1) {
2594              
2595 0           (undef, my $VlanTunnelLayer) = unpack("a$offset N", $sFlowDatagramPacked);
2596 0           push @VlanTunnelLayerStack, $VlanTunnelLayer;
2597 0           $offset += 4;
2598             }
2599              
2600             }
2601              
2602 0           $$offsetref = $offset;
2603 0           return (1, undef);
2604              
2605             }
2606              
2607              
2608             #############################################################################
2609             sub _decodeCounterGeneric {
2610             #############################################################################
2611              
2612 0     0     my $offsetref = shift;
2613 0           my $sFlowDatagramPackedRef = shift;
2614 0           my $sFlowSample = shift;
2615              
2616 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2617 0           my $offset = $$offsetref;
2618 0           my $ifSpeed1 = undef;
2619 0           my $ifSpeed2 = undef;
2620 0           my $ifInOctets1 = undef;
2621 0           my $ifInOctets2 = undef;
2622 0           my $ifOutOctets1 = undef;
2623 0           my $ifOutOctets2 = undef;
2624 0           my $ifStatus = undef;
2625              
2626 0           $sFlowSample->{COUNTERGENERIC} = 'COUNTERGENERIC';
2627              
2628             (undef,
2629 0           $sFlowSample->{ifIndex},
2630             $sFlowSample->{ifType},
2631             $ifSpeed1,
2632             $ifSpeed2,
2633             $sFlowSample->{ifDirection},
2634             $ifStatus,
2635             $ifInOctets1,
2636             $ifInOctets2,
2637             $sFlowSample->{ifInUcastPkts},
2638             $sFlowSample->{ifInMulticastPkts},
2639             $sFlowSample->{ifInBroadcastPkts},
2640             $sFlowSample->{ifInDiscards},
2641             $sFlowSample->{ifInErrors},
2642             $sFlowSample->{ifInUnknownProtos},
2643             $ifOutOctets1,
2644             $ifOutOctets2,
2645             $sFlowSample->{ifOutUcastPkts},
2646             $sFlowSample->{ifOutMulticastPkts},
2647             $sFlowSample->{ifOutBroadcastPkts},
2648             $sFlowSample->{ifOutDiscards},
2649             $sFlowSample->{ifOutErrors},
2650             $sFlowSample->{ifPromiscuousMode}) =
2651             unpack("a$offset N22", $sFlowDatagramPacked);
2652              
2653 0           $offset += 88;
2654              
2655 0           $sFlowSample->{ifSpeed} = Math::BigInt->new("$ifSpeed1");
2656 0           $sFlowSample->{ifSpeed} = $sFlowSample->{ifSpeed} << 32;
2657 0           $sFlowSample->{ifSpeed} += $ifSpeed2;
2658              
2659 0           $sFlowSample->{ifInOctets} = Math::BigInt->new("$ifInOctets1");
2660 0           $sFlowSample->{ifInOctets} = $sFlowSample->{ifInOctets} << 32;
2661 0           $sFlowSample->{ifInOctets} += $ifInOctets2;
2662              
2663 0           $sFlowSample->{ifOutOctets} = Math::BigInt->new("$ifOutOctets1");
2664 0           $sFlowSample->{ifOutOctets} = $sFlowSample->{ifOutOctets} << 32;
2665 0           $sFlowSample->{ifOutOctets} += $ifOutOctets2;
2666              
2667             # seperate the 32bit status
2668 0           $sFlowSample->{ifAdminStatus} = $ifStatus & 0x1;
2669 0           $sFlowSample->{ifOperStatus} = ($ifStatus >> 1) & 0x1;
2670              
2671 0           $$offsetref = $offset;
2672             }
2673              
2674              
2675             #############################################################################
2676             sub _decodeCounterEthernet {
2677             #############################################################################
2678              
2679 0     0     my $offsetref = shift;
2680 0           my $sFlowDatagramPackedRef = shift;
2681 0           my $sFlowSample = shift;
2682              
2683 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2684 0           my $offset = $$offsetref;
2685              
2686 0           $sFlowSample->{COUNTERETHERNET} = 'COUNTERETHERNET';
2687              
2688             (undef,
2689 0           $sFlowSample->{dot3StatsAlignmentErrors},
2690             $sFlowSample->{dot3StatsFCSErrors},
2691             $sFlowSample->{dot3StatsSingleCollisionFrames},
2692             $sFlowSample->{dot3StatsMultipleCollisionFrames},
2693             $sFlowSample->{dot3StatsSQETestErrors},
2694             $sFlowSample->{dot3StatsDeferredTransmissions},
2695             $sFlowSample->{dot3StatsLateCollisions},
2696             $sFlowSample->{dot3StatsExcessiveCollisions},
2697             $sFlowSample->{dot3StatsInternalMacTransmitErrors},
2698             $sFlowSample->{dot3StatsCarrierSenseErrors},
2699             $sFlowSample->{dot3StatsFrameTooLongs},
2700             $sFlowSample->{dot3StatsInternalMacReceiveErrors},
2701             $sFlowSample->{dot3StatsSymbolErrors}) =
2702             unpack("a$offset N13", $sFlowDatagramPacked);
2703              
2704 0           $offset += 52;
2705 0           $$offsetref = $offset;
2706             }
2707              
2708              
2709             #############################################################################
2710             sub _decodeCounterTokenring {
2711             #############################################################################
2712              
2713 0     0     my $offsetref = shift;
2714 0           my $sFlowDatagramPackedRef = shift;
2715 0           my $sFlowSample = shift;
2716              
2717 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2718 0           my $offset = $$offsetref;
2719              
2720 0           $sFlowSample->{COUNTERTOKENRING} = 'COUNTERTOKENRING';
2721              
2722             (undef,
2723 0           $sFlowSample->{dot5StatsLineErrors},
2724             $sFlowSample->{dot5StatsBurstErrors},
2725             $sFlowSample->{dot5StatsACErrors},
2726             $sFlowSample->{dot5StatsAbortTransErrors},
2727             $sFlowSample->{dot5StatsInternalErrors},
2728             $sFlowSample->{dot5StatsLostFrameErrors},
2729             $sFlowSample->{dot5StatsReceiveCongestions},
2730             $sFlowSample->{dot5StatsFrameCopiedErrors},
2731             $sFlowSample->{dot5StatsTokenErrors},
2732             $sFlowSample->{dot5StatsSoftErrors},
2733             $sFlowSample->{dot5StatsHardErrors},
2734             $sFlowSample->{dot5StatsSignalLoss},
2735             $sFlowSample->{dot5StatsTransmitBeacons},
2736             $sFlowSample->{dot5StatsRecoverys},
2737             $sFlowSample->{dot5StatsLobeWires},
2738             $sFlowSample->{dot5StatsRemoves},
2739             $sFlowSample->{dot5StatsSingles},
2740             $sFlowSample->{dot5StatsFreqErrors}) =
2741             unpack("a$offset N18", $sFlowDatagramPacked);
2742              
2743 0           $offset += 72;
2744 0           $$offsetref = $offset;
2745             }
2746              
2747              
2748             #############################################################################
2749             sub _decodeCounterVg {
2750             #############################################################################
2751              
2752 0     0     my $offsetref = shift;
2753 0           my $sFlowDatagramPackedRef = shift;
2754 0           my $sFlowSample = shift;
2755              
2756 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2757 0           my $offset = $$offsetref;
2758 0           my $dot12InHighPriorityOctets1 = undef;
2759 0           my $dot12InHighPriorityOctets2 = undef;
2760 0           my $dot12InNormPriorityOctets1 = undef;
2761 0           my $dot12InNormPriorityOctets2 = undef;
2762 0           my $dot12OutHighPriorityOctets1 = undef;
2763 0           my $dot12OutHighPriorityOctets2 = undef;
2764 0           my $dot12HCInHighPriorityOctets1 = undef;
2765 0           my $dot12HCInHighPriorityOctets2 = undef;
2766 0           my $dot12HCInNormPriorityOctets1 = undef;
2767 0           my $dot12HCInNormPriorityOctets2 = undef;
2768 0           my $dot12HCOutHighPriorityOctets1 = undef;
2769 0           my $dot12HCOutHighPriorityOctets2 = undef;
2770              
2771 0           $sFlowSample->{COUNTERVG} = 'COUNTERVG';
2772              
2773             (undef,
2774 0           $sFlowSample->{dot12InHighPriorityFrames},
2775             $dot12InHighPriorityOctets1,
2776             $dot12InHighPriorityOctets2,
2777             $sFlowSample->{dot12InNormPriorityFrames},
2778             $dot12InNormPriorityOctets1,
2779             $dot12InNormPriorityOctets2,
2780             $sFlowSample->{dot12InIPMErrors},
2781             $sFlowSample->{dot12InOversizeFrameErrors},
2782             $sFlowSample->{dot12InDataErrors},
2783             $sFlowSample->{dot12InNullAddressedFrames},
2784             $sFlowSample->{dot12OutHighPriorityFrames},
2785             $dot12OutHighPriorityOctets1,
2786             $dot12OutHighPriorityOctets2,
2787             $sFlowSample->{dot12TransitionIntoTrainings},
2788             $dot12HCInHighPriorityOctets1,
2789             $dot12HCInHighPriorityOctets2,
2790             $dot12HCInNormPriorityOctets1,
2791             $dot12HCInNormPriorityOctets2,
2792             $dot12HCOutHighPriorityOctets1,
2793             $dot12HCOutHighPriorityOctets2) =
2794             unpack("a$offset N20", $sFlowDatagramPacked);
2795              
2796 0           $offset += 80;
2797              
2798 0           $sFlowSample->{dot12InHighPriorityOctets} = Math::BigInt->new("$dot12InHighPriorityOctets1");
2799 0           $sFlowSample->{dot12InHighPriorityOctets} = $sFlowSample->{dot12InHighPriorityOctets} << 32;
2800 0           $sFlowSample->{dot12InHighPriorityOctets} += $dot12InHighPriorityOctets2;
2801              
2802 0           $sFlowSample->{dot12InNormPriorityOctets} = Math::BigInt->new("$dot12InNormPriorityOctets1");
2803 0           $sFlowSample->{dot12InNormPriorityOctets} = $sFlowSample->{dot12InNormPriorityOctets} << 32;
2804 0           $sFlowSample->{dot12InNormPriorityOctets} += $dot12InNormPriorityOctets2;
2805              
2806 0           $sFlowSample->{dot12OutHighPriorityOctets} = Math::BigInt->new("$dot12OutHighPriorityOctets1");
2807 0           $sFlowSample->{dot12OutHighPriorityOctets} = $sFlowSample->{dot12OutHighPriorityOctets} << 32;
2808 0           $sFlowSample->{dot12OutHighPriorityOctets} += $dot12OutHighPriorityOctets2;
2809              
2810 0           $sFlowSample->{dot12HCInHighPriorityOctets} = Math::BigInt->new("$dot12HCInHighPriorityOctets1");
2811 0           $sFlowSample->{dot12HCInHighPriorityOctets} = $sFlowSample->{dot12HCInHighPriorityOctets} << 32;
2812 0           $sFlowSample->{dot12HCInHighPriorityOctets} += $dot12HCInHighPriorityOctets2;
2813              
2814 0           $sFlowSample->{dot12HCInNormPriorityOctets} = Math::BigInt->new("$dot12HCInNormPriorityOctets1");
2815 0           $sFlowSample->{dot12HCInNormPriorityOctets} = $sFlowSample->{dot12HCInNormPriorityOctets} << 32;
2816 0           $sFlowSample->{dot12HCInNormPriorityOctets} += $dot12HCInNormPriorityOctets2;
2817              
2818 0           $sFlowSample->{dot12HCOutHighPriorityOctets} = Math::BigInt->new("$dot12HCOutHighPriorityOctets1");
2819 0           $sFlowSample->{dot12HCOutHighPriorityOctets} = $sFlowSample->{dot12HCOutHighPriorityOctets} << 32;
2820 0           $sFlowSample->{dot12HCOutHighPriorityOctets} += $dot12HCOutHighPriorityOctets2;
2821              
2822 0           $$offsetref = $offset;
2823             }
2824              
2825              
2826             #############################################################################
2827             sub _decodeCounterVlan {
2828             #############################################################################
2829              
2830 0     0     my $offsetref = shift;
2831 0           my $sFlowDatagramPackedRef = shift;
2832 0           my $sFlowSample = shift;
2833              
2834 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2835 0           my $offset = $$offsetref;
2836 0           my $octets1 = undef;
2837 0           my $octets2 = undef;
2838              
2839 0           $sFlowSample->{COUNTERVLAN} = 'COUNTERVLAN';
2840              
2841             (undef,
2842 0           $sFlowSample->{vlan_id},
2843             $octets1,
2844             $octets2,
2845             $sFlowSample->{ucastPkts},
2846             $sFlowSample->{multicastPkts},
2847             $sFlowSample->{broadcastPkts},
2848             $sFlowSample->{discards}) =
2849             unpack("a$offset N7", $sFlowDatagramPacked);
2850              
2851 0           $offset += 28;
2852              
2853 0           $sFlowSample->{octets} = Math::BigInt->new("$octets1");
2854 0           $sFlowSample->{octets} = $sFlowSample->{octets} << 32;
2855 0           $sFlowSample->{octets} += $octets2;
2856              
2857 0           $$offsetref = $offset;
2858             }
2859              
2860              
2861             #############################################################################
2862             sub _decodeCounterProcessor {
2863             #############################################################################
2864              
2865 0     0     my $offsetref = shift;
2866 0           my $sFlowDatagramPackedRef = shift;
2867 0           my $sFlowSample = shift;
2868              
2869 0           my $sFlowDatagramPacked = $$sFlowDatagramPackedRef;
2870 0           my $offset = $$offsetref;
2871 0           my $memoryTotal1 = undef;
2872 0           my $memoryTotal2 = undef;
2873 0           my $memoryFree1 = undef;
2874 0           my $memoryFree2 = undef;
2875              
2876 0           $sFlowSample->{COUNTERPROCESSOR} = 'COUNTERPROCESSOR';
2877              
2878             (undef,
2879 0           $sFlowSample->{cpu5s},
2880             $sFlowSample->{cpu1m},
2881             $sFlowSample->{cpu5m},
2882             $memoryTotal1,
2883             $memoryTotal2,
2884             $memoryFree1,
2885             $memoryFree2) =
2886             unpack("a$offset N7", $sFlowDatagramPacked);
2887              
2888 0           $offset += 28;
2889              
2890 0           $sFlowSample->{memoryTotal} = Math::BigInt->new("$memoryTotal1");
2891 0           $sFlowSample->{memoryTotal} = $sFlowSample->{memoryTotal} << 32;
2892 0           $sFlowSample->{memoryTotal} += $memoryTotal2;
2893              
2894 0           $sFlowSample->{memoryFree} = Math::BigInt->new("$memoryFree1");
2895 0           $sFlowSample->{memoryFree} = $sFlowSample->{memoryFree} << 32;
2896 0           $sFlowSample->{memoryFree} += $memoryFree2;
2897              
2898 0           $$offsetref = $offset;
2899             }
2900              
2901              
2902             1;
2903              
2904              
2905             __END__