line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package BGPmon::Filter; |
2
|
1
|
|
|
1
|
|
39085
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
338
|
|
3
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
41
|
|
4
|
1
|
|
|
1
|
|
6
|
use constant FALSE => 0; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
92
|
|
5
|
1
|
|
|
1
|
|
6
|
use constant TRUE => 1; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
57
|
|
6
|
1
|
|
|
1
|
|
8931
|
use BGPmon::Translator::XFB2PerlHash::Simpler; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use BGPmon::Filter::Prefix; |
8
|
|
|
|
|
|
|
use BGPmon::Filter::Address; |
9
|
|
|
|
|
|
|
use BGPmon::CPM::PList::Manager; |
10
|
|
|
|
|
|
|
use Net::IP; |
11
|
|
|
|
|
|
|
use Regexp::IPv6 qw($IPv6_re); |
12
|
|
|
|
|
|
|
use List::MoreUtils qw(uniq); |
13
|
|
|
|
|
|
|
use Data::Dumper; |
14
|
|
|
|
|
|
|
use threads; |
15
|
|
|
|
|
|
|
use threads::shared; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
BEGIN{ |
18
|
|
|
|
|
|
|
require Exporter; |
19
|
|
|
|
|
|
|
our $VERSION = '2.00'; |
20
|
|
|
|
|
|
|
our $AUTOLOAD; |
21
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
22
|
|
|
|
|
|
|
our @EXPORT_OK = qw(init parse_xml_msg parse_config_file |
23
|
|
|
|
|
|
|
parse_database_config toString filterReset get_error_msg get_error_code |
24
|
|
|
|
|
|
|
matches printFilters get_num_IPv4_prefs get_num_IPv6_prefs |
25
|
|
|
|
|
|
|
get_num_ASes get_num_ip_addrs get_tot_num_filters); |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
my $progName = $0; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# Variables to hold error codes and messages |
33
|
|
|
|
|
|
|
my %error_code; |
34
|
|
|
|
|
|
|
my %error_msg; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
use constant NO_ERROR_CODE => 0; |
37
|
|
|
|
|
|
|
use constant NO_ERROR_MSG => 'No Error. Relax with some tea.'; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#Error codes for opening the configuration file. |
40
|
|
|
|
|
|
|
use constant UNOPANABLE_CONFIG_FILE => 520; |
41
|
|
|
|
|
|
|
use constant UNOPANABLE_CONFIG_FILE_MSG => 'Invalid filename given for config |
42
|
|
|
|
|
|
|
file.'; |
43
|
|
|
|
|
|
|
#Error codes for parsing the configuration file. |
44
|
|
|
|
|
|
|
use constant INVALID_IPV4_CONFIG => 530; |
45
|
|
|
|
|
|
|
use constant INVALID_IPV4_CONFIG_MSG => "Invalid IPv4 given in config file."; |
46
|
|
|
|
|
|
|
use constant INVALID_IPV6_CONFIG => 531; |
47
|
|
|
|
|
|
|
use constant INVALID_IPV6_CONFIG_MSG => "Invalid IPv6 given in config file."; |
48
|
|
|
|
|
|
|
use constant INVALID_AS_CONFIG => 532; |
49
|
|
|
|
|
|
|
use constant INVALID_AS_CONFIG_MSG => "Invalid AS given in config file."; |
50
|
|
|
|
|
|
|
use constant UNKNOWN_CONFIG => 533; |
51
|
|
|
|
|
|
|
use constant UNKNOWN_CONFIG_MSG => "Invalid line in config file."; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#Error codes for parsing the XML file. |
54
|
|
|
|
|
|
|
use constant NO_MSG_GIVEN => 540; |
55
|
|
|
|
|
|
|
use constant NO_MSG_GIVEN_MSG => "No XML message was given."; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
#Variable to handle locking |
58
|
|
|
|
|
|
|
my $lock = 1; |
59
|
|
|
|
|
|
|
share($lock); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Variables to hold the prefixes we'd like to filter |
64
|
|
|
|
|
|
|
my @v6prefixes = (); |
65
|
|
|
|
|
|
|
my @v4prefixes = (); |
66
|
|
|
|
|
|
|
my %v4prefHash = (); |
67
|
|
|
|
|
|
|
my $v4Count = 0; |
68
|
|
|
|
|
|
|
my %asNumbers = (); |
69
|
|
|
|
|
|
|
my @addresses = (); |
70
|
|
|
|
|
|
|
my $prefixFilename; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Variables to hold prefixes we've found in the latest message that was parsed. |
73
|
|
|
|
|
|
|
my @v4 = (); |
74
|
|
|
|
|
|
|
my @v6 = (); |
75
|
|
|
|
|
|
|
my @as = (); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head1 NAME |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
BGPmon::Filter |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
This module provides information of if a BGP message matches a set of |
83
|
|
|
|
|
|
|
IPv4 or IPv6 prefixes, or if it matches a specific autonymous system number. |
84
|
|
|
|
|
|
|
=cut |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head1 SYNOPSIS |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
use BGPmon::Filter; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
if(BGPmon::Filter::init()){ |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
my $err_code = BGPmon::Filter::get_error_code('init'); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my $err_msg = BGPmon::Filter::get_error_msg('init'); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
print "$err_code : $err_msg\n"; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
exit 1; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
if(BGPmon::Filter::parse_config_file('config_file.txt')){ |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
my $err_code = BGPmon::Filter::get_error_code('parse_config_file'); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
my $err_msg = BGPmon::Filter::get_error_msg('parse_config_file'); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
print "$err_code : $err_msg\n"; |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
exit 1; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
my $xml_msg = '... |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
if(BGPmon::Filter::matches($xml_msg)){ |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
print "Matches!\n"; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
else{ |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
print "Does not match.\n"; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head1 EXPORT |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
init parse_xml_msg parse_config_file toString filterReset |
127
|
|
|
|
|
|
|
get_error_msg get_error_code matches printFilters |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 init |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Will initilialize the module an its state variables. This only needs |
136
|
|
|
|
|
|
|
to be called once. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut |
139
|
|
|
|
|
|
|
sub init{ |
140
|
|
|
|
|
|
|
lock($lock); |
141
|
|
|
|
|
|
|
my $fname = 'init'; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
144
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
return 0; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head2 filterReset |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Resets the module's state values. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=cut |
155
|
|
|
|
|
|
|
sub filterReset{ |
156
|
|
|
|
|
|
|
lock($lock); |
157
|
|
|
|
|
|
|
my $fname = 'filterReset'; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
foreach(@v6prefixes){ |
160
|
|
|
|
|
|
|
$_ = undef; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
foreach(@v4prefixes){ |
163
|
|
|
|
|
|
|
$_ = undef; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
foreach(@addresses){ |
166
|
|
|
|
|
|
|
$_ = undef; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
foreach(@v4){ |
169
|
|
|
|
|
|
|
$_ = undef; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
foreach(@v6){ |
172
|
|
|
|
|
|
|
$_ = undef; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
foreach(@as){ |
175
|
|
|
|
|
|
|
$_ = undef; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
@v4prefixes = (); |
178
|
|
|
|
|
|
|
%v4prefHash = (); |
179
|
|
|
|
|
|
|
$v4Count = 0; |
180
|
|
|
|
|
|
|
@v6prefixes = (); |
181
|
|
|
|
|
|
|
%asNumbers = (); |
182
|
|
|
|
|
|
|
@addresses = (); |
183
|
|
|
|
|
|
|
@v4 = (); |
184
|
|
|
|
|
|
|
@v6 = (); |
185
|
|
|
|
|
|
|
@as = (); |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
$prefixFilename = undef; |
189
|
|
|
|
|
|
|
%error_code = (); |
190
|
|
|
|
|
|
|
%error_msg = (); |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
193
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
return 0; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head2 get_error_msg |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Will return the error message of the given function name. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Input: A string that contains the function name where an error occured. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Output: The message which represents the error stored from that function. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=cut |
207
|
|
|
|
|
|
|
sub get_error_msg{ |
208
|
|
|
|
|
|
|
lock($lock); |
209
|
|
|
|
|
|
|
my $str = shift; |
210
|
|
|
|
|
|
|
my $fname = 'get_error_msg'; |
211
|
|
|
|
|
|
|
my $toReturn = $error_msg{$str}; |
212
|
|
|
|
|
|
|
return $toReturn; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head2 get_error_code |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Will return the error code of the given function name. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Input: A string that represents the function name where an error occured. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Output: The code which represents the error stored from that function. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
224
|
|
|
|
|
|
|
sub get_error_code{ |
225
|
|
|
|
|
|
|
lock($lock); |
226
|
|
|
|
|
|
|
my $str = shift; |
227
|
|
|
|
|
|
|
my $fname = 'get_error_code'; |
228
|
|
|
|
|
|
|
my $toReturn = $error_code{$str}; |
229
|
|
|
|
|
|
|
return $toReturn; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
#comment |
233
|
|
|
|
|
|
|
#Will check to see if the string passed in is of proper IPv6 format. |
234
|
|
|
|
|
|
|
#cut |
235
|
|
|
|
|
|
|
sub is_IPv6{ |
236
|
|
|
|
|
|
|
my $str = shift; |
237
|
|
|
|
|
|
|
my $fname = 'is_IPv6'; |
238
|
|
|
|
|
|
|
if(!($str =~ /^$IPv6_re$/)){ |
239
|
|
|
|
|
|
|
return FALSE; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
return TRUE; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
my $prefix_rgx = "\\d+\\.\\d+\\.\\d+\\.\\d+\/\\d+"; |
248
|
|
|
|
|
|
|
my $ip_rgx = "\\d+\\.\\d+\\.\\d+\\.\\d+"; |
249
|
|
|
|
|
|
|
sub ipv4_chkip($) { |
250
|
|
|
|
|
|
|
#checking to see if it's a prefix or an IPv4 address |
251
|
|
|
|
|
|
|
my ($ip) = $_[0] =~ /($prefix_rgx)/o; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
#print "Is a prefix\n" if $ip; |
255
|
|
|
|
|
|
|
#print "Not a prefix\n" unless $ip; |
256
|
|
|
|
|
|
|
if($ip){#if a prefix |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
my @parts = split /\//, $ip; |
259
|
|
|
|
|
|
|
my $addr = $parts[0]; |
260
|
|
|
|
|
|
|
my $mask = $parts[1]; |
261
|
|
|
|
|
|
|
# Check that bytes are in range |
262
|
|
|
|
|
|
|
for (split /\./, $addr ) { |
263
|
|
|
|
|
|
|
return undef if $_ < 0 or $_ > 255; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
return undef if $mask < 0 or $mask > 32; |
266
|
|
|
|
|
|
|
return $ip; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
else{#if an address |
270
|
|
|
|
|
|
|
($ip) = $_[0] =~ /($ip_rgx)/o; |
271
|
|
|
|
|
|
|
#print "Is an IP address\n" if $ip; |
272
|
|
|
|
|
|
|
#print "Not an address\n" unless $ip; |
273
|
|
|
|
|
|
|
if($ip){ |
274
|
|
|
|
|
|
|
# Check that bytes are in range |
275
|
|
|
|
|
|
|
for (split /\./, $ip ) { |
276
|
|
|
|
|
|
|
return undef if $_ < 0 or $_ > 255; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
return $ip; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
return undef; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub addV4prefixToHash{ |
287
|
|
|
|
|
|
|
my $prefix = shift; |
288
|
|
|
|
|
|
|
my $prefObj = shift; |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
my @pieces = split('/',$prefix); |
291
|
|
|
|
|
|
|
my @ips = split /\./, $pieces[0]; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
#firstOct->{secondOct->{thirdOctet->{fourthOctet->{prefixObject |
295
|
|
|
|
|
|
|
if(!exists $v4prefHash{$ips[0]}) { |
296
|
|
|
|
|
|
|
$v4prefHash{$ips[0]} = {}; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
if(!exists $v4prefHash{$ips[0]}->{$ips[1]}){ |
299
|
|
|
|
|
|
|
$v4prefHash{$ips[0]}->{$ips[1]} = {}; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
if(!exists $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}){ |
302
|
|
|
|
|
|
|
$v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]} = {}; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
if(!exists $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]}){ |
305
|
|
|
|
|
|
|
$v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]} = []; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
push($v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]}, $prefObj); |
310
|
|
|
|
|
|
|
$v4Count += 1; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
sub getChildren{ |
315
|
|
|
|
|
|
|
my $hashRef = shift; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
my @toReturn = (); |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
foreach my $key(keys % $hashRef){ |
320
|
|
|
|
|
|
|
my $item = $hashRef->{$key}; |
321
|
|
|
|
|
|
|
#print "$item\n"; |
322
|
|
|
|
|
|
|
if(ref($item) eq 'HASH'){ #still going through the hashes |
323
|
|
|
|
|
|
|
push(@toReturn, @{getChildren($item)}); |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
elsif(ref($item) eq 'ARRAY'){ |
326
|
|
|
|
|
|
|
my @toAdd = @{$item}; |
327
|
|
|
|
|
|
|
#print Dumper @toAdd; |
328
|
|
|
|
|
|
|
push(@toReturn, @toAdd); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
return \@toReturn; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub getV4comparisons{ |
335
|
|
|
|
|
|
|
my $prefix = shift; |
336
|
|
|
|
|
|
|
my @pieces = split /\//, $prefix; |
337
|
|
|
|
|
|
|
my $ip = $pieces[0]; |
338
|
|
|
|
|
|
|
my @ips = split /\./, $ip; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
if(!exists $v4prefHash{$ips[0]}) { |
341
|
|
|
|
|
|
|
return getChildren(\%v4prefHash); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
elsif(!exists $v4prefHash{$ips[0]}->{$ips[1]}) { |
344
|
|
|
|
|
|
|
return getChildren($v4prefHash{$ips[0]}); |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
elsif(!exists $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}) { |
347
|
|
|
|
|
|
|
return getChildren($v4prefHash{$ips[0]}->{$ips[1]}); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
elsif(!exists $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]}) { |
350
|
|
|
|
|
|
|
return getChildren($v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}); |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
elsif(exists $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]}){ |
353
|
|
|
|
|
|
|
#returns the array of prefixes with these four octets |
354
|
|
|
|
|
|
|
my $toReturn = $v4prefHash{$ips[0]}->{$ips[1]}->{$ips[2]}->{$ips[3]}; |
355
|
|
|
|
|
|
|
return $toReturn; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
else{ |
358
|
|
|
|
|
|
|
#TODO make lookup error |
359
|
|
|
|
|
|
|
return undef; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=head2 parse_config_file |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
Will parse the wanted IPv4 and IPv6 prefixes from a configuration file as well |
369
|
|
|
|
|
|
|
as any autonymous system numbers. These will be stored until |
370
|
|
|
|
|
|
|
BGPmon::Filter::filterReset() is called. This will also aggregate addresses |
371
|
|
|
|
|
|
|
where possible and setup a mult-layer hash lookup system for faster retrieval |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Input: A string with the location of the configuration file to parse |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Output: 0 if there is no error |
376
|
|
|
|
|
|
|
1 if an error occured |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=cut |
380
|
|
|
|
|
|
|
sub parse_config_file{ |
381
|
|
|
|
|
|
|
lock($lock); |
382
|
|
|
|
|
|
|
$prefixFilename = shift; |
383
|
|
|
|
|
|
|
my $fname = 'parse_config_file'; |
384
|
|
|
|
|
|
|
my $file; |
385
|
|
|
|
|
|
|
my $lineNum = 0; |
386
|
|
|
|
|
|
|
if(!open($file, $prefixFilename)){ |
387
|
|
|
|
|
|
|
$error_code{$fname} = UNOPANABLE_CONFIG_FILE; |
388
|
|
|
|
|
|
|
$error_msg{$fname} = UNOPANABLE_CONFIG_FILE_MSG; |
389
|
|
|
|
|
|
|
return 1; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
while(my $line = <$file>){ |
393
|
|
|
|
|
|
|
$lineNum ++; |
394
|
|
|
|
|
|
|
chomp $line; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# Remove any trailing white space. |
397
|
|
|
|
|
|
|
$line =~ s/^s+//g; |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
# If the line starts with a #, skip it. |
400
|
|
|
|
|
|
|
next if ($line =~ /^s*#/); |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Skipping the line if it's blank |
403
|
|
|
|
|
|
|
next if ($line eq ""); |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
# Splitting the line up |
407
|
|
|
|
|
|
|
my @lineArray = split ' ', $line; |
408
|
|
|
|
|
|
|
my $lineLength = scalar(@lineArray); |
409
|
|
|
|
|
|
|
if($lineLength < 1){ |
410
|
|
|
|
|
|
|
$error_code{$fname} = UNKNOWN_CONFIG; |
411
|
|
|
|
|
|
|
$error_msg{$fname} = UNKNOWN_CONFIG_MSG; |
412
|
|
|
|
|
|
|
return 1; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
# if this line is an AS number |
417
|
|
|
|
|
|
|
if($lineArray[0] =~ /[aA][sS]/){ |
418
|
|
|
|
|
|
|
if($lineArray[1] > 0 and $lineArray[1] < 65536){ |
419
|
|
|
|
|
|
|
my $temp = $lineArray[1]; |
420
|
|
|
|
|
|
|
$asNumbers{$temp} = 1; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
else{ |
423
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_AS_CONFIG; |
424
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_AS_CONFIG_MSG; |
425
|
|
|
|
|
|
|
return 1; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
# if this line is an IPv4 number |
429
|
|
|
|
|
|
|
elsif($lineArray[0] =~ /[iI][pP][vV][4]/){ |
430
|
|
|
|
|
|
|
#Making sure whatever is next is either a valid prefix or IPv4 address |
431
|
|
|
|
|
|
|
my $ipcheck = ipv4_chkip($lineArray[1]); |
432
|
|
|
|
|
|
|
unless($ipcheck) { |
433
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV4_CONFIG; |
434
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV4_CONFIG_MSG.':'.$line; |
435
|
|
|
|
|
|
|
return 1; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
#Decerning if we have a prefix or IPv4 address |
438
|
|
|
|
|
|
|
if($ipcheck =~ /\//){ #prefix |
439
|
|
|
|
|
|
|
if(!exists($lineArray[2]) or !$lineArray[2] =~ m/[mMlL][sS]/){ |
440
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV4_CONFIG; |
441
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV4_CONFIG_MSG.':'.$line; |
442
|
|
|
|
|
|
|
return 1; |
443
|
|
|
|
|
|
|
#print "Skippnig $line\n"; |
444
|
|
|
|
|
|
|
#next; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
# Adding prefix to the list since it's okay |
447
|
|
|
|
|
|
|
my $moreSpecific = $lineArray[2] =~ m/[mM][sS]/; |
448
|
|
|
|
|
|
|
my $temp = new BGPmon::Filter::Prefix(4, $lineArray[1], $moreSpecific); |
449
|
|
|
|
|
|
|
push(@v4prefixes, $temp); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
else{#IPv4 address |
452
|
|
|
|
|
|
|
my $temp = new BGPmon::Filter::Address(4,$lineArray[1]); |
453
|
|
|
|
|
|
|
push(@addresses,$temp); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# if this line is an IPv6 number |
458
|
|
|
|
|
|
|
elsif($lineArray[0] =~ /[iI][pP][vV][6]/){ |
459
|
|
|
|
|
|
|
# Ensuring that it's a valid IPv6 number and prefix |
460
|
|
|
|
|
|
|
my @ipv6Addr = split(/\//, $lineArray[1]); |
461
|
|
|
|
|
|
|
my $address = $ipv6Addr[0]; |
462
|
|
|
|
|
|
|
my $prefix = $ipv6Addr[1]; |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# Making sure the IPv6 is valid - in any form. |
465
|
|
|
|
|
|
|
if(!is_IPv6($ipv6Addr[0])){ |
466
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV6_CONFIG; |
467
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV6_CONFIG_MSG; |
468
|
|
|
|
|
|
|
return 1; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# Making sure the prefix is valid |
472
|
|
|
|
|
|
|
if($prefix < 0 or $prefix > 128){ |
473
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV6_CONFIG; |
474
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV6_CONFIG_MSG; |
475
|
|
|
|
|
|
|
return 1; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# Adding prefix to the list |
479
|
|
|
|
|
|
|
if(!defined($lineArray[2])){ |
480
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV6_CONFIG; |
481
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV6_CONFIG_MSG; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
if(!$lineArray[2] =~ m/[mMlL][sS]/){ |
484
|
|
|
|
|
|
|
$error_code{$fname} = INVALID_IPV6_CONFIG; |
485
|
|
|
|
|
|
|
$error_msg{$fname} = INVALID_IPV6_CONFIG_MSG; |
486
|
|
|
|
|
|
|
return 1; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
my $moreSpecific = $lineArray[2] =~ m/[mM][sS]/; |
489
|
|
|
|
|
|
|
my $temp = new BGPmon::Filter::Prefix(6, $lineArray[1], $moreSpecific); |
490
|
|
|
|
|
|
|
push(@v6prefixes, $temp); |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# if we don't know what this line is |
494
|
|
|
|
|
|
|
else{ |
495
|
|
|
|
|
|
|
$error_code{$fname} = UNKNOWN_CONFIG; |
496
|
|
|
|
|
|
|
$error_msg{$fname} = UNKNOWN_CONFIG_MSG; |
497
|
|
|
|
|
|
|
return 1; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
#closing the file |
505
|
|
|
|
|
|
|
close($file); |
506
|
|
|
|
|
|
|
condense_prefs(); #aggregates where possible |
507
|
|
|
|
|
|
|
optimize_prefs(); #puts them in the multilayer hash for faster lookups |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
510
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
return 0; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub parse_database_config{ |
518
|
|
|
|
|
|
|
my $listName = shift; |
519
|
|
|
|
|
|
|
my $fname = 'parse_database_config'; |
520
|
|
|
|
|
|
|
lock($lock); |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
#getting a list of prefixes |
524
|
|
|
|
|
|
|
my @prefs = BGPmon::CPM::PList::Manager::export2CSV('',$listName); |
525
|
|
|
|
|
|
|
my $size = scalar(@prefs); |
526
|
|
|
|
|
|
|
if($size == 0){ |
527
|
|
|
|
|
|
|
#TODO create an error message that has the list size at zero |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
#resetting the module |
531
|
|
|
|
|
|
|
filterReset(); |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
#creating new prefixes |
534
|
|
|
|
|
|
|
foreach(@prefs){ |
535
|
|
|
|
|
|
|
my $newPref = $_->prefix(); |
536
|
|
|
|
|
|
|
my $moreSpec = $_->watch_more_specifics(); |
537
|
|
|
|
|
|
|
if(is_IPv6($newPref)){ |
538
|
|
|
|
|
|
|
my $temp = new BGPmon::Filter::Prefix(6, $newPref, $moreSpec); |
539
|
|
|
|
|
|
|
push(@v6prefixes, $temp); |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
else{ |
542
|
|
|
|
|
|
|
my $temp = new BGPmon::Filter::Prefix(4, $newPref, $moreSpec); |
543
|
|
|
|
|
|
|
push(@v4prefixes, $temp); |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
#optimizing |
549
|
|
|
|
|
|
|
condense_prefs(); #aggregates where possible |
550
|
|
|
|
|
|
|
optimize_prefs(); #puts them in the multilayer hash for faster lookups |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
553
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
return 0; |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
#puts the prefixes for IPv4 into a multi-layer hash lookup |
560
|
|
|
|
|
|
|
sub optimize_prefs{ |
561
|
|
|
|
|
|
|
foreach(@v4prefixes){ |
562
|
|
|
|
|
|
|
my $temp = $_; |
563
|
|
|
|
|
|
|
addV4prefixToHash($temp->prefix(), $temp); |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
#TODO put in error codes |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
return 0; |
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
=head2 get_num_IPv4_prefs |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
Will count the number of IPv4 prefixes it has parsed from the configuration |
574
|
|
|
|
|
|
|
file and return the integer |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
Input: None |
577
|
|
|
|
|
|
|
Output : Integer |
578
|
|
|
|
|
|
|
=cut |
579
|
|
|
|
|
|
|
sub get_num_IPv4_prefs{ |
580
|
|
|
|
|
|
|
my $toReturn = scalar(@v4prefixes); |
581
|
|
|
|
|
|
|
return $toReturn; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
=head2 get_num_IPv6_prefs |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
Will count the number of IPv6 prefixes it has parsed from the configuration |
587
|
|
|
|
|
|
|
file and return the integer |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
Input: None |
590
|
|
|
|
|
|
|
Output : Integer |
591
|
|
|
|
|
|
|
=cut |
592
|
|
|
|
|
|
|
sub get_num_IPv6_prefs{ |
593
|
|
|
|
|
|
|
my $toReturn = scalar(@v6prefixes); |
594
|
|
|
|
|
|
|
return $toReturn; |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=head2 get_num_ASes |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Will count the number of ASes it has parsed from the configuration |
601
|
|
|
|
|
|
|
file and return the integer |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
Input: None |
604
|
|
|
|
|
|
|
Output : Integer |
605
|
|
|
|
|
|
|
=cut |
606
|
|
|
|
|
|
|
sub get_num_ASes{ |
607
|
|
|
|
|
|
|
my $toReturn = scalar(keys %asNumbers); |
608
|
|
|
|
|
|
|
return $toReturn; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=head2 get_num_ip_addrs |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Will count the number of IPv4 addresses it has parsed from the configuration |
616
|
|
|
|
|
|
|
file and return the integer |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
Input: None |
619
|
|
|
|
|
|
|
Output : Integer |
620
|
|
|
|
|
|
|
=cut |
621
|
|
|
|
|
|
|
sub get_num_ip_addrs{ |
622
|
|
|
|
|
|
|
my $toReturn = scalar(@addresses); |
623
|
|
|
|
|
|
|
return $toReturn; |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=head2 get_total_num_filters |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
Will tally all filters the module will look for per message and return |
629
|
|
|
|
|
|
|
the interger |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Input: None |
632
|
|
|
|
|
|
|
Output : Integer |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=cut |
635
|
|
|
|
|
|
|
sub get_total_num_filters{ |
636
|
|
|
|
|
|
|
lock($lock); |
637
|
|
|
|
|
|
|
my $toReturn = 0; |
638
|
|
|
|
|
|
|
$toReturn += scalar(@v4prefixes); |
639
|
|
|
|
|
|
|
$toReturn += scalar(@v6prefixes); |
640
|
|
|
|
|
|
|
$toReturn += scalar(%asNumbers); |
641
|
|
|
|
|
|
|
$toReturn += scalar(@addresses); |
642
|
|
|
|
|
|
|
return $toReturn; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
#condense__prefs |
647
|
|
|
|
|
|
|
# |
648
|
|
|
|
|
|
|
#Will try to aggregate IPv4 and IPv6 prefixes where possible. This is used to reduce |
649
|
|
|
|
|
|
|
#overhead that the filter script may experience later. Please note that the |
650
|
|
|
|
|
|
|
#parse_config_file must be ran beforehand. |
651
|
|
|
|
|
|
|
# |
652
|
|
|
|
|
|
|
#Input: None |
653
|
|
|
|
|
|
|
# |
654
|
|
|
|
|
|
|
#Output: 0 if there is no error |
655
|
|
|
|
|
|
|
# 1 if an error occured |
656
|
|
|
|
|
|
|
# |
657
|
|
|
|
|
|
|
# |
658
|
|
|
|
|
|
|
sub condense_prefs{ |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
##Starting with IPv4 |
661
|
|
|
|
|
|
|
#Will continuously agg. addresses where it can until none are left |
662
|
|
|
|
|
|
|
my $found = TRUE; |
663
|
|
|
|
|
|
|
while($found){ |
664
|
|
|
|
|
|
|
$found = FALSE; |
665
|
|
|
|
|
|
|
for( my $i = 0; $i < scalar(@v4prefixes); $i++){ |
666
|
|
|
|
|
|
|
my $currPref = $v4prefixes[$i]; |
667
|
|
|
|
|
|
|
for(my $k = $i+1; $k < scalar(@v4prefixes); $k++){ |
668
|
|
|
|
|
|
|
my $thisPref = $v4prefixes[$k]; |
669
|
|
|
|
|
|
|
next if not $currPref->matchSpecific($thisPref); |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
if($currPref->canAggregateWith($thisPref)){ |
672
|
|
|
|
|
|
|
my $newPref = $currPref->getAggregate($thisPref); |
673
|
|
|
|
|
|
|
splice @v4prefixes, $k, 1; |
674
|
|
|
|
|
|
|
splice @v4prefixes, $i, 1; |
675
|
|
|
|
|
|
|
my $np = new BGPmon::Filter::Prefix(4, |
676
|
|
|
|
|
|
|
$newPref, $currPref->{moreSpecific}); |
677
|
|
|
|
|
|
|
push(@v4prefixes, $np); |
678
|
|
|
|
|
|
|
$found = TRUE; |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
} |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
} |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
##Starting with IPv6 |
685
|
|
|
|
|
|
|
#Will continuously agg. addresses where it can until none are left |
686
|
|
|
|
|
|
|
$found = TRUE; |
687
|
|
|
|
|
|
|
while($found){ |
688
|
|
|
|
|
|
|
$found = FALSE; |
689
|
|
|
|
|
|
|
for( my $i = 0; $i < scalar(@v6prefixes); $i++){ |
690
|
|
|
|
|
|
|
my $currPref = $v6prefixes[$i]; |
691
|
|
|
|
|
|
|
for(my $k = $i+1; $k < scalar(@v6prefixes); $k++){ |
692
|
|
|
|
|
|
|
my $thisPref = $v6prefixes[$k]; |
693
|
|
|
|
|
|
|
next if not $currPref->matchSpecific($thisPref); |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
if($currPref->canAggregateWith($thisPref)){ |
696
|
|
|
|
|
|
|
my $newPref = $currPref->getAggregate($thisPref); |
697
|
|
|
|
|
|
|
splice @v6prefixes, $k, 1; |
698
|
|
|
|
|
|
|
splice @v6prefixes, $i, 1; |
699
|
|
|
|
|
|
|
my $np = new BGPmon::Filter::Prefix(6, |
700
|
|
|
|
|
|
|
$newPref, $currPref->{moreSpecific}); |
701
|
|
|
|
|
|
|
push(@v6prefixes, $np); |
702
|
|
|
|
|
|
|
$found = TRUE; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
return 0; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
=head2 printFilters |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
Will print to standard output the filters currently set for the module. |
716
|
|
|
|
|
|
|
For example, if your prefix file looked like |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
#IPv4 |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
ipv4 192.168.1.0/24 ls |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
#IPv6 |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
ipv6 ::0/32 ms |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
#AS |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
as 1 |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
This will print |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
ipv4 192.168.1.0/24 ls |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
ipv6 ::0/32 ms |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
as 1 |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
=cut |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
sub printFilters{ |
741
|
|
|
|
|
|
|
lock($lock); |
742
|
|
|
|
|
|
|
foreach(@v4prefixes){ |
743
|
|
|
|
|
|
|
my $temp = $_->toString(); |
744
|
|
|
|
|
|
|
print "$temp\n"; |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
foreach(@v6prefixes){ |
747
|
|
|
|
|
|
|
my $temp = $_->toString(); |
748
|
|
|
|
|
|
|
print "$temp\n"; |
749
|
|
|
|
|
|
|
} |
750
|
|
|
|
|
|
|
foreach(keys %asNumbers){ |
751
|
|
|
|
|
|
|
print "$_\n"; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
foreach(@addresses){ |
754
|
|
|
|
|
|
|
my $temp = $_->toString(); |
755
|
|
|
|
|
|
|
print "$temp\n"; |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
=head2 toString |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
Will return a string that prints the most recently filtered prefixes and |
764
|
|
|
|
|
|
|
autonymous system numbers in human-readable format. |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
E.g., |
767
|
|
|
|
|
|
|
IPv4 prefixes pulled from the message: |
768
|
|
|
|
|
|
|
192.168.1.0/24 |
769
|
|
|
|
|
|
|
IPv6 prefixes pulled from the message: |
770
|
|
|
|
|
|
|
(none) |
771
|
|
|
|
|
|
|
AS numbers pulled from the message: |
772
|
|
|
|
|
|
|
12345 |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
=cut |
775
|
|
|
|
|
|
|
sub toString{ |
776
|
|
|
|
|
|
|
lock($lock); |
777
|
|
|
|
|
|
|
my $fname = 'toString'; |
778
|
|
|
|
|
|
|
my $toReturn = ""; |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
#Adding v4's |
781
|
|
|
|
|
|
|
$toReturn .= "IPv4 prefixes pulled from the message:\n"; |
782
|
|
|
|
|
|
|
if(scalar @v4 == 0){ |
783
|
|
|
|
|
|
|
$toReturn .= "(none)\n"; |
784
|
|
|
|
|
|
|
} |
785
|
|
|
|
|
|
|
else{ |
786
|
|
|
|
|
|
|
foreach(@v4){ |
787
|
|
|
|
|
|
|
$toReturn .= "$_\n"; |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
} |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
#Adding v6's |
792
|
|
|
|
|
|
|
# |
793
|
|
|
|
|
|
|
$toReturn .= "IPv6 prefixes pulled from the message:\n"; |
794
|
|
|
|
|
|
|
if(scalar @v6 == 0){ |
795
|
|
|
|
|
|
|
$toReturn .= "(none)\n"; |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
else{ |
798
|
|
|
|
|
|
|
foreach(@v6){ |
799
|
|
|
|
|
|
|
$toReturn .= "$_\n"; |
800
|
|
|
|
|
|
|
} |
801
|
|
|
|
|
|
|
} |
802
|
|
|
|
|
|
|
#Adding AS's |
803
|
|
|
|
|
|
|
# |
804
|
|
|
|
|
|
|
$toReturn .= "AS numbers pulled from the message:\n"; |
805
|
|
|
|
|
|
|
if(scalar @as == 0){ |
806
|
|
|
|
|
|
|
$toReturn .= "(none)\n"; |
807
|
|
|
|
|
|
|
} |
808
|
|
|
|
|
|
|
else{ |
809
|
|
|
|
|
|
|
foreach(@as){ |
810
|
|
|
|
|
|
|
$toReturn .= "$_\n"; |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
return $toReturn; |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
#comment |
819
|
|
|
|
|
|
|
# |
820
|
|
|
|
|
|
|
#Will reset the most recently filtered prefixes and AS numbers, parse the |
821
|
|
|
|
|
|
|
#message that was sent to it, and store a unique set of prefixes and |
822
|
|
|
|
|
|
|
#AS numbers. |
823
|
|
|
|
|
|
|
# |
824
|
|
|
|
|
|
|
#cut |
825
|
|
|
|
|
|
|
sub parse_xml_msg{ |
826
|
|
|
|
|
|
|
lock($lock); |
827
|
|
|
|
|
|
|
my $fname = 'parse_xml_msg'; |
828
|
|
|
|
|
|
|
my $xmlMsg = shift; |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
if(!defined($xmlMsg)){ |
831
|
|
|
|
|
|
|
$error_code{$fname} = NO_MSG_GIVEN; |
832
|
|
|
|
|
|
|
$error_msg{$fname} = NO_MSG_GIVEN_MSG; |
833
|
|
|
|
|
|
|
return undef; |
834
|
|
|
|
|
|
|
} |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
# A list of all the prefixes and AS's found during searching. |
837
|
|
|
|
|
|
|
my @v4s = (); |
838
|
|
|
|
|
|
|
my @v6s = (); |
839
|
|
|
|
|
|
|
my @ases = (); |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
# The translation of the message |
842
|
|
|
|
|
|
|
my $parseRes = BGPmon::Translator::XFB2PerlHash::Simpler::parse_xml_msg($xmlMsg); |
843
|
|
|
|
|
|
|
if($parseRes){ |
844
|
|
|
|
|
|
|
#TODO return new value saying we couldn't parse the message. |
845
|
|
|
|
|
|
|
return 1; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
#Checking the withdrawn part of the message |
849
|
|
|
|
|
|
|
my @withs = BGPmon::Translator::XFB2PerlHash::Simpler::extract_withdraw(); |
850
|
|
|
|
|
|
|
foreach(@withs){ |
851
|
|
|
|
|
|
|
#my $pref = $_->{'content'}; |
852
|
|
|
|
|
|
|
my @parts = split(/\//, $_); |
853
|
|
|
|
|
|
|
if(is_IPv6($parts[0])){ |
854
|
|
|
|
|
|
|
push(@v6s, $_); |
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
else{ |
857
|
|
|
|
|
|
|
push(@v4s, $_); |
858
|
|
|
|
|
|
|
} |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
#Checking the address parts in NLRI place |
863
|
|
|
|
|
|
|
my @nlris = BGPmon::Translator::XFB2PerlHash::Simpler::extract_nlri(); |
864
|
|
|
|
|
|
|
foreach(@nlris){ |
865
|
|
|
|
|
|
|
my @parts = split(/\//, $_); |
866
|
|
|
|
|
|
|
if(is_IPv6($parts[0])){ |
867
|
|
|
|
|
|
|
push(@v6s, $_); |
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
else{ |
870
|
|
|
|
|
|
|
push(@v4s, $_); |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
} |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
#Checking the MP_NLRI part of MP_REACH_NLRI; skipping the Next Hop addresses |
876
|
|
|
|
|
|
|
my @reach = BGPmon::Translator::XFB2PerlHash::Simpler::extract_mpreach_nlri(); |
877
|
|
|
|
|
|
|
foreach(@reach){ |
878
|
|
|
|
|
|
|
my @parts = split(/\//, $_); |
879
|
|
|
|
|
|
|
if(is_IPv6($parts[0])){ |
880
|
|
|
|
|
|
|
push(@v6s, $_); |
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
else{ |
883
|
|
|
|
|
|
|
push(@v4s, $_); |
884
|
|
|
|
|
|
|
} |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
#Checking the address part of MP_UNREACH_NLRI |
889
|
|
|
|
|
|
|
my @unreach = BGPmon::Translator::XFB2PerlHash::Simpler::extract_mpunreach_nlri(); |
890
|
|
|
|
|
|
|
foreach(@unreach){ |
891
|
|
|
|
|
|
|
my @parts = split(/\//, $_); |
892
|
|
|
|
|
|
|
if(is_IPv6($parts[0])){ |
893
|
|
|
|
|
|
|
push(@v6s, $_); |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
else{ |
896
|
|
|
|
|
|
|
push(@v4s, $_); |
897
|
|
|
|
|
|
|
} |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
#Checking for the origin in the AS_Path attribute |
903
|
|
|
|
|
|
|
my $origin = BGPmon::Translator::XFB2PerlHash::Simpler::extract_origin(); |
904
|
|
|
|
|
|
|
push(@ases, $origin) if defined($origin); |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
@v4 = uniq(@v4s); |
908
|
|
|
|
|
|
|
@v6 = uniq(@v6s); |
909
|
|
|
|
|
|
|
@as = uniq(@ases); |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
return 0; # successful message parsing |
912
|
|
|
|
|
|
|
} |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
=head2 matches |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
Will check to see if the BGPmon message passed to it has maching prefix or AS |
918
|
|
|
|
|
|
|
fields that were given earlier to the module. |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
Input: A BGPmon message in XML format |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
Output: 1 if there was at least one matching filed. |
923
|
|
|
|
|
|
|
0 if no matches were found. |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
=cut |
926
|
|
|
|
|
|
|
sub matches{ |
927
|
|
|
|
|
|
|
lock($lock); |
928
|
|
|
|
|
|
|
my $xmlMsg = shift; |
929
|
|
|
|
|
|
|
my $fname = 'matches'; |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
if(!defined($xmlMsg)){ |
932
|
|
|
|
|
|
|
$error_code{$fname} = NO_MSG_GIVEN; |
933
|
|
|
|
|
|
|
$error_msg{$fname} = NO_MSG_GIVEN_MSG; |
934
|
|
|
|
|
|
|
return undef; |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
parse_xml_msg($xmlMsg); |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
# Checking to see if any of these AS numbers are ones we're looking for. |
940
|
|
|
|
|
|
|
if(scalar @as > 0){ |
941
|
|
|
|
|
|
|
foreach(@as){ |
942
|
|
|
|
|
|
|
return TRUE if defined $asNumbers{$_}; |
943
|
|
|
|
|
|
|
} |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
# Checking to see if any of the v4 prefixes are matches. |
949
|
|
|
|
|
|
|
if(scalar @v4 > 0){ |
950
|
|
|
|
|
|
|
foreach(@v4){ |
951
|
|
|
|
|
|
|
my $ipPrefAddr = $_; |
952
|
|
|
|
|
|
|
my @toCheck = @{getV4comparisons($_)}; |
953
|
|
|
|
|
|
|
foreach(@toCheck){ |
954
|
|
|
|
|
|
|
my $v4Prefix = $_; |
955
|
|
|
|
|
|
|
return TRUE if $v4Prefix->matches($ipPrefAddr); |
956
|
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
#Checking to see if any of the v4 addresses are a match |
962
|
|
|
|
|
|
|
if(scalar @v4 > 0){ |
963
|
|
|
|
|
|
|
foreach(@addresses){ |
964
|
|
|
|
|
|
|
my $addr = $_; |
965
|
|
|
|
|
|
|
foreach(@v4){ |
966
|
|
|
|
|
|
|
my $tempPrefix = $_; |
967
|
|
|
|
|
|
|
if($addr->matches($tempPrefix)){ |
968
|
|
|
|
|
|
|
return TRUE; |
969
|
|
|
|
|
|
|
} |
970
|
|
|
|
|
|
|
} |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
} |
973
|
|
|
|
|
|
|
} |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
# Checking to see if any of the v6 addresses are matches. |
976
|
|
|
|
|
|
|
if(scalar @v6 > 0){ |
977
|
|
|
|
|
|
|
foreach (@v6prefixes){ |
978
|
|
|
|
|
|
|
my $v6Prefix = $_; |
979
|
|
|
|
|
|
|
#Seeing if we need to keep on to the message |
980
|
|
|
|
|
|
|
foreach(@v6){ |
981
|
|
|
|
|
|
|
my $ipPrefAddr = $_; |
982
|
|
|
|
|
|
|
if($v6Prefix->matches($ipPrefAddr)){ |
983
|
|
|
|
|
|
|
return TRUE; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
return FALSE; |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
1; |
997
|
|
|
|
|
|
|
__END__ |