File Coverage

blib/lib/Net/Frame/Layer/IGMP.pm
Criterion Covered Total %
statement 69 108 63.8
branch 8 40 20.0
condition 0 9 0.0
subroutine 20 26 76.9
pod 12 12 100.0
total 109 195 55.9


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   24662 use strict; use warnings;
  5     5   11  
  5         114  
  5         21  
  5         10  
  5         182  
6              
7             our $VERSION = '1.02';
8              
9 5     5   2062 use Net::Frame::Layer qw(:consts :subs);
  5         268613  
  5         1116  
10 5     5   49 use Exporter;
  5         11  
  5         398  
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   28 use constant NF_IGMP_ALLIGMPRTRS => '224.0.0.22';
  5         10  
  5         235  
30 5     5   27 use constant NF_IGMP_ALLIGMPRTRS_MAC => '01:00:5e:00:00:16';
  5         10  
  5         176  
31 5     5   26 use constant NF_IGMP_TYPE_QUERY => 0x11;
  5         10  
  5         166  
32 5     5   25 use constant NF_IGMP_TYPE_DVMRP => 0x13;
  5         27  
  5         171  
33 5     5   24 use constant NF_IGMP_TYPE_REPORTv1 => 0x12;
  5         10  
  5         196  
34 5     5   40 use constant NF_IGMP_TYPE_REPORTv2 => 0x16;
  5         9  
  5         178  
35 5     5   25 use constant NF_IGMP_TYPE_REPORTv3 => 0x22;
  5         9  
  5         178  
36 5     5   23 use constant NF_IGMP_TYPE_LEAVE => 0x17;
  5         13  
  5         337  
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   2631 use Net::Frame::Layer::IGMP::v3Query;
  5         12  
  5         198  
51 5     5   1775 use Net::Frame::Layer::IGMP::v3Report qw(:consts);
  5         13  
  5         4050  
52              
53             sub new {
54             shift->SUPER::new(
55 6     6 1 930 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 v3query {
66 0     0 1 0 return new(@_)
67             }
68              
69             sub v3report {
70             shift->SUPER::new(
71 1     1 1 6 type => NF_IGMP_TYPE_REPORTv3,
72             maxResp => 0,
73             checksum => 0,
74             reserved => 0,
75             numGroupRecs => 0,
76             @_,
77             );
78             }
79              
80             sub match {
81 0     0 1 0 my $self = shift;
82 0         0 my ($with) = @_;
83 0         0 my $sType = $self->type;
84 0         0 my $wType = $with->type;
85 0 0 0     0 if ($sType eq NF_IGMP_TYPE_QUERY
      0        
86             && ( ($wType eq NF_IGMP_TYPE_REPORTv1)
87             || ($wType eq NF_IGMP_TYPE_REPORTv2)
88             || ($wType eq NF_IGMP_TYPE_REPORTv3)) ) {
89 0         0 return 1;
90             }
91 0         0 0;
92             }
93              
94             # XXX: may be better, by keying on type also
95 0     0 1 0 sub getKey { shift->layer }
96 0     0 1 0 sub getKeyReverse { shift->layer }
97              
98 0     0 1 0 sub getLength { 8 }
99              
100             sub pack {
101 1     1 1 316 my $self = shift;
102              
103 1         2 my $raw;
104 1 50       5 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
105 0 0       0 $raw = $self->SUPER::pack('CCnnn',
106             $self->type,
107             $self->maxResp,
108             $self->checksum,
109             $self->reserved,
110             $self->numGroupRecs
111             ) or return;
112             } else {
113 1 50       25 $raw = $self->SUPER::pack('CCna4',
114             $self->type,
115             $self->maxResp,
116             $self->checksum,
117             inetAton($self->groupAddress)
118             ) or return;
119             }
120              
121 1         64 return $self->raw($raw);
122             }
123              
124             sub unpack {
125 1     1 1 15 my $self = shift;
126              
127 1 50       4 my ($type, $maxResp, $checksum, $groupAddress, $payload) =
128             $self->SUPER::unpack('CCna4 a*', $self->raw)
129             or return;
130              
131 1         37 $self->type($type);
132 1         11 $self->maxResp($maxResp);
133 1         10 $self->checksum($checksum);
134            
135 1 50       11 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
136 0         0 $self->reserved(unpack "n", (substr $groupAddress, 0, 2));
137 0         0 $self->numGroupRecs(unpack "n", (substr $groupAddress, 2, 2));
138             } else {
139 1         20 $self->groupAddress(inetNtoa($groupAddress))
140             }
141              
142 1         21 $self->payload($payload);
143              
144 1         10 return $self;
145             }
146              
147             sub computeChecksums {
148 0     0 1 0 my $self = shift;
149 0         0 my ($layers) = @_;
150              
151 0         0 my $phpkt;
152 0 0       0 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
153 0 0       0 $phpkt .= $self->SUPER::pack('CCnnn',
154             $self->type, $self->maxResp, 0, $self->reserved, $self->numGroupRecs)
155             or return;
156             } else {
157 0 0       0 $phpkt .= $self->SUPER::pack('CCna4',
158             $self->type, $self->maxResp, 0, inetAton($self->groupAddress))
159             or return;
160             }
161              
162 0         0 my $start = 0;
163 0         0 my $last = $self;
164 0         0 my $payload = '';
165 0         0 for my $l (@$layers) {
166 0         0 $last = $l;
167 0 0       0 if (! $start) {
168 0 0       0 $start++ if $l->layer eq 'IGMP';
169 0         0 next;
170             }
171 0         0 $payload .= $l->pack;
172             }
173              
174 0 0 0     0 if (defined($last->payload) && length($last->payload)) {
175 0         0 $payload .= $last->payload;
176             }
177              
178 0 0       0 if (length($payload)) {
179 0 0       0 $phpkt .= $self->SUPER::pack('a*', $payload)
180             or return;
181             }
182              
183 0         0 $self->checksum(inetChecksum($phpkt));
184              
185 0         0 return 1;
186             }
187              
188             sub encapsulate {
189 1     1 1 10 my $self = shift;
190              
191 1 50       8 return $self->nextLayer if $self->nextLayer;
192              
193 1 50       18 if ($self->payload) {
194 0 0       0 if ($self->type == 0x11) {
    0          
    0          
195 0         0 return 'IGMP::v3Query';
196             } elsif ($self->type == 0x22) {
197 0         0 return 'IGMP::v3Report';
198             } elsif ($self->type == 0x13) {
199 0         0 return 'DVMRP';
200             }
201             }
202              
203 1         11 NF_LAYER_NONE;
204             }
205              
206             sub print {
207 13     13 1 1522 my $self = shift;
208              
209 13         56 my $l = $self->layer;
210 13         159 my $buf = sprintf
211             "$l: type:0x%02x maxResp:%d checksum:0x%04x\n",
212             $self->type, $self->maxResp, $self->checksum;
213              
214 13 100       426 if ($self->type == NF_IGMP_TYPE_REPORTv3) {
215 2         23 $buf .= sprintf
216             "$l: reserved:%d numGroupRecs:%d",
217             $self->reserved, $self->numGroupRecs;
218             } else {
219 11         148 $buf .= sprintf
220             "$l: groupAddress:%s",
221             $self->groupAddress;
222             }
223              
224 13         1590 return $buf;
225             }
226              
227             1;
228              
229             __END__