File Coverage

blib/lib/Metabrik/Network/Stream.pm
Criterion Covered Total %
statement 9 154 5.8
branch 0 96 0.0
condition 0 53 0.0
subroutine 3 12 25.0
pod 2 9 22.2
total 14 324 4.3


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # network::stream Brik
5             #
6             package Metabrik::Network::Stream;
7 1     1   714 use strict;
  1         3  
  1         28  
8 1     1   5 use warnings;
  1         3  
  1         26  
9              
10 1     1   5 use base qw(Metabrik::Network::Read);
  1         3  
  1         1856  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             device => [ qw(device) ],
20             filter => [ qw(filter) ],
21             protocol => [ qw(udp|tcp) ],
22             },
23             attributes_default => {
24             filter => '',
25             protocol => 'tcp',
26             },
27             commands => {
28             from_pcap => [ qw(file filter|OPTIONAL) ],
29             to_pcap => [ qw(stream file) ],
30             list_source_ip_addresses => [ qw(stream) ],
31             list_destination_ip_addresses => [ qw(stream) ],
32             list_tcp_streams => [ qw($simple_frames_list) ],
33             save_stream_payload => [ qw($simple_frames_list) ],
34             get_payloads_from_pcap => [ qw(file filter|OPTIONAL) ],
35             },
36             require_modules => {
37             'Net::Frame::Layer::TCP' => [ ],
38             'Net::Frame::Simple' => [ ],
39             'Net::Frame::Dump::Writer' => [ ],
40             'Metabrik::File::Pcap' => [ ],
41             },
42             };
43             }
44              
45             sub brik_use_properties {
46 0     0 1   my $self = shift;
47              
48             return {
49 0   0       attributes_default => {
50             device => defined($self->global) && $self->global->device || 'eth0',
51             },
52             };
53             }
54              
55             sub from_pcap {
56 0     0 0   my $self = shift;
57 0           my ($file, $filter) = @_;
58              
59 0 0         $self->brik_help_run_undef_arg('from_pcap', $file) or return;
60 0 0         $self->brik_help_run_file_not_found('from_pcap', $file) or return;
61              
62 0   0       $filter ||= $self->filter;
63              
64 0 0         my $fp = Metabrik::File::Pcap->new_from_brik_init($self) or return;
65 0 0         $fp->open($file, 'read', $filter) or return;
66              
67 0           my $src_ip;
68             my $dst_ip;
69 0           my $src_port;
70 0           my $dst_port;
71 0           my @stream = ();
72 0           while (1) {
73 0           my $h = $fp->read_next(10); # We read 10 by 10
74 0 0         last if @$h == 0; # Eof
75 0           for my $this (@$h) {
76 0 0         my $simple = $fp->from_read($this) or next;
77 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6};
78 0           my $transport = $simple->ref->{TCP};
79              
80 0 0 0       if (defined($network) && defined($transport)) {
81 0           my $this_src_ip = $network->src;
82 0           my $this_dst_ip = $network->dst;
83 0           my $this_src_port = $transport->src;
84 0           my $this_dst_port = $transport->dst;
85             # We found a new stream
86             #if ($transport->flags == Net::Frame::Layer::TCP::NF_TCP_FLAGS_SYN()) {
87 0           $src_ip = $this_src_ip;
88 0           $dst_ip = $this_dst_ip;
89 0           $src_port = $this_src_port;
90 0           $dst_port = $this_dst_port;
91 0           $self->log->info("from_pcap: new stream [$src_ip:$src_port] [$dst_ip:$dst_port]");
92             #}
93              
94 0 0         next unless defined($src_ip); # We haven't found a stream yet
95              
96 0 0 0       if (($this_src_ip eq $src_ip || $this_src_ip eq $dst_ip)
      0        
      0        
97             && ($this_src_port eq $src_port || $this_src_port eq $dst_port)) {
98 0           push @stream, $simple;
99             }
100             }
101             }
102             }
103              
104 0           my @data = ();
105 0           for my $simple (@stream) {
106 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6};
107 0           my $transport = $simple->ref->{TCP};
108 0 0 0       if (defined($transport) && length($transport->payload) && defined($network)) {
      0        
109 0           $src_ip = $network->src;
110 0           $dst_ip = $network->dst;
111 0           $src_port = $transport->src;
112 0           $dst_port = $transport->dst;
113 0           my $payload = $transport->payload;
114 0           $self->log->verbose("payload: $src_ip:$src_port > $dst_ip:$dst_port: [".unpack('H*', $payload)."]");
115             }
116             }
117              
118 0           return \@stream;
119             }
120              
121             sub to_pcap {
122 0     0 0   my $self = shift;
123 0           my ($stream, $file) = @_;
124              
125 0 0         $self->brik_help_run_undef_arg('to_pcap', $file) or return;
126 0 0         $self->brik_help_run_undef_arg('to_pcap', $stream) or return;
127 0 0         $self->brik_help_run_invalid_arg('to_pcap', $stream, 'ARRAY') or return;
128 0 0         $self->brik_help_run_empty_array_arg('to_pcap', $stream) or return;
129              
130 0           my $first = $stream->[0];
131 0 0         if (ref($first) ne 'Net::Frame::Simple') {
132 0           return $self->log->error("to_pcap: stream must contains Net::Frame::Simple objects");
133             }
134              
135 0 0         my $fp = Metabrik::File::Pcap->new_from_brik_init($self) or return;
136 0 0         $fp->open($file, 'write', $first->firstLayer) or return;
137 0 0         my $frames = $fp->to_read($stream) or return;
138 0 0         $fp->write($frames) or return;
139 0           $fp->close;
140              
141 0           return 1;
142             }
143              
144             sub list_source_ip_addresses {
145 0     0 0   my $self = shift;
146 0           my ($stream) = @_;
147              
148 0 0         $self->brik_help_run_undef_arg('list_source_ip_addresses', $stream) or return;
149 0 0         $self->brik_help_run_invalid_arg('list_source_ip_addresses', $stream, 'ARRAY') or return;
150 0 0         $self->brik_help_run_empty_array_arg('list_source_ip_addresses', $stream) or return;
151              
152 0 0         if (ref($stream->[0]) ne 'Net::Frame::Simple') {
153 0           return $self->log->error("list_source_ip_addresses: stream must contains Net::Frame::Simple objects");
154             }
155              
156 0           my %src_ips = ();
157 0           for my $simple (@$stream) {
158 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6};
159 0 0         if (defined($network)) {
160 0           $src_ips{$network->src}++;
161             }
162             }
163              
164 0           return [ sort { $a cmp $b } keys %src_ips ];
  0            
