line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package FusionInventory::Agent::Task::Deploy::P2P; |
2
|
|
|
|
|
|
|
|
3
|
10
|
|
|
10
|
|
30535768
|
use strict; |
|
10
|
|
|
|
|
14
|
|
|
10
|
|
|
|
|
256
|
|
4
|
10
|
|
|
10
|
|
34
|
use warnings; |
|
10
|
|
|
|
|
15
|
|
|
10
|
|
|
|
|
294
|
|
5
|
|
|
|
|
|
|
|
6
|
10
|
|
|
10
|
|
34
|
use English qw(-no_match_vars); |
|
10
|
|
|
|
|
37
|
|
|
10
|
|
|
|
|
69
|
|
7
|
10
|
|
|
10
|
|
8919
|
use Net::IP; |
|
10
|
|
|
|
|
296975
|
|
|
10
|
|
|
|
|
1266
|
|
8
|
10
|
|
|
10
|
|
5678
|
use Net::Ping; |
|
10
|
|
|
|
|
66656
|
|
|
10
|
|
|
|
|
486
|
|
9
|
10
|
|
|
10
|
|
4360
|
use Parallel::ForkManager; |
|
10
|
|
|
|
|
102611
|
|
|
10
|
|
|
|
|
115
|
|
10
|
|
|
|
|
|
|
|
11
|
10
|
|
|
10
|
|
227
|
use UNIVERSAL::require; |
|
10
|
|
|
|
|
11
|
|
|
10
|
|
|
|
|
59
|
|
12
|
|
|
|
|
|
|
|
13
|
10
|
|
|
10
|
|
624
|
use FusionInventory::Agent::Logger; |
|
10
|
|
|
|
|
11
|
|
|
10
|
|
|
|
|
9018
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub new { |
16
|
9
|
|
|
9
|
0
|
54
|
my ($class, %params) = @_; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my $self = { |
19
|
|
|
|
|
|
|
logger => $params{logger} || |
20
|
|
|
|
|
|
|
FusionInventory::Agent::Logger->new(), |
21
|
|
|
|
|
|
|
max_workers => $params{max_workers} || 10, |
22
|
|
|
|
|
|
|
cache_timeout => $params{cache_timeout} || 600, |
23
|
|
|
|
|
|
|
scan_timeout => $params{scan_timeout} || 5, |
24
|
|
|
|
|
|
|
max_peers => $params{max_peers} || 512, |
25
|
9
|
|
33
|
|
|
153
|
max_size => $params{max_size} || 5000, |
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
26
|
|
|
|
|
|
|
cache_time => 0, |
27
|
|
|
|
|
|
|
cache => [] |
28
|
|
|
|
|
|
|
}; |
29
|
|
|
|
|
|
|
|
30
|
9
|
|
|
|
|
18
|
bless $self, $class; |
31
|
|
|
|
|
|
|
|
32
|
9
|
|
|
|
|
18
|
return $self; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub findPeers { |
36
|
0
|
|
|
0
|
0
|
0
|
my ($self, $port) = @_; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# $self->{logger}->debug("cachedate: ".$cache{date}); |
39
|
0
|
|
|
|
|
0
|
$self->{logger}->info("looking for a peer in the network"); |
40
|
0
|
|
|
|
|
0
|
return @{$self->{cache}} |
41
|
0
|
0
|
|
|
|
0
|
if time - $self->{cache_time} < $self->{cache_timeout}; |
42
|
|
|
|
|
|
|
|
43
|
0
|
|
|
|
|
0
|
my @interfaces; |
44
|
|
|
|
|
|
|
|
45
|
0
|
0
|
|
|
|
0
|
if ($OSNAME eq 'linux') { |
|
|
0
|
|
|
|
|
|
46
|
0
|
|
|
|
|
0
|
FusionInventory::Agent::Tools::Linux->require(); |
47
|
0
|
|
|
|
|
0
|
@interfaces = FusionInventory::Agent::Tools::Linux::getInterfacesFromIfconfig(); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
} elsif ($OSNAME eq 'MSWin32') { |
50
|
0
|
|
|
|
|
0
|
FusionInventory::Agent::Tools::Win32->require(); |
51
|
0
|
|
|
|
|
0
|
@interfaces = FusionInventory::Agent::Tools::Win32::getInterfaces(); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
0
|
0
|
|
|
|
0
|
if (!@interfaces) { |
55
|
0
|
|
|
|
|
0
|
$self->{logger}->info("No network interfaces found"); |
56
|
0
|
|
|
|
|
0
|
return; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
0
|
my @addresses; |
60
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
0
|
foreach my $interface (@interfaces) { |
62
|
|
|
|
|
|
|
#if interface has both ip and netmask setup then push the address |
63
|
0
|
0
|
|
|
|
0
|
next unless $interface->{IPADDRESS}; |
64
|
0
|
0
|
|
|
|
0
|
next unless $interface->{IPMASK}; |
65
|
0
|
0
|
|
|
|
0
|
next unless lc($interface->{STATUS}) eq 'up'; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
push @addresses, { |
68
|
|
|
|
|
|
|
ip => $interface->{IPADDRESS}, |
69
|
|
|
|
|
|
|
mask => $interface->{IPMASK} |
70
|
0
|
|
|
|
|
0
|
}; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
0
|
0
|
|
|
|
0
|
if (!@addresses) { |
74
|
0
|
|
|
|
|
0
|
$self->{logger}->info("No local address found"); |
75
|
0
|
|
|
|
|
0
|
return; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
0
|
my @potential_peers; |
79
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
0
|
foreach my $address (@addresses) { |
81
|
0
|
|
|
|
|
0
|
push @potential_peers, $self->_getPotentialPeers($address); |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
0
|
0
|
|
|
|
0
|
if (!@potential_peers) { |
85
|
0
|
|
|
|
|
0
|
$self->{logger}->info("No neighbour address found"); |
86
|
0
|
|
|
|
|
0
|
return; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
0
|
$self->{cache_time} = time; |
90
|
0
|
|
|
|
|
0
|
$self->{cache} = [ $self->_scanPeers($port, @potential_peers) ]; |
91
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
0
|
return @{$self->{cache}}; |
|
0
|
|
|
|
|
0
|
|
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub _getPotentialPeers { |
96
|
72
|
|
|
72
|
|
115443
|
my ($self, $address, $limit) = @_; |
97
|
|
|
|
|
|
|
|
98
|
72
|
50
|
|
|
|
171
|
$limit = $self->{max_peers} unless defined $limit; |
99
|
|
|
|
|
|
|
|
100
|
72
|
|
|
|
|
243
|
my @ip_bytes = split(/\./, $address->{ip}); |
101
|
72
|
|
|
|
|
198
|
my @mask_bytes = split(/\./, $address->{mask}); |
102
|
72
|
100
|
|
|
|
216
|
return if $ip_bytes[0] == 127; # Ignore 127.x.x.x addresses |
103
|
63
|
50
|
|
|
|
144
|
return if $ip_bytes[0] == 169; # Ignore 169.x.x.x range too |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# compute range |
106
|
63
|
|
|
|
|
72
|
my @start; |
107
|
|
|
|
|
|
|
my @end; |
108
|
|
|
|
|
|
|
|
109
|
63
|
|
|
|
|
144
|
foreach my $idx (0..3) { |
110
|
|
|
|
|
|
|
## no critic (ProhibitBitwise) |
111
|
252
|
|
|
|
|
315
|
push @start, $ip_bytes[$idx] & (255 & $mask_bytes[$idx]); |
112
|
252
|
|
|
|
|
261
|
push @end, $ip_bytes[$idx] | (255 - $mask_bytes[$idx]); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
63
|
|
|
|
|
198
|
my $ipStart = join('.', @start); |
116
|
63
|
|
|
|
|
135
|
my $ipEnd = join('.', @end); |
117
|
63
|
50
|
|
|
|
117
|
return if $ipStart eq $ipEnd; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Get ip interval before this interface ip |
120
|
|
|
|
|
|
|
my $ipIntervalBefore = Net::IP->new($ipStart.' - '.$address->{ip}) |
121
|
63
|
50
|
|
|
|
252
|
or die Net::IP::Error(); |
122
|
|
|
|
|
|
|
# Get ip interval after this interface ip |
123
|
63
|
50
|
|
|
|
112770
|
my $ipIntervalAfter = Net::IP->new($address->{ip}.' - '.$ipEnd) |
124
|
|
|
|
|
|
|
or die Net::IP::Error(); |
125
|
|
|
|
|
|
|
|
126
|
63
|
|
|
|
|
95742
|
my $beforeCount = int($limit/2); |
127
|
63
|
|
|
|
|
63
|
my $afterCount = $beforeCount ; |
128
|
|
|
|
|
|
|
|
129
|
63
|
|
|
|
|
162
|
my $size = $ipIntervalBefore->size() + $ipIntervalAfter->size() - 1 ; |
130
|
63
|
100
|
|
|
|
605070
|
if ($size > $self->{max_size}) { |
131
|
|
|
|
|
|
|
$self->{logger}->debug( |
132
|
9
|
|
|
|
|
567
|
"Range too large: $size (max $self->{max_size})" |
133
|
|
|
|
|
|
|
); |
134
|
9
|
|
|
|
|
117
|
return; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Handle the case ip range is bigger than expected |
138
|
54
|
50
|
|
|
|
2880
|
if ($ipIntervalBefore->size() + $ipIntervalAfter->size() > $limit) { |
139
|
|
|
|
|
|
|
$self->{logger}->debug( |
140
|
54
|
|
|
|
|
19125
|
"Have to limit ip range between ".$ipStart." and ".$ipEnd |
141
|
|
|
|
|
|
|
); |
142
|
|
|
|
|
|
|
# Update counts in the case we are too close from a range limit |
143
|
54
|
100
|
|
|
|
117
|
if ( $ipIntervalBefore->size() - 1 < $beforeCount ) { |
|
|
100
|
|
|
|
|
|
144
|
9
|
|
|
|
|
2421
|
$beforeCount = $ipIntervalBefore->size() ; |
145
|
9
|
|
|
|
|
1224
|
$afterCount = $limit - $beforeCount + 1; |
146
|
|
|
|
|
|
|
} elsif ( $ipIntervalAfter->size() < $afterCount ) { |
147
|
9
|
|
|
|
|
4023
|
$afterCount = $ipIntervalAfter->size(); |
148
|
9
|
|
|
|
|
1206
|
$beforeCount = $limit - $afterCount + 1 ; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
# Forget too far before ips |
151
|
54
|
100
|
66
|
|
|
19242
|
if (defined($ipIntervalBefore) && $ipIntervalBefore->size() > $beforeCount+1) { |
152
|
45
|
|
|
|
|
8712
|
$ipIntervalBefore += $ipIntervalBefore->size() - $beforeCount - 1 ; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
} |
155
|
54
|
|
|
|
|
73440
|
$ipStart = $ipIntervalBefore->ip(); |
156
|
54
|
|
|
|
|
261
|
$beforeCount = $ipIntervalBefore->size() - 1; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Now add ips before |
159
|
54
|
|
|
|
|
220833
|
my @peers; |
160
|
54
|
|
66
|
|
|
279
|
while (defined($ipIntervalBefore) && $beforeCount-->0) { |
161
|
171
|
|
|
|
|
432441
|
push @peers, $ipIntervalBefore->ip() ; |
162
|
171
|
|
|
|
|
711
|
++$ipIntervalBefore ; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# Then add ips after |
166
|
54
|
|
100
|
|
|
289368
|
while (defined(++$ipIntervalAfter) and $afterCount-->0) { |
167
|
153
|
|
|
|
|
704007
|
$ipEnd = $ipIntervalAfter->ip() ; |
168
|
153
|
|
|
|
|
648
|
push @peers, $ipEnd ; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
54
|
|
|
|
|
330993
|
$self->{logger}->debug("Scanning from ".$ipStart." to ".$ipEnd); |
172
|
|
|
|
|
|
|
|
173
|
54
|
|
|
|
|
522
|
return @peers; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _scanPeers { |
177
|
14
|
|
|
14
|
|
9029602
|
my ($self, $port, @addresses) = @_; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
$self->{logger}->debug( |
180
|
14
|
|
|
|
|
329
|
"Scanning from $addresses[0] to $addresses[-1]" |
181
|
|
|
|
|
|
|
); |
182
|
|
|
|
|
|
|
|
183
|
14
|
|
|
|
|
569
|
_fisher_yates_shuffle(\@addresses); |
184
|
|
|
|
|
|
|
|
185
|
14
|
|
|
|
|
370
|
my $ping = Net::Ping->new('tcp', $self->{scan_timeout}); |
186
|
14
|
|
|
|
|
4563
|
$ping->{port_num} = $port; |
187
|
14
|
|
|
|
|
142
|
$ping->service_check(1); |
188
|
|
|
|
|
|
|
|
189
|
14
|
|
|
|
|
56
|
my @found; |
190
|
|
|
|
|
|
|
|
191
|
14
|
|
|
|
|
273
|
my $manager = Parallel::ForkManager->new($self->{max_workers}); |
192
|
|
|
|
|
|
|
$manager->run_on_finish(sub { |
193
|
24
|
|
|
24
|
|
6009040
|
my ($pid, $exit_code, $address) = @_; |
194
|
24
|
100
|
|
|
|
143
|
push @found, $address if $exit_code; |
195
|
14
|
|
|
|
|
7816
|
}); |
196
|
|
|
|
|
|
|
|
197
|
14
|
|
|
|
|
184
|
foreach my $address (@addresses) { |
198
|
44
|
100
|
|
|
|
25534
|
$manager->start($address) and next; |
199
|
8
|
100
|
|
|
|
26242
|
$manager->finish($ping->ping($address) ? 1 : 0); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
6
|
|
|
|
|
4155
|
$manager->wait_all_children(); |
203
|
|
|
|
|
|
|
|
204
|
6
|
|
|
|
|
140
|
return @found; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub _fisher_yates_shuffle { |
208
|
14
|
|
|
14
|
|
59
|
my $deck = shift; # $deck is a reference to an array |
209
|
|
|
|
|
|
|
|
210
|
14
|
50
|
|
|
|
132
|
return unless @$deck; # must not be empty! |
211
|
|
|
|
|
|
|
|
212
|
14
|
|
|
|
|
73
|
my $i = @$deck; |
213
|
14
|
|
|
|
|
195
|
while (--$i) { |
214
|
42
|
|
|
|
|
115
|
my $j = int rand ($i+1); |
215
|
42
|
|
|
|
|
139
|
@$deck[$i,$j] = @$deck[$j,$i]; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
1; |