File Coverage

blib/lib/NetPacket/IPX.pm
Criterion Covered Total %
statement 50 50 100.0
branch 7 14 50.0
condition 3 9 33.3
subroutine 11 11 100.0
pod 3 4 75.0
total 74 88 84.0


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