File Coverage

blib/lib/NetPacket/IPX.pm
Criterion Covered Total %
statement 51 51 100.0
branch 7 14 50.0
condition 3 9 33.3
subroutine 12 12 100.0
pod 3 4 75.0
total 76 90 84.4


line stmt bran cond sub pod time code
1             package NetPacket::IPX;
2             BEGIN {
3 1     1   837 $NetPacket::IPX::AUTHORITY = 'cpan:YANICK';
4             }
5             # ABSTRACT: Assemble and disassemble IPX packets
6             $NetPacket::IPX::VERSION = '1.6.0';
7 1     1   7 use strict;
  1         1  
  1         29  
8 1     1   3 use warnings;
  1         1  
  1         35  
9              
10 1     1   420 use parent qw(NetPacket);
  1         253  
  1         5  
11              
12 1     1   36 use Carp;
  1         1  
  1         771  
13              
14             sub new
15             {
16 1     1 1 2742 my ($class, %packet) = @_;
17            
18 1         3 foreach my $key(qw(tc type dest_network dest_node dest_socket
19             src_network src_node src_socket data))
20             {
21 9 50       15 croak("Missing $key argument") unless(defined($packet{$key}));
22             }
23            
24 1 50 33     14 croak("Invalid tc argument") unless($packet{tc} =~ m/^\d+$/ && $packet{tc} <= 255);
25 1 50 33     10 croak("Invalid type argument") unless($packet{type} =~ m/^\d+$/ && $packet{type} <= 255);
26            
27 1         3 _check_address("destination", $packet{dest_network}, $packet{dest_node}, $packet{dest_socket});
28 1         22 _check_address("source", $packet{src_network}, $packet{src_node}, $packet{src_socket});
29            
30 1         3 return bless(\%packet, $class);
31             }
32              
33             sub _check_address
34             {
35 2     2   3 my ($direction, $network, $node, $socket) = @_;
36            
37 2         6 my $OCTET = qr/[0-9A-F][0-9A-F]?/i;
38            
39 2 50       49 croak("Invalid $direction network") unless($network =~ m/^$OCTET(:$OCTET){3}$/);
40 2 50       25 croak("Invalid $direction node") unless($node =~ m/^$OCTET(:$OCTET){5}$/);
41 2 50 33     13 croak("Invalid $direction socket") unless($socket =~ m/^\d+$/ && $socket <= 65535);
42             }
43              
44             #
45             # Decode the packet
46             #
47              
48             sub decode
49             {
50 2     2 1 339 my ($class, $pkt, $parent) = @_;
51            
52 2         7 my $self = bless({
53             _parent => $parent,
54             _frame => $pkt,
55             }, $class);
56            
57 2 50       6 if(defined($pkt))
58             {
59             # Use array slices to capture the appropriate number of bytes
60             # from each address field.
61            
62             my (
63 2         2 $checksum, $length, $tc, $type,
64             @dst_network, @dst_node, $dst_socket,
65             @src_network, @src_node, $src_socket,
66             );
67            
68             (
69 2         20 $checksum, $length, $tc, $type,
70             @dst_network[0..3], @dst_node[0..5], $dst_socket,
71             @src_network[0..3], @src_node[0..5], $src_socket,
72             ) = unpack("nnCC C4C6n C4C6n", $pkt);
73            
74 2         9 $self->{tc} = $tc;
75 2         1 $self->{type} = $type;
76            
77 2         5 $self->{dest_network} = _addr_to_string(@dst_network);
78 2         4 $self->{dest_node} = _addr_to_string(@dst_node);
79 2         3 $self->{dest_socket} = $dst_socket;
80            
81 2         3 $self->{src_network} = _addr_to_string(@src_network);
82 2         4 $self->{src_node} = _addr_to_string(@src_node);
83 2         4 $self->{src_socket} = $src_socket;
84            
85 2         5 $self->{data} = substr($pkt, 30);
86             }
87            
88 2         6 return $self;
89             }
90              
91             #
92             # Strip header from packet and return the data contained in it
93             #
94              
95             sub strip {
96 1     1 0 290 my ($pkt) = @_;
97 1         4 return NetPacket::IPX->decode($pkt)->{data};
98             }
99              
100             #
101             # Encode a packet
102             #
103              
104             sub encode
105             {
106 1     1 1 241 my ($self) = @_;
107            
108 1         8 return pack("nnCC", 0xFFFF, 30 + length($self->{data}), $self->{tc}, $self->{type})
109             ._addr_from_string($self->{dest_network})
110             ._addr_from_string($self->{dest_node})
111             .pack("n", $self->{dest_socket})
112             ._addr_from_string($self->{src_network})
113             ._addr_from_string($self->{src_node})
114             .pack("n", $self->{src_socket})
115             .$self->{data};
116             }
117              
118             sub _addr_to_string
119             {
120 8     8   8 my (@bytes) = @_;
121 8         6 return join(":", map { sprintf("%02X", $_) } @bytes);
  40         61  
122             }
123              
124             sub _addr_from_string
125             {
126 4     4   4 my ($string) = @_;
127 4         435 return join("", map { pack("C", hex($_)) } split(m/:/, $string));
  20         38  
128             }
129              
130             1;
131              
132             __END__