165             }
166              
167             sub list_destination_ip_addresses {
168 0     0 0   my $self = shift;
169 0           my ($stream) = @_;
170              
171 0 0         $self->brik_help_run_undef_arg('list_destination_ip_addresses', $stream) or return;
172 0 0         $self->brik_help_run_invalid_arg('list_destination_ip_addresses', $stream, 'ARRAY') or return;
173 0 0         $self->brik_help_run_empty_array_arg('list_destination_ip_addresses', $stream) or return;
174              
175 0 0         if (ref($stream->[0]) ne 'Net::Frame::Simple') {
176 0           return $self->log->error("list_destination_ip_addresses: stream must contains Net::Frame::Simple objects");
177             }
178              
179 0           my %dst_ips = ();
180 0           for my $simple (@$stream) {
181 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6};
182 0 0         if (defined($network)) {
183 0           $dst_ips{$network->dst}++;
184             }
185             }
186              
187 0           return [ sort { $a cmp $b } keys %dst_ips ];
  0            
188             }
189              
190             sub list_tcp_streams {
191 0     0 0   my $self = shift;
192 0           my ($frames) = @_;
193              
194 0 0         $self->brik_help_run_undef_arg('list_tcp_streams', $frames) or return;
195 0 0         $self->brik_help_run_invalid_arg('list_tcp_streams', $frames, 'ARRAY') or return;
196 0 0         $self->brik_help_run_empty_array_arg('list_tcp_streams', $frames) or return;
197              
198 0 0         if (ref($frames->[0]) ne 'Net::Frame::Simple') {
199 0           return $self->log->error("list_tcp_streams: frames Argument must contain Net::Frame::Simple objects");
200             }
201              
202 0           my %streams = ();
203 0           for my $simple (@$frames) {
204 0   0       my $transport = $simple->ref->{TCP} || next;
205 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6} || next;
206              
207 0           my $src = $network->src;
208 0           my $dst = $network->dst;
209 0           my $src_port = $transport->src;
210 0           my $dst_port = $transport->dst;
211              
212 0           my $id1 = "$src:$src_port-$dst:$dst_port"; # Try one way of dialog
213 0           my $id2 = "$dst:$dst_port-$src:$src_port"; # Or the other
214 0 0         if (exists($streams{$id1})) {
215 0           push @{$streams{$id1}}, $simple;
  0            
216             }
217             else {
218 0           push @{$streams{$id2}}, $simple;
  0            
219             }
220             }
221              
222 0           return \%streams;
223             }
224              
225             sub save_stream_payload {
226 0     0 0   my $self = shift;
227 0           my ($frames) = @_;
228              
229 0 0         $self->brik_help_run_undef_arg('save_stream_payload', $frames) or return;
230 0 0         $self->brik_help_run_invalid_arg('save_stream_payload', $frames, 'ARRAY') or return;
231 0 0         $self->brik_help_run_empty_array_arg('save_stream_payload', $frames) or return;
232              
233 0 0         if (ref($frames->[0]) ne 'Net::Frame::Simple') {
234 0           return $self->log->error("save_stream_payload: frames Argument must contain Net::Frame::Simple objects");
235             }
236              
237 0           my $data = '';
238 0           for my $simple (@$frames) {
239 0   0       my $transport = $simple->ref->{TCP} || $simple->ref->{UDP} || next;
240 0 0         my $payload = $transport->payload or next;
241 0 0         if (length($payload)) {
242 0           $data .= $payload;
243             }
244             }
245              
246 0           return $data;
247             }
248              
249             sub get_payloads_from_pcap {
250 0     0 0   my $self = shift;
251 0           my ($file, $filter) = @_;
252              
253 0 0         $self->brik_help_run_undef_arg('get_payloads_from_pcap', $file) or return;
254 0 0         $self->brik_help_run_file_not_found('get_payloads_from_pcap', $file) or return;
255              
256 0   0       $filter ||= $self->filter;
257              
258 0 0         my $fp = Metabrik::File::Pcap->new_from_brik_init($self) or return;
259 0 0         $fp->open($file, 'read', $filter) or return;
260              
261 0           my @payloads = ();
262 0           while (1) {
263 0           my $h = $fp->read_next(10); # We read 10 by 10
264 0 0         last if @$h == 0; # Eof
265 0           for my $this (@$h) {
266 0 0         my $simple = $fp->from_read($this) or next;
267 0   0       my $network = $simple->ref->{IPv4} || $simple->ref->{IPv6};
268 0           my $transport = $simple->ref->{TCP};
269              
270 0 0 0       if (defined($network) && defined($transport)) {
271 0 0 0       if (defined($transport) && length($transport->payload)) {
272 0           push @payloads, CORE::unpack('H*', $transport->payload);
273             }
274             }
275             }
276             }
277              
278 0           return \@payloads;
279             }
280              
281             1;
282              
283             __END__