File Coverage

blib/lib/Net/ASN.pm
Criterion Covered Total %
statement 159 174 91.3
branch 69 96 71.8
condition 18 48 37.5
subroutine 22 22 100.0
pod 14 14 100.0
total 282 354 79.6


line stmt bran cond sub pod time code
1             # ASN.pm - Perl module to manipulate autonomous system numbers
2             #
3             # Author: David J. Freedman
4             #
5             # Copyright (C) 2008 Convergence Inc.
6             #
7             # This program is free software; you can redistribute it and/or modify
8             # it under the terms as perl itself.
9             #
10              
11             package Net::ASN;
12              
13 1     1   715 use strict;
  1         2  
  1         57  
14 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         1  
  1         177  
15              
16             BEGIN {
17              
18 1     1   5 require Exporter;
19              
20 1         27 @ISA = qw(Exporter);
21              
22 1         3 @EXPORT = qw();
23              
24 1         4 %EXPORT_TAGS = (
25             all => [qw{
26             plaintodot plaintodotplus
27             dottodotplus dottoplain
28             dottoplain16 dotplustodot
29             dotplustoplain dotplustoplain16
30             } ],
31             );
32              
33 1         1 @EXPORT_OK = qw();
34              
35 1         45 Exporter::export_ok_tags('all');
36              
37 1         15 $VERSION = '1.06';
38             }
39              
40             # Preloaded methods go here.
41 1     1   6 use Carp;
  1         1  
  1         98  
42              
43             #Constants
44 1     1   5 use constant AS_TRANS => 23456;
  1         2  
  1         7326  
