xref: /openbsd-src/regress/sys/net/pflow/flow.pl (revision bfa684ac25aa831afda4a9f0631fb3f41f0aaa88)
1b5ac7c87Sflorian#! /usr/bin/perl
2*bfa684acSbluhm# $OpenBSD: flow.pl,v 1.6 2017/03/03 21:34:14 bluhm Exp $
3b5ac7c87Sflorian
4b5ac7c87Sflorian# Copyright (c) 2013 Florian Obser <florian@openbsd.org>
5b5ac7c87Sflorian#
6b5ac7c87Sflorian# Permission to use, copy, modify, and distribute this software for any
7b5ac7c87Sflorian# purpose with or without fee is hereby granted, provided that the above
8b5ac7c87Sflorian# copyright notice and this permission notice appear in all copies.
9b5ac7c87Sflorian#
10b5ac7c87Sflorian# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b5ac7c87Sflorian# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b5ac7c87Sflorian# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b5ac7c87Sflorian# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b5ac7c87Sflorian# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b5ac7c87Sflorian# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b5ac7c87Sflorian# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b5ac7c87Sflorian
18b5ac7c87Sflorian
19b5ac7c87Sflorianuse strict;
20b5ac7c87Sflorianuse warnings;
21b5ac7c87Sflorianuse 5.010;
22b3e4b791Sbluhmuse Config;
23b5ac7c87Sflorian
24b5ac7c87Sflorianuse Data::Dumper;
25b5ac7c87Sflorianuse IO::Socket::INET;
26b5ac7c87Sflorianuse Net::Flow;
27b5ac7c87Sflorian
28b5ac7c87Sflorianmy $port = 9996;
29b5ac7c87Sflorian
30b5ac7c87Sflorian{
31b5ac7c87Sflorian	my $id2name = {
32b5ac7c87Sflorian		  1 => 'octetDeltaCount',
33b5ac7c87Sflorian		  2 => 'packetDeltaCount',
34b5ac7c87Sflorian		  4 => 'protocolIdentifier',
35b5ac7c87Sflorian		  5 => 'ipClassOfService',
36b5ac7c87Sflorian		  7 => 'sourceTransportPort',
37b5ac7c87Sflorian		  8 => 'sourceIPv4Address',
38b5ac7c87Sflorian		 10 => 'ingressInterface',
39b5ac7c87Sflorian		 11 => 'destinationTransportPort',
40b5ac7c87Sflorian		 12 => 'destinationIPv4Address',
41b5ac7c87Sflorian		 14 => 'egressInterface',
42b5ac7c87Sflorian		 21 => 'flowEndSysUpTime',
43b5ac7c87Sflorian		 22 => 'flowStartSysUpTime',
44b5ac7c87Sflorian		 27 => 'sourceIPv6Address',
45b5ac7c87Sflorian		 28 => 'destinationIPv6Address',
46b5ac7c87Sflorian		150 => 'flowStartSeconds',
47b5ac7c87Sflorian		151 => 'flowEndSeconds',
48b5ac7c87Sflorian		152 => 'flowStartMilliseconds',
49b5ac7c87Sflorian		153 => 'flowEndMilliseconds',
50b5ac7c87Sflorian	};
51b5ac7c87Sflorian	my $name2id = {reverse %$id2name};
52b5ac7c87Sflorian	sub id2name { return $id2name->{$_[0]} || $_[0]; }
53b5ac7c87Sflorian	sub name2id { return $name2id->{$_[0]} || $_[0]; }
54b5ac7c87Sflorian}
55b5ac7c87Sflorian
56b5ac7c87Sfloriansub get_ifs
57b5ac7c87Sflorian{
58b5ac7c87Sflorian	my (@ifs, $prog);
59b5ac7c87Sflorian	open($prog, 'ifconfig |') or die $!;
60b5ac7c87Sflorian	while(<$prog>) {
61b5ac7c87Sflorian		chomp;
62b5ac7c87Sflorian		push(@ifs, $1) if(/^(\w+):/);
63b5ac7c87Sflorian	}
64b5ac7c87Sflorian	close($prog) or die $!;
65b5ac7c87Sflorian	return(grep({$_ ne 'lo0'} @ifs));
66b5ac7c87Sflorian}
67b5ac7c87Sflorian
68b5ac7c87Sfloriansub gen_pf_conf
69b5ac7c87Sflorian{
70b5ac7c87Sflorian	my @ifs = @_;
71b5ac7c87Sflorian	my $skip = 'set skip on {'.join(' ', @ifs).'}';
72b5ac7c87Sflorian	return <<END;
73b5ac7c87Sflorian$skip
74b5ac7c87Sflorianpass on lo0 no state
75b5ac7c87Sflorianpass on lo0 proto tcp from port 12345 to port 12346 keep state (pflow)
76b5ac7c87SflorianEND
77b5ac7c87Sflorian}
78b5ac7c87Sflorian
79b5ac7c87Sflorianif (scalar(@ARGV) != 2 || ($ARGV[0] != 9 && $ARGV[0]!=10)) {
80b5ac7c87Sflorian	print STDERR "usage: $0 [9|10] [4|6]\n";
81b5ac7c87Sflorian	exit(1);
82b5ac7c87Sflorian}
83b5ac7c87Sflorian
84b5ac7c87Sflorianif (scalar(@ARGV) != 2 || ($ARGV[1] != 4 && $ARGV[1]!=6)) {
85b5ac7c87Sflorian	print STDERR "usage: $0 [9|10] [4|6]\n";
86b5ac7c87Sflorian	exit(1);
87b5ac7c87Sflorian}
88b5ac7c87Sflorian
89b5ac7c87Sflorian
90b5ac7c87Sflorianmy @v94_elem_names = qw (sourceIPv4Address
91b5ac7c87Sflorian    destinationIPv4Address
92b5ac7c87Sflorian    ingressInterface
93b5ac7c87Sflorian    egressInterface
94b5ac7c87Sflorian    packetDeltaCount
95b5ac7c87Sflorian    octetDeltaCount
96b5ac7c87Sflorian    flowStartSysUpTime
97b5ac7c87Sflorian    flowEndSysUpTime
98b5ac7c87Sflorian    sourceTransportPort
99b5ac7c87Sflorian    destinationTransportPort
100b5ac7c87Sflorian    ipClassOfService
101b5ac7c87Sflorian    protocolIdentifier);
102b5ac7c87Sflorian
103b5ac7c87Sflorianmy @v96_elem_names = qw (sourceIPv6Address
104b5ac7c87Sflorian    destinationIPv6Address
105b5ac7c87Sflorian    ingressInterface
106b5ac7c87Sflorian    egressInterface
107b5ac7c87Sflorian    packetDeltaCount
108b5ac7c87Sflorian    octetDeltaCount
109b5ac7c87Sflorian    flowStartSysUpTime
110b5ac7c87Sflorian    flowEndSysUpTime
111b5ac7c87Sflorian    sourceTransportPort
112b5ac7c87Sflorian    destinationTransportPort
113b5ac7c87Sflorian    ipClassOfService
114b5ac7c87Sflorian    protocolIdentifier);
115b5ac7c87Sflorian
116b5ac7c87Sflorianmy @v104_elem_names = qw (sourceIPv4Address
117b5ac7c87Sflorian    destinationIPv4Address
118b5ac7c87Sflorian    ingressInterface
119b5ac7c87Sflorian    egressInterface
120b5ac7c87Sflorian    packetDeltaCount
121b5ac7c87Sflorian    octetDeltaCount
122b5ac7c87Sflorian    flowStartMilliseconds
123b5ac7c87Sflorian    flowEndMilliseconds
124b5ac7c87Sflorian    sourceTransportPort
125b5ac7c87Sflorian    destinationTransportPort
126b5ac7c87Sflorian    ipClassOfService
127b5ac7c87Sflorian    protocolIdentifier);
128b5ac7c87Sflorian
129b5ac7c87Sflorianmy @v106_elem_names = qw (sourceIPv6Address
130b5ac7c87Sflorian    destinationIPv6Address
131b5ac7c87Sflorian    ingressInterface
132b5ac7c87Sflorian    egressInterface
133b5ac7c87Sflorian    packetDeltaCount
134b5ac7c87Sflorian    octetDeltaCount
135b5ac7c87Sflorian    flowStartMilliseconds
136b5ac7c87Sflorian    flowEndMilliseconds
137b5ac7c87Sflorian    sourceTransportPort
138b5ac7c87Sflorian    destinationTransportPort
139b5ac7c87Sflorian    ipClassOfService
140b5ac7c87Sflorian    protocolIdentifier);
141b5ac7c87Sflorian
142b5ac7c87Sflorianmy ($name, $sock, $packet, $header_ref, $template_ref, $flow_ref, $flows_ref,
143b5ac7c87Sflorian    $error_ref, @elem_names, $prog, $line);
144b5ac7c87Sflorian
145b3e4b791Sbluhmsystem('ifconfig', 'lo0', 'inet', '10.11.12.13', 'alias');
146b5ac7c87Sfloriansystem('ifconfig', 'lo0', 'inet6', '2001:db8::13');
147b5ac7c87Sflorian
148b5ac7c87Sflorianopen($prog, '|pfctl -f -') or die $!;
149b5ac7c87Sflorianprint $prog gen_pf_conf(get_ifs());
150b5ac7c87Sflorianclose($prog) or die $!;
151b5ac7c87Sflorian
152b5ac7c87Sflorianif (`ifconfig pflow0 2>&1` ne "pflow0: no such interface\n") {
153b5ac7c87Sflorian	system('ifconfig', 'pflow0', 'destroy');
154b5ac7c87Sflorian}
155b5ac7c87Sflorian
156b5ac7c87Sfloriansystem('ifconfig', 'pflow0', 'flowsrc', '127.0.0.1', 'flowdst',
157b5ac7c87Sflorian    '127.0.0.1:9996', 'pflowproto', $ARGV[0]);
158b5ac7c87Sflorian
159b5ac7c87Sfloriansystem('./gen_traffic '.$ARGV[1].' &');
160b5ac7c87Sflorian
161b5ac7c87Sflorianif ($ARGV[0] == 9 && $ARGV[1] == 4) {
162b5ac7c87Sflorian	@elem_names = @v94_elem_names;
163b5ac7c87Sflorian} elsif ($ARGV[0] == 9 && $ARGV[1] == 6) {
164b5ac7c87Sflorian	@elem_names = @v96_elem_names;
165b5ac7c87Sflorian} elsif ($ARGV[0] == 10 && $ARGV[1] == 4) {
166b5ac7c87Sflorian	@elem_names = @v104_elem_names;
167b5ac7c87Sflorian} elsif ($ARGV[0] == 10 && $ARGV[1] == 6) {
168b5ac7c87Sflorian	@elem_names = @v106_elem_names;
169b5ac7c87Sflorian}
170b5ac7c87Sflorian
171b5ac7c87Sflorian$sock = IO::Socket::INET->new(LocalPort =>$port, Proto => 'udp');
172b5ac7c87Sflorianwhile ($sock->recv($packet,1548)) {
173b5ac7c87Sflorian	($header_ref, $template_ref, $flows_ref, $error_ref) =
174b5ac7c87Sflorian		Net::Flow::decode(\$packet, $template_ref);
175b5ac7c87Sflorian	if (scalar(@$flows_ref) > 0) {
176b5ac7c87Sflorian		say scalar(@$flows_ref),' flows';
177b5ac7c87Sflorian		foreach $flow_ref (@$flows_ref) {
178b5ac7c87Sflorian			say scalar(keys %$flow_ref) - 1, ' elements';
179b5ac7c87Sflorian			say 'SetId: ', $flow_ref->{'SetId'};
180b5ac7c87Sflorian			my ($iif, $eif, $start, $end);
181b5ac7c87Sflorian
182b3e4b791Sbluhm			my $qpack = $Config{longsize} == 8 ? 'Q>' :
183b3e4b791Sbluhm			    $Config{byteorder} == 1234 ? 'L>xxxx' : 'xxxxL>';
184b3e4b791Sbluhm
185b5ac7c87Sflorian			foreach $name (@elem_names) {
186b5ac7c87Sflorian				if ($name eq 'ingressInterface') {
187b5ac7c87Sflorian					$iif = unpack('N',
188b5ac7c87Sflorian					    $flow_ref->{name2id($name)});
189b5ac7c87Sflorian				} elsif ($name eq 'egressInterface') {
190b5ac7c87Sflorian					$eif = unpack('N',
191b5ac7c87Sflorian					    $flow_ref->{name2id($name)});
192b5ac7c87Sflorian				} elsif ($name eq 'flowStartSysUpTime') {
193b5ac7c87Sflorian					$start = unpack('N',
194b5ac7c87Sflorian					    $flow_ref->{name2id($name)})/1000;
195b5ac7c87Sflorian				} elsif ($name eq 'flowEndSysUpTime') {
196b5ac7c87Sflorian					$end = unpack('N',
197b5ac7c87Sflorian					    $flow_ref->{name2id($name)})/1000;
198b5ac7c87Sflorian				} elsif ($name eq 'flowStartSeconds') {
199b5ac7c87Sflorian					$start = unpack('N',
200b5ac7c87Sflorian					    $flow_ref->{name2id($name)});
201b5ac7c87Sflorian				} elsif ($name eq 'flowEndSeconds') {
202b5ac7c87Sflorian					$end = unpack('N',
203b5ac7c87Sflorian					    $flow_ref->{name2id($name)});
204b5ac7c87Sflorian				} elsif ($name eq 'flowStartMilliseconds') {
205b3e4b791Sbluhm					$start = unpack($qpack,
206b5ac7c87Sflorian					    $flow_ref->{name2id($name)})/1000;
207b5ac7c87Sflorian				} elsif ($name eq 'flowEndMilliseconds') {
208b3e4b791Sbluhm					$end = unpack($qpack,
209b5ac7c87Sflorian					    $flow_ref->{name2id($name)})/1000;
210b5ac7c87Sflorian				} else {
211b5ac7c87Sflorian					say $name,': ', unpack('H*',
212b5ac7c87Sflorian					    $flow_ref->{name2id($name)});
213b5ac7c87Sflorian				}
214b5ac7c87Sflorian			}
21520d0d40fSflorian
216b5ac7c87Sflorian			say 'ingressInterface == egressInterface && '.
217b5ac7c87Sflorian			    'egressInterface > 0: ', ($iif == $eif && $eif > 0);
218b5ac7c87Sflorian		}
219b5ac7c87Sflorian		last;
220b5ac7c87Sflorian	}
221b5ac7c87Sflorian}
222b3e4b791Sbluhm
223b3e4b791SbluhmEND {
224b5ac7c87Sflorian	system('ifconfig', 'pflow0', 'destroy');
225b3e4b791Sbluhm	system('ifconfig', 'lo0', 'inet', '10.11.12.13', 'delete');
226b3e4b791Sbluhm	system('ifconfig', 'lo0', 'inet6', '2001:db8::13', 'delete');
227b3e4b791Sbluhm}
228