File Coverage

blib/lib/Net/IPv6Address.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Net::IPv6Address;
2              
3 1     1   14424 use 5.006001;
  1         5  
  1         47  
4 1     1   10 use strict;
  1         3  
  1         131  
5 1     1   8 use warnings;
  1         16  
  1         41  
6 1     1   2219 use Debug;
  0            
  0            
7              
8             require Exporter;
9              
10             our @ISA = qw(Exporter);
11              
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15              
16             # This allows declaration use Net::IPv6Address ':all';
17             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
18             # will save memory.
19             our %EXPORT_TAGS = ( 'all' => [ qw(
20            
21             ) ] );
22              
23             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
24              
25             our @EXPORT = qw(
26            
27             );
28              
29             our $VERSION = '0.02';
30              
31             # Preloaded methods go here.
32             my $package = __PACKAGE__;
33             my $logger = new Debug();
34              
35             sub new {
36             my $class = shift;
37             my $address = shift || undef;
38             my $length = shift || 64;
39             my $self = {};
40            
41             $self->{'ADDRESS'} = $address if defined $address;
42             $self->{'ADDRESSLENGTH'} = $length if defined $length;
43            
44             # $logger->initialize();
45            
46             bless $self, $class;
47            
48             if(($self->{'ADDRESS'})&&($self->{'ADDRESSLENGTH'})) {
49             $self->decompressAddress();
50             }
51            
52             return $self;
53             }
54              
55             # loadDebug() - this routine accepts a Debug.pm object to facilitate initialization of the debugging
56             sub loadDebug() {
57             my $self = shift;
58             my $debug = shift;
59            
60             $logger = bless $debug, "Debug";
61             # $logger->initialize();
62             }
63              
64             # decompressAddress() - fully uncompresses an IPv6 address so that all 128 bits are displayed and returned.
65             sub decompressAddress() {
66             my $self = shift;
67             my @address = undef;
68             my @uAddress = undef;
69             my $s_uAddress = undef;
70             my $tmp = undef;
71            
72             @address = split(/:/,$self->{'ADDRESS'});
73             my $address_len = scalar(@address);
74            
75             $logger->message("Decompressing $self->{'ADDRESS'}");
76            
77             if($address_len < 8) {
78            
79             my $iteration = 0;
80             my @t_address = undef;
81             my $found_empty = 0;
82             $logger->message("Address provided is abbreviated, performing additional processing");
83             foreach my $a (@address) {
84             # $logger->message("address_len = $address_len, iteration = $iteration, a = $a");
85             if($iteration < 7) {
86             if((!$found_empty)&&($a ne "")) {
87             # $logger->message("Found no empties, copying data to temporary array");
88             $t_address[$iteration] = $a;
89             $iteration++;
90             next;
91             }
92             # handle the first missing portion of the address
93             if($a eq "") {
94             # $logger->message("Found first empty");
95             $found_empty = 1;
96             $t_address[$iteration] = 0;
97             # $logger->message("Setting chunk to 0");
98             $iteration++;
99             next;
100             }
101             # handle when a non-empty portion follows and missing portions
102             if(($found_empty)&&($a)) {
103             # $logger->message("Already found an empty, but the chunk contains data");
104             $t_address[7] = $a;
105             $iteration++;
106             next;
107             }
108             }
109             $iteration++;
110             }
111            
112             my $t_address_len = scalar(@t_address);
113             my $need_to_pad = 8 - $t_address_len;
114             my $pad_counter = undef;
115             # $logger->message("t_address_len = $t_address_len, need_to_pad = $need_to_pad, pad_counter = $pad_counter");
116             if($need_to_pad > 0) {
117             $logger->message("Still need to pad $need_to_pad positions");
118             for($pad_counter = 0; $pad_counter < $need_to_pad; $pad_counter++) {
119             # $logger->message("pad_counter = $pad_counter, need_to_pad = $need_to_pad");
120             $tmp = $t_address_len+$pad_counter;
121             $t_address[$tmp] = 0;
122             # $logger->message("Set t_address[$tmp] to 0");
123             }
124             }
125            
126             @address = @t_address;
127             $logger->message("Unabbreviation is complete");
128             }
129            
130             $logger->message("Decompressing address...");
131            
132             $tmp = undef;
133             my $chunk_len = undef;
134             my $c = 0;
135             my $x = undef;
136            
137             foreach my $y (@address) {
138             if(!$y) {
139             $y = 0;
140             }
141             $x = $self->trim($y);
142             # $x = $y;
143             $chunk_len = length($x);
144             # $logger->message("original data $x, length $chunk_len, iteration $c");
145            
146             if((length($x)) < 4) {
147             # $tmp = printf("%04S", $x);
148             $tmp = sprintf("%04s", $x);
149             } else {
150             # $logger->message("chunk is uncompressed already") if ($verbose);
151             $tmp = $x;
152             # $logger->message("chunk is uncompressed already");
153             }
154            
155             # $logger->message("[debug]:uncompressed chunk $tmp");
156             # $logger->message("setting uAddress[$c] -> $tmp");
157             $uAddress[$c] = $tmp;
158             $c++;
159             }
160              
161             my $uAddress_len = scalar(@uAddress);
162             # $logger->message("uAddress_len, $uAddress_len");
163            
164             my $buf = undef;
165             foreach my $z(@uAddress) {
166             $s_uAddress .= $z;
167             # $logger->message("contents of z, $z");
168             }
169            
170             # $logger->message("uncomressed address, $s_uAddress");
171             $logger->message("Decompressed address, @uAddress($s_uAddress)");
172            
173             $self->{'D_ADDRESS'} = $s_uAddress;
174            
175             return $self->{'D_ADDRESS'};
176             }
177              
178             # address() - use this function to set the address attibute of this object. This would be used to override the address attribute that is set when
179             # constructed or if no address was supplied when the object was constructed. Address passed in or if no argument specified currently
180             # set address attribute is returned.
181             sub address() {
182             my $self = shift;
183             my $address = shift;
184            
185             $self->{'ADDRESS'} = $address if defined $address;
186            
187             $self->decompressAddress();
188            
189             return $self->{'D_ADDRESS'};
190             }
191              
192             # addrressLength() - use this function to set the length attibute of this object. This would be used to override the length attribute that is set when
193             # constructed or if no length was supplied when the object was constructed. Length passed in or if no argument specified currently
194             # set length attribute is returned.
195             sub addressLength() {
196             my $self = shift;
197             my $addressLength = shift || $self->{'ADDRESSLENGTH'};
198            
199             $self->{'ADDRESSLENGTH'} = $addressLength if defined $addressLength;
200            
201             return $self->{'ADDRESSLENGTH'};
202             }
203              
204             # prefix() - use this function to retrieve the prefix for the supplied address given the prefix length that has been povided.
205             sub prefix() {
206             my $self = shift;
207             my $maxPrefixLength = 128;
208             my $diffLength = undef;
209            
210             $diffLength = $maxPrefixLength - $self->{'ADDRESSLENGTH'};
211            
212             $logger->message("Prefix length = $self->{'ADDRESSLENGTH'}");
213            
214             $self->hexToBin();
215            
216             $self->{'PREFIXBITS'} = substr $self->{'B_ADDRESS'}, 0, $self->{'ADDRESSLENGTH'};
217             $self->{'PREFIX'} = $self->binToHex($self->{'PREFIXBITS'});
218             $self->{'INTERFACEBITS'} = substr $self->{'B_ADDRESS'}, $self->{'ADDRESSLENGTH'}, $diffLength;
219             # $self->{'INTERFACE'} = $self->binToHex($self->{'INTERFACEBITS'});
220            
221             return $self->{'PREFIX'};
222             }
223              
224             # interface() - use this function to retrieve the interface identifier for the supplied address given the prefix length that has been povided.
225             sub interface() {
226             my $self = shift;
227             my $maxPrefixLength = 128;
228             my $diffLength = undef;
229            
230             $diffLength = $maxPrefixLength - $self->{'ADDRESSLENGTH'};
231            
232             $logger->message("Prefix length = $diffLength");
233            
234             $self->hexToBin();
235            
236             $self->{'PREFIXBITS'} = substr $self->{'B_ADDRESS'}, 0, $self->{'ADDRESSLENGTH'};
237             # $self->{'PREFIX'} = $self->binToHex($self->{'PREFIXBITS'});
238             $self->{'INTERFACEBITS'} = substr $self->{'B_ADDRESS'}, $self->{'ADDRESSLENGTH'}, $diffLength;
239             $self->{'INTERFACE'} = $self->binToHex($self->{'INTERFACEBITS'});
240            
241             return $self->{'INTERFACE'};
242             }
243              
244             # formatAddress() - properly formats an IPv6 address, if the address is compressed or abbreviated it will be uncompressed and unabbreviated
245             # then formatted and returned.
246             sub formatAddress() {
247             my $self = shift;
248             my $s_unformattedAddressLen = undef;
249             my @a_unformattedAddress = undef;
250             my $s_formattedAddress = undef;
251            
252             $logger->message("Formatting $self->{'D_ADDRESS'}");
253            
254             $s_unformattedAddressLen = length($self->{'D_ADDRESS'});
255             @a_unformattedAddress = split(//, $self->{'D_ADDRESS'});
256            
257             my $i = 0;
258             my $c = 0;
259             foreach my $x (@a_unformattedAddress) {
260             # $logger->message("Processing $x($i)[$c]");
261             if($i eq 3) {
262             $s_formattedAddress .= $x;
263             $s_formattedAddress .= ":" unless ($c >= 7);
264             $i = 0;
265             $c++;
266             # $logger->message("Added colon, reset counter to 1, c = $c");
267             } else {
268             $s_formattedAddress .= $x;
269             $i++;
270             }
271             # $i++;
272             }
273            
274             $self->{'F_ADDRESS'} = $s_formattedAddress;
275            
276             return $self->{'F_ADDRESS'};
277             }
278              
279             # toString() - converts an IPv6 address array to a string. The string is returned.
280             sub toString() {
281             my $self = shift;
282             my @a_address = shift;
283             my $s_address = undef;
284            
285             my $i = 0;
286             my $c = 0;
287             foreach my $x (@a_address) {
288             # $logger->message("Processing $x($i)[$c]");
289             if($i eq 3) {
290             $s_address .= $x;
291             $s_address .= ":" unless ($c >= 7);
292             $i = 0;
293             $c++;
294             # $logger->message("Added colon, reset counter to 1, c = $c");
295             } else {
296             $s_address .= $x;
297             $i++;
298             }
299             # $i++;
300             }
301            
302             return $s_address;
303             }
304              
305             # hexToBin() - converts a hexidecimal representation of an IPv6 address to its binary form. The binary representation is returned.
306             sub hexToBin() {
307             my $self = shift;
308             my $address = shift;
309             my $i = 0;
310             my $j = 0;
311             my $binaryprefix = undef;
312            
313             if($address) {
314             $logger->message("Converting hex to binary, $address");
315            
316             my @zzz = split(//, $address);
317             for my $y (@zzz) {
318             # $logger->message("Processing 4 bit element[$j] -> $y");
319             # my $buf = sprintf("%04i", $y);
320             my $buf = hex($y);
321             # $logger->message("Hex representation of $y -> $buf");
322             my $buf2 = sprintf("%04b", $buf);
323             $binaryprefix .= $buf2;
324             # $logger->message("Binary representation of $buf -> $buf2");
325             $j++;
326             }
327             $i++;
328            
329             # my $binaryprefixlen = length($binaryprefix);
330             # $logger->message("Length of binary data, $binaryprefixlen");
331            
332             $logger->message("Returning binary representation, $binaryprefix");
333            
334             return $binaryprefix;
335             } else {
336             $logger->message("Converting hex to binary, $self->{'D_ADDRESS'}");
337            
338             my @zzz = split(//, $self->{'D_ADDRESS'});
339             for my $y (@zzz) {
340             # $logger->message("Processing 4 bit element[$j] -> $y");
341             # my $buf = sprintf("%04i", $y);
342             my $buf = hex($y);
343             # $logger->message("Hex representation of $y -> $buf");
344             my $buf2 = sprintf("%04b", $buf);
345             $binaryprefix .= $buf2;
346             # $logger->message("Binary representation of $buf -> $buf2");
347             $j++;
348             }
349             $i++;
350            
351             # my $binaryprefixlen = length($binaryprefix);
352             # $logger->message("Length of binary data, $binaryprefixlen");
353            
354             $logger->message("Returning binary representation, $binaryprefix");
355            
356             $self->{'B_ADDRESS'} = $binaryprefix;
357            
358             return $self->{'B_ADDRESS'};
359             }
360             }
361              
362             # binToHex() - converts the binary representation of an IPv6 address to it hexidecimal form. The uncompresse and unabbbreviated hexidecimal
363             # representation is returned.
364             sub binToHex() {
365             my $self = shift;
366             my $bAddress = shift;
367             my $i = 0;
368             my $j = 0;
369             my $hex = undef;
370            
371             if($bAddress) {
372             my @bits = split(//, $bAddress);
373            
374             my $bitslen = length($bAddress);
375             my $offset = 0;
376             my $length = 4;
377             my $buf1 = undef;
378             my $buf2 = undef;
379            
380             $logger->message("Converting binary to hex, $bAddress");
381            
382             while($offset < ($bitslen)) {
383             # $logger->message("($i)offset = $offset, bitslen = $bitslen");
384             $buf1 = substr($bAddress, $offset, $length);
385             $buf2 = sprintf('%x', oct("0b$buf1"));
386             $hex .= $buf2;
387             # $logger->message("buf1 = $buf1, buf2 = $buf2");
388             $offset = $offset+4;
389             $i++
390             }
391            
392             $logger->message("Returning hexidecimal representation, $hex");
393            
394             return $hex;
395             } else {
396             my @bits = split(//, $self->{'B_ADDRESS'});
397            
398             my $bitslen = length($self->{'B_ADDRESS'});
399             my $offset = 0;
400             my $length = 4;
401             my $buf1 = undef;
402             my $buf2 = undef;
403            
404             $logger->message("Converting binary to hex, $self->{'B_ADDRESS'}");
405            
406             while($offset < ($bitslen)) {
407             # $logger->message("($i)offset = $offset, bitslen = $bitslen");
408             $buf1 = substr($self->{'B_ADDRESS'}, $offset, $length);
409             $buf2 = sprintf('%x', oct("0b$buf1"));
410             $hex .= $buf2;
411             # $logger->message("buf1 = $buf1, buf2 = $buf2");
412             $offset = $offset+4;
413             $i++
414             }
415            
416             $self->{'H_ADDRESS'} = $hex;
417              
418             $logger->message("Returning hexidecimal representation, $self->{'H_ADDRESS'}");
419            
420             return $self->{'H_ADDRESS'};
421             }
422             }
423              
424             # trim() - removes leading whitespace, tabs, spaces, carriage returns, and line feeds. The trimmed data is returned.
425             sub trim() {
426             my $self = shift;
427             my $buf = shift;
428            
429             if($buf) {
430             $buf =~ s/\+s//;
431             $buf =~ s/\r\n//;
432             $buf =~ s/\t//;
433             $buf =~ s/\s+//;
434             }
435            
436             return $buf;
437             }
438              
439             1;
440             __END__