45              
46             ##OO Methods
47              
48             #Initialise with an ASN
49             #
50             sub new {
51              
52 22     22 1 552 my $class = shift;
53 22         47 my $self = {};
54              
55 22         31 my $asn = shift;
56              
57 22         27 my $asasdot = shift;
58              
59 22         53 bless $self, $class;
60              
61 22         63 $self->_parseasn($asn,$asasdot); #Parse the ASN
62              
63 22         95 return $self;
64              
65             }
66              
67             #Parses an ASN, in any format
68             sub _parseasn ($;$) {
69              
70 22     22   26 my $self = shift;
71 22         27 my $inasn = shift;
72 22         29 my $asasdot = shift;
73              
74             #Perform some basic checks
75             #
76             #1) did we even get a parameter?
77 22 50       51 unless ($inasn) {
78 0         0 croak __PACKAGE__, ": ASN not provided";
79             }
80             #2) does the ASN contain a valid character set?
81 22 50       182 unless ($inasn=~m/^[\d\.]+$/) {
82 0         0 croak __PACKAGE__, ": Invalid ASN (Illegal Characters)";
83             }
84             #3) Next, check the format
85              
86 22 100       153 if ($inasn=~m/^(\d+)$/) { #ASN is ASN16 (1-65535) or ASN32 ASPLAIN (1-4294967295) or ASDOT if forced
    50          
87 10 100 66     65 if ($asasdot) {
    100 33        
    50          
88 4 50 33     23 if ($inasn > 0 && $inasn <= 65535) {
89 4         10 $self->{_informat} = 'asdot';
90 4         7 $self->{_asdot} = $inasn;
91             }
92             else {
93 0         0 croak __PACKAGE__, ": Invalid ASDOT ASN (ASDOT does NOT permit ASPLAIN notation for ASNs 63356-4294967295)";
94             }
95             }
96             elsif ($inasn > 0 && $inasn <= 65535) {
97 3         29 $self->{_informat} = 'asplain16';
98 3         8 $self->{_asplain16} = $inasn;
99             }
100             elsif ($inasn > 65535 && $inasn <= 4294967295) {
101 3         8 $self->{_informat} = 'asplain32';
102 3         8 $self->{_asplain32} = $inasn;
103             }
104             else {
105 0         0 croak __PACKAGE__, ": Invalid ASPLAIN ASN (must be between 1-4294967295)";
106             }
107             }
108             elsif ($inasn=~m/^(\d+)\.(\d+)$/) { #ASN is ASN32 ASDOT+ notation or ASDOT if forced
109              
110 12         31 my $firstasn = $1;
111 12         20 my $secondasn = $2;
112              
113 12 50 33     157 unless (
      33        
      33        
      66        
      33        
114             ($firstasn >= 0 && $firstasn <= 65535) &&
115             ($secondasn >= 0 && $secondasn <= 65535) &&
116             (
117             ($firstasn > 0) ||
118             ($secondasn > 0)
119             )
120             ) {
121 0         0 croak __PACKAGE__, ": Invalid ASDOT(+) ASN (must be between 0-65535.0-65535 and NOT 0.0)";
122             }
123              
124             #Allow input as ASDOT if $asasdot is populated
125 12 100       21 if ($asasdot) {
126 4 50       11 if ($firstasn > 0) {
127 4         10 $self->{_informat} = 'asdot';
128             }
129             else {
130 0         0 croak __PACKAGE__, ": Invalid ASDOT ASN (ASDOT does NOT permit ASDOT+ notation for ASNs 0-65535)";
131             }
132             }
133             else {
134 8         23 $self->{_informat} = 'asdotplus';
135             }
136 12         22 $self->{_asdotsedtet1} = $firstasn;
137 12         23 $self->{_asdotsedtet2} = $secondasn;
138              
139             }
140             else {
141 0         0 croak __PACKAGE__, ": Invalid ASN (Illegal Format)";
142             }
143              
144 22         35 return;
145              
146             }
147              
148             sub _plaintodot ($) {
149            
150 8     8   12 my $self = shift;
151 8         12 my $asplain = shift;
152              
153 8 50       40 unless ($asplain=~m/^(\d+)$/) {
154 0         0 die ("Internal Error: _plaintodot called with invalid plain");
155             }
156             else {
157 8         23 my $asdot=int($asplain/65536);
158 8         18 $asdot .= ".";
159 8         29 $asdot .= ($asplain - ($asdot*65536));
160 8         28 return $asdot;
161             }
162              
163             }
164              
165             sub _dottoplain ($) {
166              
167 6     6   10 my $self = shift;
168 6         11 my $asdot = shift;
169              
170 6 50       33 unless ($asdot=~m/^(\d+)\.(\d+)$/) {
171 0         0 die("Internal Error: _dottoplain called with invalid dot");
172             }
173             else {
174 6         14 my $asplain1 = $1;
175 6         11 my $asplain2 = $2;
176 6         17 my $asplain = (65536 * $asplain1);
177 6         11 $asplain+=$asplain2;
178 6         13 return $asplain;
179             }
180             }
181              
182             ##Produce ASDOT representation of parsed ASN
183             sub toasdot () {
184              
185 10     10 1 21 my $self = shift;
186 10 100       66 if ($self->{_informat} eq 'asdot') { #User wants asdot and we already have it, just return it
    100          
    100          
    50          
187 2 100       9 if ($self->{_asdot}) {
188 1         6 return $self->{_asdot};
189             }
190             else {
191 1         4 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
192 1         5 return ($value);
193             }
194              
195             }
196             elsif ($self->{_informat} eq 'asdotplus') { #User wants asdot and has given us asdotplus, so return asplain if
197 4 100       13 if ($self->{_asdotsedtet1} == 0) { #If first sedtet is 0, return the second only
198 2         13 return ($self->{_asdotsedtet2});
199             }
200             else { #Else, return both
201 2         6 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
202 2         13 return ($value);
203             }
204             }
205             elsif ($self->{_informat} eq 'asplain16') { #User wants asdot and has given us an 16 bit asplain (just return asplain)
206 2         5 my $value = $self->{_asplain16};
207 2         12 return ($value);
208             }
209             elsif ($self->{_informat} eq 'asplain32') { #User wants asdot and has given us an 32 bit asplain
210 2         5 my $value = $self->{_asplain32};
211 2         8 $value = $self->_plaintodot($value);
212 2         11 return ($value);
213             }
214             else {
215 0         0 die ("Internal Error: no acceptable informat defined");
216             }
217              
218             }
219              
220             ##Produce ASDOT+ representation of parsed ASN
221             sub toasdotplus () {
222              
223 10     10 1 24 my $self = shift;
224 10 100       60 if ($self->{_informat} eq 'asdot') { #User wants asdotplus and we have asdot
    100          
    100          
    50          
225 4 100       14 if ($self->{_asdot}) {
226 2         8 my $value = $self->_plaintodot($self->{_asdot});
227 2         12 return ($value);
228             }
229             else {
230 2         7 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
231 2         9 return ($value);
232             }
233             }
234             elsif ($self->{_informat} eq 'asdotplus') { #User wants asdotplus and we have it, just return it
235 2         8 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
236 2         9 return ($value);
237             }
238             elsif ($self->{_informat} eq 'asplain16') { #User wants asdotplus and has given us an 16 bit asplain
239 2         4 my $value = $self->{_asplain16};
240 2         7 $value = $self->_plaintodot($value);
241 2         14 return ($value);
242             }
243             elsif ($self->{_informat} eq 'asplain32') { #User wants asdotplus and has given us an 32 bit asplain
244 2         5 my $value = $self->{_asplain32};
245 2         6 $value = $self->_plaintodot($value);
246 2         12 return ($value);
247             }
248             else {
249 0         0 die ("Internal Error: no acceptable informat defined");
250             }
251              
252             }
253              
254             ##Produce ASPLAIN representation of parsed ASN (32 bit version)
255             sub toasplain () {
256              
257 10     10 1 22 my $self = shift;
258              
259 10 100       775 if ($self->{_informat} eq 'asdot') { #User wants asplain and we have asdot
    100          
    100          
    50          
260 4 100       12 if ($self->{_asdot}) {
261 2         15 return ($self->{_asdot});
262             }
263             else {
264 2         8 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
265 2         7 $value = $self->_dottoplain($value);
266 2         9 return ($value);
267             }
268             }
269             elsif ($self->{_informat} eq 'asplain16') { #User wants asplain and we have it
270 1         4 my $value = $self->{_asplain16};
271 1         6 return ($value);
272             }
273             elsif ($self->{_informat} eq 'asplain32') { #User wants asplain and we have it
274 1         6 my $value = $self->{_asplain32};
275 1         7 return ($value);
276             }
277             elsif ($self->{_informat} eq 'asdotplus') { #User wants asplain and has given us asdotplus so return asplain
278 4         14 my $value = "$self->{_asdotsedtet1}.$self->{_asdotsedtet2}";
279 4         15 $value = $self->_dottoplain($value);
280 4         23 return ($value);
281             }
282             else {
283 0         0 die ("Internal Error: no acceptable informat defined");
284             }
285             }
286              
287             ##Produce ASPLAIN representation of parsed ASN (16 bit version)
288             sub toasplain16 () {
289              
290 8     8 1 17 my $self = shift;
291              
292 8 100       55 if ($self->{_informat} eq 'asdot') { #User wants asplain16 and we have asdot
    50          
    100          
    50          
293 3 100       10 if ($self->{_asdot}) {
294 1         5 return ($self->{_asdot});
295             }
296             else {
297 2         11 return (AS_TRANS);
298             }
299             }
300             elsif ($self->{_informat} eq 'asplain16') { #User wants asplain and we have it
301 0         0 my $value = $self->{_asplain16};
302 0         0 return ($value);
303             }
304             elsif ($self->{_informat} eq 'asplain32') { #User wants asplain so return AS_TRANS
305 1         5 return (AS_TRANS);
306             }
307             elsif ($self->{_informat} eq 'asdotplus') { #User wants asplain and has given us asdotplus, return AS_TRANS for 32 bit
308 4 100       11 if ($self->{_asdotsedtet1} == 0) {
309 2         16 return ($self->{_asdotsedtet2});
310             }
311             else {
312 2         11 return (AS_TRANS);
313             }
314             }
315             else {
316 0         0 die ("Internal Error: no acceptable informat defined");
317             }
318             }
319              
320             ##Return parsed type
321             sub gettype () {
322 6     6 1 15 my $self = shift;
323 6         14 my $informat = $self->{_informat};
324 6         25 $informat=~s/\d+//g; #Remove ASPLAIN differentiation
325 6         33 return ($informat);
326             }
327              
328             ###NON OO Function wrappers
329             ##toasdot
330             sub plaintodot ($) {
331 2     2 1 4 my $inasn = shift;
332 2 50       10 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
333 2 50       11 croak __PACKAGE__, ": Must provide ASPLAIN" unless ($inasn=~m/^(\d+)$/); #Ensure only numerical is passed
334 2   33     8 my $asn = Net::ASN->new($inasn) || croak __PACKAGE__, ": Could not create new Net::ASN object";
335 2         6 return ($asn->toasdot);
336             }
337             ##toasdotplus
338             sub plaintodotplus ($) {
339 2     2 1 5 my $inasn = shift;
340 2 50       6 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
341 2 50       10 croak __PACKAGE__, ": Must provide ASPLAIN" unless ($inasn=~m/^(\d+)$/); #Ensure only numerical is passed
342 2   33     6 my $asn = Net::ASN->new($inasn) || croak __PACKAGE__, ": Could not create new Net::ASN object";
343 2         6 return ($asn->toasdotplus);
344             }
345             ##toasdotplus
346             sub dottodotplus ($) {
347 2     2 1 3 my $inasn = shift;
348 2 50       6 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
349 2   33     5 my $asn = Net::ASN->new($inasn,1) || croak __PACKAGE__, ": Could not create new Net::ASN object";
350 2         8 return ($asn->toasdotplus);
351             }
352             ##toasplain
353             sub dottoplain ($) {
354 2     2 1 3 my $inasn = shift;
355 2 50       5 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
356 2   33     8 my $asn = Net::ASN->new($inasn,1) || croak __PACKAGE__, ": Could not create new Net::ASN object";
357 2         4 return ($asn->toasplain);
358             }
359             ##toasplain16
360             sub dottoplain16 ($) {
361 2     2 1 4 my $inasn = shift;
362 2 50       6 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
363 2   33     5 my $asn = Net::ASN->new($inasn,1) || croak __PACKAGE__, ": Could not create new Net::ASN object";
364 2         4 return ($asn->toasplain16);
365             }
366             ##toasdot again
367             sub dotplustodot ($) {
368 2     2 1 5 my $inasn = shift;
369 2 50       7 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
370 2 50       8 croak __PACKAGE__, ": Must provide ASDOT+" unless ($inasn=~m/\./); #Ensure only dotted is passed
371 2   33     7 my $asn = Net::ASN->new($inasn) || croak __PACKAGE__, ": Could not create new Net::ASN object";
372 2         6 return ($asn->toasdot);
373             }
374             ##toasplain
375             sub dotplustoplain ($) {
376 2     2 1 4 my $inasn = shift;
377 2 50       6 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
378 2 50       8 croak __PACKAGE__, ": Must provide ASDOT+" unless ($inasn=~m/\./); #Ensure only dotted is passed
379 2   33     17 my $asn = Net::ASN->new($inasn) || croak __PACKAGE__, ": Could not create new Net::ASN object";
380 2         7 return ($asn->toasplain);
381             }
382             ##toasplain16
383             sub dotplustoplain16 ($) {
384 2     2 1 5 my $inasn = shift;
385 2 50       73 croak __PACKAGE__, ": No ASN specified" unless ($inasn);
386 2 50       9 croak __PACKAGE__, ": Must provide ASDOT+" unless ($inasn=~m/\./); #Ensure only dotted is passed
387 2   33     8 my $asn = Net::ASN->new($inasn) || croak __PACKAGE__, ": Could not create new Net::ASN object";
388 2         6 return ($asn->toasplain16);
389             }
390              
391             1;
392             __END__