File Coverage

blib/lib/Net/Frame/Layer/IGMP.pm
Criterion Covered Total %
statement 69 98 70.4
branch 8 38 21.0
condition 0 3 0.0
subroutine 20 22 90.9
pod 8 8 100.0
total 105 169 62.1


line stmt bran cond sub pod time code
1             #
2             # $Id: IGMP.pm 49 2009-05-31 13:15:34Z VinsWorldcom $
3             #
4             package Net::Frame::Layer::IGMP;
5 5     5   73430 use strict; use warnings;
  5     5   14  
  5         197  
  5         27  
  5         11  
  5         259  
6              
7             our $VERSION = '1.01';
8              
9 5     5   17189 use Net::Frame::Layer qw(:consts :subs);
  5         444398  
  5         8255  
10 5     5   230 use Exporter;
  5         15  
  5         506  
11             our @ISA = qw(Net::Frame::Layer Exporter);
12              
13             our %EXPORT_TAGS = (
14             consts => [qw(
15             NF_IGMP_ALLIGMPRTRS
16             NF_IGMP_ALLIGMPRTRS_MAC
17             NF_IGMP_TYPE_QUERY
18             NF_IGMP_TYPE_DVMRP
19             NF_IGMP_TYPE_REPORTv1
20             NF_IGMP_TYPE_REPORTv2
21             NF_IGMP_TYPE_REPORTv3
22             NF_IGMP_TYPE_LEAVE
23             )],
24             );
25             our @EXPORT_OK = (
26             @{$EXPORT_TAGS{consts}},
27             );
28              
29 5     5   87 use constant NF_IGMP_ALLIGMPRTRS => '224.0.0.22';
  5         10  
  5         283  
30 5     5   25 use constant NF_IGMP_ALLIGMPRTRS_MAC => '01:00:5e:00:00:16';
  5         8  
  5         244  
31 5     5   24 use constant NF_IGMP_TYPE_QUERY => 0x11;
  5         11  
  5         220  
32 5     5   25 use constant NF_IGMP_TYPE_DVMRP => 0x13;
  5         11  
  5         217  
33 5     5   25 use constant NF_IGMP_TYPE_REPORTv1 => 0x12;
  5         10  
  5         214  
34 5     5   60 use constant NF_IGMP_TYPE_REPORTv2 => 0x16;
  5         30  
  5         221  
35 5     5   25 use constant NF_IGMP_TYPE_REPORTv3 => 0x22;
  5         9  
  5         522  
36 5     5   26 use constant NF_IGMP_TYPE_LEAVE => 0x17;
  5         9  
  5         442  
37              
38             our @AS = qw(
39             type
40             maxResp
41             checksum
42             groupAddress
43             reserved
44             numGroupRecs
45             );
46             __PACKAGE__->cgBuildIndices;
47             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
48              
49             #no strict 'vars';
50 5     5   5471 use Net::Frame::Layer::IGMP::v3Query;
  5         16  
  5         1097  
51 5     5   3716 use Net::Frame::Layer::IGMP::v3Report qw(:consts);
  5         15  
  5         5833  
