line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::Whois::RIPE; |
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
364562
|
use 5.006; |
|
5
|
|
|
|
|
66
|
|
4
|
5
|
|
|
5
|
|
29
|
use warnings; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
196
|
|
5
|
5
|
|
|
5
|
|
30
|
use strict; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
106
|
|
6
|
5
|
|
|
5
|
|
2565
|
use Net::Whois::Generic; |
|
5
|
|
|
|
|
16
|
|
|
5
|
|
|
|
|
208
|
|
7
|
5
|
|
|
5
|
|
38
|
use IO::Socket::INET; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
49
|
|
8
|
5
|
|
|
5
|
|
2923
|
use IO::Select; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
187
|
|
9
|
5
|
|
|
5
|
|
28
|
use Iterator; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
401
|
|
10
|
|
|
|
|
|
|
|
11
|
5
|
|
|
|
|
8528
|
use constant { SOON => 30, |
12
|
|
|
|
|
|
|
END_OF_OBJECT_MARK => "\n\n", |
13
|
|
|
|
|
|
|
EOL => "\015\012", |
14
|
|
|
|
|
|
|
QUERY_KEEPALIVE => q{-k }, |
15
|
|
|
|
|
|
|
QUERY_NON_RECURSIVE => q{-r }, |
16
|
|
|
|
|
|
|
QUERY_REFERRAL => q{-R }, |
17
|
|
|
|
|
|
|
QUERY_GROUPING => q{-G }, |
18
|
|
|
|
|
|
|
QUERY_UNFILTERED => q{-B }, |
19
|
|
|
|
|
|
|
QUERY_LIST_OBJECTS => q{-qtypes }, |
20
|
|
|
|
|
|
|
QUERY_LIST_SOURCES => q{-qsources }, |
21
|
|
|
|
|
|
|
QUERY_FETCH_TEMPLATE => q{-t%s }, |
22
|
|
|
|
|
|
|
QUERY_LIMIT_OBJECT_TYPE => q{-T%s }, |
23
|
5
|
|
|
5
|
|
35
|
}; |
|
5
|
|
|
|
|
10
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 NAME |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Net::Whois::RIPE - a pure-Perl implementation of the RIPE Database client. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 VERSION |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Version 2.008001 |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=cut |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
our $VERSION = 2.008001; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 SYNOPSIS |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
This is an evolution of the module I (Arnaud Assad) inherited from Luis Motta Campos. |
40
|
|
|
|
|
|
|
Which was a complete rewrite of the old version of the module inherited from |
41
|
|
|
|
|
|
|
Paul Gampe. It incorporated new concepts Luis have learned while working at the |
42
|
|
|
|
|
|
|
RIPE NCC between Nov 2007 and Jan 2010. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
It intends to provide a cleaner, simpler, and complete implementation of a RIPE |
45
|
|
|
|
|
|
|
Database client. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
The usage should remain mostly the same: |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
use Net::Whois::RIPE; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my $whois = Net::Whois::RIPE->new( %options ); |
52
|
|
|
|
|
|
|
$iterator = $whois->query( 'AS333' ); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
From version 2.005000 you can also use the Net::Whois::Generic interface |
55
|
|
|
|
|
|
|
that mimics Net::Whois::Object while offering access to data from other sources |
56
|
|
|
|
|
|
|
than RIPE (AFRINIC, APNIC) |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
use Net::Whois::RIPE; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
my @objects = Net::Whois::Generic->query( 'ORG-AFNC1-AFRINIC' ); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Please see L documentation for more details |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Of course, comments are more than welcome. If you believe you can help, please |
65
|
|
|
|
|
|
|
do not hesitate in contacting me. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 BACKWARD COMPATIBILITY |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
I've choose to break backwards compatibility with older versions of the L |
70
|
|
|
|
|
|
|
module for several different reasons. I will try to explain and justify them here, as design documentation. |
71
|
|
|
|
|
|
|
I will also strive to provide practical solutions for porting problems, if any. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head2 Architecture |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
The old module provided it's own L implementation. This was common |
76
|
|
|
|
|
|
|
practice 10 years ago, when the module was initially written. I believe Perl |
77
|
|
|
|
|
|
|
has a stable and useful standard implementation of L now, and |
78
|
|
|
|
|
|
|
adopted it instead of maintaining my own. This allows me to reduce the |
79
|
|
|
|
|
|
|
necessary code base without losing features. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 Query Options |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
From release 2.0 onwards, L will allow almost all query |
84
|
|
|
|
|
|
|
options understanded by the RIPE Database Server. I bumped in the lack of |
85
|
|
|
|
|
|
|
options myself, sometimes, and I believe other programmers can also use the |
86
|
|
|
|
|
|
|
extra features offered. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
There are nice, sane defaults provided for most of the options. This should |
89
|
|
|
|
|
|
|
make it possible for a beginner to just ignore all options and settings and |
90
|
|
|
|
|
|
|
still be able to make some use of the module. |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 Memory Footprint |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
I had the intention of reducing the memory footprint of this module when doing |
95
|
|
|
|
|
|
|
heavy-lifting. I still don't have measurements, but that was the idea behind |
96
|
|
|
|
|
|
|
adopting an L wrapping the L used to return results. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head2 Better Data Structures |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
A production release of this module will be able to feed a L with |
101
|
|
|
|
|
|
|
RPSL objects extracted from the RIPE Database and return full-fledged objects |
102
|
|
|
|
|
|
|
containing a parsed version of the text (way more useful than a text blob, I |
103
|
|
|
|
|
|
|
believe). |
104
|
|
|
|
|
|
|
L (from release 2.00_010) is the first attempt toward this |
105
|
|
|
|
|
|
|
goal. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# You can now do |
108
|
|
|
|
|
|
|
my @objects = Net::Whois::Object->query( 'AS333' ); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# And manipulate the object the OO ways |
111
|
|
|
|
|
|
|
for my $object (@objects) { |
112
|
|
|
|
|
|
|
print $object->remarks(); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 METHODS |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head2 B |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Constructor. Returns a new L object with an open connection |
120
|
|
|
|
|
|
|
to the RIPE Database service of choice (defaulting to C). |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
The C<%options> hash migth contain configuration options for the RIPE Database |
123
|
|
|
|
|
|
|
server. Not all options provided by the RIPE Database server are suitable for |
124
|
|
|
|
|
|
|
this implementation, but the idea is to provide everything someone can show a |
125
|
|
|
|
|
|
|
use for. The options currently recognized are: |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=over 4 |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item B (IPv4 address or DNS name. Default is C) |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
The hostname or IP address of the service to connect to |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item B (integer, default is C<43>) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
The TCP port of the service to connect to |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item B (integer, default is C<5>) |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
The time-out (in seconds) for the TCP connection. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item B (boolean, default is C) |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Wherever we want (C) or not (C) to keep the connection to the |
144
|
|
|
|
|
|
|
server open. This option implements the functionality available through RIPE |
145
|
|
|
|
|
|
|
Database's "-k" parameter. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item B (boolean, default is C) |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
When true, prevents the server from using the referral mechanism for domain |
150
|
|
|
|
|
|
|
lookups, so that the RIPE Database server returns an object in the RIPE |
151
|
|
|
|
|
|
|
Database with the exact match with the lookup argument, rather than doing a |
152
|
|
|
|
|
|
|
referral lookup. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item B (boolean, default is C) |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
When set to C, prevents recursion into queried objects for personal |
157
|
|
|
|
|
|
|
information. This prevents lots of unsolicited objects from showing up on |
158
|
|
|
|
|
|
|
queries. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=item B (boolean, default is C) |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
When C enables object grouping in server responses. There's little |
163
|
|
|
|
|
|
|
utility to enable this option, as the objects will be parsed and returned on a |
164
|
|
|
|
|
|
|
much reasonable format most of the time. For the brave or more knowledgeable |
165
|
|
|
|
|
|
|
people that want to have they answers in plain text, this can help stablishing |
166
|
|
|
|
|
|
|
a 'good' ordering for the RPSL objects returned by a query ('good' is RIPE |
167
|
|
|
|
|
|
|
NCC's definition of 'good' in this case). |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item B (boolean, default is C) |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
When C enables unfiltered object output responses. This produces objects |
172
|
|
|
|
|
|
|
that can be presented back to the RIPE Database for updating. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item B (list of valid RIPE Database object types, default is empty, meaning all types) |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Restrict the RPSL object types allowed in the response to those in the list. |
177
|
|
|
|
|
|
|
Using this option will cause the L object to query the RIPE |
178
|
|
|
|
|
|
|
Database for the available object types for validating the list. The response |
179
|
|
|
|
|
|
|
will be cached for speed and bandwidth. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item B (boolean, default is C) |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Prevents the constructor from automatically opening a connection to the service |
184
|
|
|
|
|
|
|
specified (conneting the socket is the default behavior). When set (C), |
185
|
|
|
|
|
|
|
the programmer is responsible for calling C in order to stablish a |
186
|
|
|
|
|
|
|
connection to the RIPE Database service desired. |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=back |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=cut |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
{ |
193
|
|
|
|
|
|
|
my %default_options = ( hostname => 'whois.ripe.net', |
194
|
|
|
|
|
|
|
port => '43', |
195
|
|
|
|
|
|
|
timeout => 5, |
196
|
|
|
|
|
|
|
keepalive => 0, |
197
|
|
|
|
|
|
|
referral => 0, |
198
|
|
|
|
|
|
|
recursive => 0, |
199
|
|
|
|
|
|
|
grouping => 1, |
200
|
|
|
|
|
|
|
unfiltered => 0, |
201
|
|
|
|
|
|
|
types => undef, |
202
|
|
|
|
|
|
|
disconnected => 0, |
203
|
|
|
|
|
|
|
); |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub new { |
206
|
3
|
|
|
3
|
1
|
1755
|
my ( $class, %options ) = @_; |
207
|
3
|
|
|
|
|
7
|
my %known_options; |
208
|
3
|
100
|
|
|
|
47
|
$known_options{$_} = exists $options{$_} ? $options{$_} : $default_options{$_} foreach keys %default_options; |
209
|
|
|
|
|
|
|
|
210
|
3
|
|
|
|
|
12
|
my $self = bless { __options => \%known_options }, $class; |
211
|
|
|
|
|
|
|
|
212
|
3
|
100
|
|
|
|
19
|
$self->connect unless delete $self->{__options}{disconnected}; |
213
|
3
|
|
|
|
|
12
|
return $self; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 B |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Accessor to the hostname. Accepts an optional hostname, always return the |
220
|
|
|
|
|
|
|
current hostname. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=cut |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub hostname { |
225
|
8
|
|
|
8
|
1
|
368
|
my ( $self, $hostname ) = @_; |
226
|
8
|
100
|
|
|
|
23
|
$self->{__options}{hostname} = $hostname if defined $hostname; |
227
|
8
|
|
|
|
|
29
|
return $self->{__options}{hostname}; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head2 B |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
Accessor to the port. Accepts an optional port, always return the current |
233
|
|
|
|
|
|
|
port. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=cut |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub port { |
238
|
10
|
|
|
10
|
1
|
21
|
my ( $self, $port ) = @_; |
239
|
10
|
100
|
100
|
|
|
43
|
$self->{__options}{port} = $port if defined $port && $port =~ m{^\d+$}; |
240
|
10
|
|
|
|
|
36
|
return $self->{__options}{port}; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head2 B |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Accessor to the timeout configuration option. Accepts an optional timeout, |
246
|
|
|
|
|
|
|
always return the current timeout. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=cut |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub timeout { |
251
|
16
|
|
|
16
|
1
|
36
|
my ( $self, $timeout ) = @_; |
252
|
16
|
100
|
100
|
|
|
55
|
$self->{__options}{timeout} = $timeout |
253
|
|
|
|
|
|
|
if defined $timeout && $timeout =~ m{^\d+$}; |
254
|
16
|
|
|
|
|
76
|
return $self->{__options}{timeout}; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=begin UNDOCUMENTED |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=head2 B<__boolean_accessor( $self, $attribute [, $value ] )> |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Private method. Shouldn't be used from other modules. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Generic implementation of an accessor for booleans. Receives a reference to the |
264
|
|
|
|
|
|
|
current instance, the attribute name, and a value to be interpreted under |
265
|
|
|
|
|
|
|
Perl's boolean rules. Sets or gets the named attribute with the given value. |
266
|
|
|
|
|
|
|
Always returns the most up-to-date value of the attribute. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=end UNDOCUMENTED |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub __boolean_accessor { |
273
|
32
|
|
|
32
|
|
62
|
my ( $self, $attribute ) = ( shift, shift ); |
274
|
32
|
100
|
|
|
|
73
|
if ( scalar @_ == 1 ) { |
275
|
8
|
|
|
|
|
11
|
my $value = shift; |
276
|
8
|
100
|
|
|
|
51
|
$self->{__options}{$attribute} = $value ? 1 : 0; |
277
|
|
|
|
|
|
|
} |
278
|
32
|
|
|
|
|
144
|
return $self->{__options}{$attribute}; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 B |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Accessor to the keepalive configuration option. Accepts an optional keepalive, |
284
|
|
|
|
|
|
|
always return the current keepalive. |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=cut |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub keepalive { |
289
|
13
|
|
|
13
|
1
|
23
|
my $self = shift; |
290
|
13
|
|
|
|
|
37
|
return $self->__boolean_accessor( 'keepalive', @_ ); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 B |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Accessor to the referral configuration option. Accepts an optional referral, |
296
|
|
|
|
|
|
|
always return the current referral. |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=cut |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub referral { |
301
|
6
|
|
|
6
|
1
|
11
|
my $self = shift; |
302
|
6
|
|
|
|
|
16
|
return $self->__boolean_accessor( 'referral', @_ ); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head2 B |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Accessor to the recursive configuration option. Accepts an optional recursive, |
308
|
|
|
|
|
|
|
always return the current recursive. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=cut |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub recursive { |
313
|
6
|
|
|
6
|
1
|
12
|
my $self = shift; |
314
|
6
|
|
|
|
|
14
|
return $self->__boolean_accessor( 'recursive', @_ ); |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head2 B |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Accessor to the grouping configuration option. Accepts an optional grouping, |
320
|
|
|
|
|
|
|
always return the current grouping. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=cut |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub grouping { |
325
|
5
|
|
|
5
|
1
|
10
|
my $self = shift; |
326
|
5
|
|
|
|
|
13
|
return $self->__boolean_accessor( 'grouping', @_ ); |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head2 B |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
Accessor to the unfiltered configuration option. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=cut |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub unfiltered { |
336
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
337
|
2
|
|
|
|
|
6
|
return $self->__boolean_accessor( 'unfiltered', @_ ); |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head2 B |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
Initiates a connection with the current object's configuration. |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=cut |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub connect { |
347
|
5
|
|
|
5
|
1
|
14
|
my $self = shift; |
348
|
5
|
|
|
|
|
17
|
my %connection = ( Proto => 'tcp', |
349
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
350
|
|
|
|
|
|
|
PeerAddr => $self->hostname, |
351
|
|
|
|
|
|
|
PeerPort => $self->port, |
352
|
|
|
|
|
|
|
Timeout => $self->timeout, |
353
|
|
|
|
|
|
|
Domain => AF_INET, |
354
|
|
|
|
|
|
|
Multihomed => 1, |
355
|
|
|
|
|
|
|
); |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Create a new IO::Socket object |
358
|
5
|
|
|
|
|
43
|
my $socket = $self->{__state}{socket} = IO::Socket::INET->new(%connection); |
359
|
5
|
50
|
|
|
|
153252
|
die q{Can't connect to "} . $self->hostname . ':' . $self->port . qq{". Reason: [$@].\n} |
360
|
|
|
|
|
|
|
unless defined $socket; |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# Register $socket with the IO::Select object |
363
|
5
|
100
|
|
|
|
43
|
if ( my $ios = $self->ios ) { |
364
|
3
|
50
|
|
|
|
12
|
$ios->add($socket) unless $ios->exists($socket); |
365
|
|
|
|
|
|
|
} else { |
366
|
2
|
|
|
|
|
15
|
$self->{__state}{ioselect} = IO::Select->new($socket); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Set RIPE Database's "keepalive" capability |
370
|
5
|
50
|
|
|
|
311
|
$self->send(QUERY_KEEPALIVE) if $self->keepalive; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=head2 B |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Accessor to the L object coordinating the I/O to the L |
376
|
|
|
|
|
|
|
object used by this module to communicate with the RIPE Database Server. You |
377
|
|
|
|
|
|
|
shouldn't use this object, but the L"send()"> and L<"query( $query_string )"> |
378
|
|
|
|
|
|
|
methods instead. |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=cut |
381
|
|
|
|
|
|
|
|
382
|
13
|
|
|
13
|
1
|
58
|
sub ios { return $_[0]->{__state}{ioselect} } |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=head2 B |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Read-only accessor to the L object used by this module. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=cut |
389
|
|
|
|
|
|
|
|
390
|
22
|
|
|
22
|
1
|
535
|
sub socket { return $_[0]->{__state}{socket} } |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head2 B |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
Sends a message to the RIPE Database server instance to which we're connected |
395
|
|
|
|
|
|
|
to. Dies if it cannot write, or if there's no open connection to the server. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
Return C if the message could be written to the socket, C |
398
|
|
|
|
|
|
|
otherwise. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=cut |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub send { |
403
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $message ) = @_; |
404
|
0
|
0
|
|
|
|
0
|
die q{Not connected} unless $self->is_connected; |
405
|
0
|
0
|
|
|
|
0
|
if ( $self->ios->can_write( SOON + $self->timeout ) ) { |
406
|
0
|
|
|
|
|
0
|
$self->socket->print( $message, EOL ); |
407
|
0
|
|
|
|
|
0
|
$self->socket->flush; |
408
|
0
|
|
|
|
|
0
|
return 1; |
409
|
|
|
|
|
|
|
} |
410
|
0
|
|
|
|
|
0
|
return 0; |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=head2 B |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
Reconnects to the server in case we lost connection. |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=cut |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub reconnect { |
420
|
3
|
|
|
3
|
1
|
7
|
my $self = shift; |
421
|
3
|
50
|
|
|
|
7
|
$self->disconnect if $self->is_connected; |
422
|
3
|
|
|
|
|
10
|
$self->connect; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=head2 B |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Disconnects this client from the server. This renders the client useless until |
428
|
|
|
|
|
|
|
you call L"connect()"> again. This method is called by L as part of |
429
|
|
|
|
|
|
|
an object's clean-up process. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub disconnect { |
434
|
7
|
|
|
7
|
1
|
1182
|
my $self = shift; |
435
|
7
|
100
|
|
|
|
30
|
if ( $self->is_connected ) { |
436
|
5
|
|
|
|
|
101
|
my $socket = $self->{__state}{socket}; |
437
|
5
|
|
|
|
|
29
|
$socket->close; |
438
|
|
|
|
|
|
|
$self->{__state}{ioselect}->remove($socket) |
439
|
5
|
50
|
|
|
|
579
|
if $self->{__state}{ioselect}; |
440
|
5
|
|
|
|
|
474
|
delete $self->{__state}{socket}; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=head2 B |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
Returns C if this instance is connected to the RIPE Database service |
447
|
|
|
|
|
|
|
configured. |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=cut |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub is_connected { |
452
|
15
|
|
|
15
|
1
|
1152
|
my $self = shift; |
453
|
15
|
|
|
|
|
33
|
my $socket = $self->socket; |
454
|
15
|
100
|
66
|
|
|
245
|
return UNIVERSAL::isa( $socket, 'IO::Socket' ) |
455
|
|
|
|
|
|
|
&& $socket->connected ? 1 : 0; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=head2 B |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
Net::Whois::RIPE object destructor. Called by the Perl interpreter upon |
461
|
|
|
|
|
|
|
destruction of an instance. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=cut |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub DESTROY { |
466
|
3
|
|
|
3
|
|
1376
|
my $self = shift; |
467
|
3
|
|
|
|
|
11
|
$self->disconnect; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=head2 B |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
Sends a query to the server. Returns an L object that will return one RPSL block at a time. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=cut |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
# TODO: Identify and ignore comments within the Iterator scope? |
477
|
|
|
|
|
|
|
# TODO: Identify and rise as soon as possible "%ERROR:\d+:.+" results. |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
sub query { |
480
|
1
|
|
|
1
|
1
|
3
|
my ( $self, $query ) = @_; |
481
|
1
|
|
|
|
|
3
|
my $parameters = ""; |
482
|
1
|
50
|
|
|
|
3
|
$parameters .= q{ } . QUERY_KEEPALIVE if $self->keepalive; |
483
|
1
|
50
|
|
|
|
4
|
$parameters .= q{ } . QUERY_UNFILTERED if $self->unfiltered; |
484
|
1
|
50
|
|
|
|
3
|
$parameters .= q{ } . QUERY_NON_RECURSIVE unless $self->recursive; |
485
|
1
|
50
|
|
|
|
4
|
$parameters .= q{ } . QUERY_REFERRAL if $self->referral; |
486
|
1
|
|
|
|
|
3
|
my $fullquery = $parameters . $query; |
487
|
1
|
|
|
|
|
5
|
return $self->__query($fullquery); |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# Allows me to pass in queries without having all the automatic options added |
491
|
|
|
|
|
|
|
# up to it. |
492
|
|
|
|
|
|
|
sub __query { |
493
|
2
|
|
|
2
|
|
17
|
my ( $self, $query ) = @_; |
494
|
2
|
50
|
|
|
|
9
|
$self->reconnect unless $self->keepalive; |
495
|
2
|
50
|
|
|
|
6
|
die "Not connected" unless $self->is_connected; |
496
|
|
|
|
|
|
|
|
497
|
2
|
50
|
|
|
|
49
|
if ( $self->ios->can_write( SOON + $self->timeout ) ) { |
498
|
2
|
|
|
|
|
99
|
$self->socket->print( $query, EOL ); |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
return Iterator->new( |
501
|
|
|
|
|
|
|
sub { |
502
|
4
|
|
|
4
|
|
94
|
local $/ = "\n\n"; |
503
|
4
|
50
|
|
|
|
14
|
if ( $self->ios->can_read( SOON + $self->timeout ) ) { |
504
|
4
|
|
|
|
|
35428
|
my $block = $self->socket->getline; |
505
|
4
|
50
|
|
|
|
274
|
return $block if defined $block; |
506
|
|
|
|
|
|
|
} |
507
|
0
|
|
|
|
|
0
|
Iterator::is_done; |
508
|
|
|
|
|
|
|
} |
509
|
2
|
|
|
|
|
252
|
); |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=head2 B |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
Return a list of known object types from the RIPE Database. |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
RIPE currently returns 21 types (Limerik have been removed): |
518
|
|
|
|
|
|
|
as-block as-set aut-num domain filter-set inet6num inetnum inet-rtr irt |
519
|
|
|
|
|
|
|
key-cert mntner organisation peering-set person poem poetic-form role route |
520
|
|
|
|
|
|
|
route6 route-set rtr-set |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Due to some strange mis-behaviour in the protocol (or documentation?) the RIPE |
523
|
|
|
|
|
|
|
Database server won't allow a keep-alive token with this query, meaning the |
524
|
|
|
|
|
|
|
connection will be terminated after this query. |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=cut |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
sub object_types { |
529
|
1
|
|
|
1
|
1
|
1045
|
my $self = shift; |
530
|
1
|
|
|
|
|
4
|
my $iterator = $self->__query(QUERY_LIST_OBJECTS); |
531
|
1
|
|
|
|
|
29
|
while ( !$iterator->is_exhausted ) { |
532
|
2
|
|
|
|
|
19
|
my $value = $iterator->value; |
533
|
2
|
100
|
|
|
|
69
|
return split /\s+/, $value if $value !~ /^%\s/; |
534
|
|
|
|
|
|
|
} |
535
|
0
|
|
|
|
|
|
return; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=head1 CAVEATS |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=over 4 |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=item B |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
There's no support for IPv6 still on this module. I'm planning to add it in a |
545
|
|
|
|
|
|
|
future version. |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=item B |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
As this is the initial alpha release, there is still some work to do in terms |
550
|
|
|
|
|
|
|
of testing. One of the first things I must work on is to eliminate the |
551
|
|
|
|
|
|
|
dependency on connectivity to the RIPE Database. |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=item B |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
I plan to implement a drop-in replacement to the old interface soon, as an extension to this module. For now, this module just breaks compatibility with the old interface. Please read the full discussion about compatibility with older version of the L in the L"BACKWARD COMPATIBILITY"> section. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=back |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=head1 BUGS |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
Please report any bugs or feature requests to C
|
562
|
|
|
|
|
|
|
rt.cpan.org>, or through the web interface at |
563
|
|
|
|
|
|
|
L. I will be |
564
|
|
|
|
|
|
|
notified, and then you'll automatically be notified of progress on your bug as |
565
|
|
|
|
|
|
|
I make changes. |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
=head1 SUPPORT |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
perldoc Net::Whois::RIPE |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
You can also look for information at: |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=over 4 |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
L |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
L |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=item * CPAN Ratings |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
L |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=item * Search CPAN |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
L |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=back |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=head1 AUTHORS |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
Arnaud Assad, C<< aassad at cpan.org >> |
600
|
|
|
|
|
|
|
Luis Motta Campos, C<< >> |
601
|
|
|
|
|
|
|
Paul Gampe |
602
|
|
|
|
|
|
|
Kevin Backer |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
Thanks to DOOLTA (L) for allowing Arnaud Assad to work on this module during some of his office |
607
|
|
|
|
|
|
|
hours. |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Thanks to Luis Motta Campos for allowing me (Arnaud Assad) the maintenance of this |
610
|
|
|
|
|
|
|
module on CPAN; |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
Thanks to RIPE NCC for allowing Luis Motta Campos to work on this during some of his office |
613
|
|
|
|
|
|
|
hours. |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Thanks to Paul Gampe for allowing Luis Motta Campos to handle me the maintenance of this |
616
|
|
|
|
|
|
|
module on CPAN; |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
Thanks to Paul Gampe and Kevin Backer for writing previous versions of this |
619
|
|
|
|
|
|
|
module; |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
Thanks to Carlos Fuentes for the nice patch with bugfixes for version 2.00_008. |
622
|
|
|
|
|
|
|
Thanks to Moritz Lenz for all his contributions |
623
|
|
|
|
|
|
|
Thanks to Noris Network AG for allowing him to contribute to this module. |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
Copyright 2012-2020 Arnaud Assad |
628
|
|
|
|
|
|
|
Copyright 2010 Luis Motta Campos, all rights reserved. |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
631
|
|
|
|
|
|
|
under the same terms as Perl itself. |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=cut |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
1; |