52              
53             sub new {
54             shift->SUPER::new(
55 6     6 1 1793 type => NF_IGMP_TYPE_QUERY,
56             maxResp => 0,
57             checksum => 0,
58             groupAddress => '0.0.0.0',
59             reserved => 0,
60             numGroupRecs => 0,
61             @_,
62             );
63             }
64              
65             sub v3report {
66             shift->SUPER::new(
67 1     1 1 7 type => NF_IGMP_TYPE_REPORTv3,
68             maxResp => 0,
69             checksum => 0,
70             reserved => 0,
71             numGroupRecs => 0,
72             @_,
73             );
74             }
75              
76 0     0 1 0 sub getLength { 8 }
77              
78             sub pack {
79 1     1 1 302 my $self = shift;
80              
81 1         3 my $raw;
82 1 50       5 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
83 0 0       0 $raw = $self->SUPER::pack('CCnnn',
84             $self->type,
85             $self->maxResp,
86             $self->checksum,
87             $self->reserved,
88             $self->numGroupRecs
89             ) or return;
90             } else {
91 1 50       31 $raw = $self->SUPER::pack('CCna4',
92             $self->type,
93             $self->maxResp,
94             $self->checksum,
95             inetAton($self->groupAddress)
96             ) or return;
97             }
98              
99 1         89 return $self->raw($raw);
100             }
101              
102             sub unpack {
103 1     1 1 14 my $self = shift;
104              
105 1 50       4 my ($type, $maxResp, $checksum, $groupAddress, $payload) =
106             $self->SUPER::unpack('CCna4 a*', $self->raw)
107             or return;
108              
109 1         34 $self->type($type);
110 1         12 $self->maxResp($maxResp);
111 1         10 $self->checksum($checksum);
112            
113 1 50       11 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
114 0         0 $self->reserved(unpack "n", (substr $groupAddress, 0, 2));
115 0         0 $self->numGroupRecs(unpack "n", (substr $groupAddress, 2, 2));
116             } else {
117 1         18 $self->groupAddress(inetNtoa($groupAddress))
118             }
119              
120 1         23 $self->payload($payload);
121              
122 1         10 return $self;
123             }
124              
125             sub computeChecksums {
126 0     0 1 0 my $self = shift;
127 0         0 my ($layers) = @_;
128              
129 0         0 my $phpkt;
130 0 0       0 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
131 0 0       0 $phpkt .= $self->SUPER::pack('CCnnn',
132             $self->type, $self->maxResp, 0, $self->reserved, $self->numGroupRecs)
133             or return;
134             } else {
135 0 0       0 $phpkt .= $self->SUPER::pack('CCna4',
136             $self->type, $self->maxResp, 0, inetAton($self->groupAddress))
137             or return;
138             }
139              
140 0         0 my $start = 0;
141 0         0 my $last = $self;
142 0         0 my $payload = '';
143 0         0 for my $l (@$layers) {
144 0         0 $last = $l;
145 0 0       0 if (! $start) {
146 0 0       0 $start++ if $l->layer eq 'IGMP';
147 0         0 next;
148             }
149 0         0 $payload .= $l->pack;
150             }
151              
152 0 0 0     0 if (defined($last->payload) && length($last->payload)) {
153 0         0 $payload .= $last->payload;
154             }
155              
156 0 0       0 if (length($payload)) {
157 0 0       0 $phpkt .= $self->SUPER::pack('a*', $payload)
158             or return;
159             }
160              
161 0         0 $self->checksum(inetChecksum($phpkt));
162              
163 0         0 return 1;
164             }
165              
166             sub encapsulate {
167 1     1 1 8 my $self = shift;
168              
169 1 50       11 return $self->nextLayer if $self->nextLayer;
170              
171 1 50       21 if ($self->payload) {
172 0 0       0 if ($self->type == 0x11) {
    0          
    0          
173 0         0 return 'IGMP::v3Query';
174             } elsif ($self->type == 0x22) {
175 0         0 return 'IGMP::v3Report';
176             } elsif ($self->type == 0x13) {
177 0         0 return 'DVMRP';
178             }
179             }
180              
181 1         14 NF_LAYER_NONE;
182             }
183              
184             sub print {
185 13     13 1 1402 my $self = shift;
186              
187 13         55 my $l = $self->layer;
188 13         139 my $buf = sprintf
189             "$l: type:0x%02x maxResp:%d checksum:0x%04x\n",
190             $self->type, $self->maxResp, $self->checksum;
191              
192 13 100       526 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
193 2         27 $buf .= sprintf
194             "$l: reserved:%d numGroupRecs:%d",
195             $self->reserved, $self->numGroupRecs;
196             } else {
197 11         131 $buf .= sprintf
198             "$l: groupAddress:%s",
199             $self->groupAddress;
200             }
201              
202 13         2292 return $buf;
203             }
204              
205             1;
206              
207             __END__