File Coverage

blib/lib/Net/Frame/Layer/OSPF.pm
Criterion Covered Total %
statement 144 194 74.2
branch 6 46 13.0
condition 1 30 3.3
subroutine 43 49 87.7
pod 8 9 88.8
total 202 328 61.5


line stmt bran cond sub pod time code
1             #
2             # $Id: OSPF.pm,v 1.11 2007/03/09 08:41:11 gomor Exp $
3             #
4             package Net::Frame::Layer::OSPF;
5 2     2   7563 use strict;
  2         2  
  2         44  
6 2     2   6 use warnings;
  2         1  
  2         70  
7              
8             our $VERSION = '1.00_01';
9              
10 2     2   769 use Net::Frame::Layer qw(:consts :subs);
  2         95832  
  2         556  
11             require Exporter;
12             our @ISA = qw(Net::Frame::Layer Exporter);
13              
14             our %EXPORT_TAGS = (
15             consts => [qw(
16             NF_OSPF_HDR_LEN
17             NF_OSPF_AUTH_TYPE_NULL
18             NF_OSPF_TYPE_HELLO
19             NF_OSPF_TYPE_DATABASEDESC
20             NF_OSPF_TYPE_LINKSTATEREQUEST
21             NF_OSPF_TYPE_LINKSTATEUPDATE
22             NF_OSPF_TYPE_LINKSTATEACK
23             NF_OSPF_AUTHTYPE_NULL
24             NF_OSPF_AUTHTYPE_SIMPLE
25             NF_OSPF_AUTHTYPE_CRYPTO
26             NF_OSPF_LSA_HDR_LEN
27             NF_OSPF_LSTYPE_ROUTER
28             NF_OSPF_LSTYPE_NETWORK
29             NF_OSPF_LSTYPE_SUMMARYIP
30             NF_OSPF_LSTYPE_SUMMARYASBR
31             NF_OSPF_LSTYPE_ASEXTERNAL
32             NF_OSPF_LSTYPE_OPAQUELINKLOCAL
33             NF_OSPF_LSTYPE_OPAQUEAREALOCAL
34             NF_OSPF_LSTYPE_OPAQUEDOMAIN
35             NF_OSPF_HELLO_OPTIONS_UNK
36             NF_OSPF_HELLO_OPTIONS_E
37             NF_OSPF_HELLO_OPTIONS_MC
38             NF_OSPF_HELLO_OPTIONS_NP
39             NF_OSPF_HELLO_OPTIONS_EA
40             NF_OSPF_HELLO_OPTIONS_DC
41             NF_OSPF_HELLO_OPTIONS_O
42             NF_OSPF_HELLO_OPTIONS_DN
43             NF_OSPF_DATABASEDESC_OPTIONS_DN
44             NF_OSPF_DATABASEDESC_OPTIONS_0
45             NF_OSPF_DATABASEDESC_OPTIONS_DC
46             NF_OSPF_DATABASEDESC_OPTIONS_L
47             NF_OSPF_DATABASEDESC_OPTIONS_NP
48             NF_OSPF_DATABASEDESC_OPTIONS_MC
49             NF_OSPF_DATABASEDESC_OPTIONS_E
50             NF_OSPF_DATABASEDESC_FLAGS_MS
51             NF_OSPF_DATABASEDESC_FLAGS_M
52             NF_OSPF_DATABASEDESC_FLAGS_I
53             )],
54             );
55             our @EXPORT_OK = (
56             @{$EXPORT_TAGS{consts}},
57             );
58              
59 2     2   11 use constant NF_OSPF_HDR_LEN => 24;
  2         3  
  2         85  
60 2     2   7 use constant NF_OSPF_AUTH_TYPE_NULL => 0x0000;
  2         2  
  2         70  
61              
62 2     2   5 use constant NF_OSPF_TYPE_HELLO => 0x01;
  2         2  
  2         64  
63 2     2   6 use constant NF_OSPF_TYPE_DATABASEDESC => 0x02;
  2         2  
  2         60  
64 2     2   6 use constant NF_OSPF_TYPE_LINKSTATEREQUEST => 0x03;
  2         2  
  2         76  
65 2     2   5 use constant NF_OSPF_TYPE_LINKSTATEUPDATE => 0x04;
  2         3  
  2         59  
66 2     2   15 use constant NF_OSPF_TYPE_LINKSTATEACK => 0x05;
  2         3  
  2         68  
67              
68 2     2   6 use constant NF_OSPF_AUTHTYPE_NULL => 0x00;
  2         2  
  2         62  
69 2     2   6 use constant NF_OSPF_AUTHTYPE_SIMPLE => 0x01;
  2         2  
  2         60  
70 2     2   6 use constant NF_OSPF_AUTHTYPE_CRYPTO => 0x02;
  2         2  
  2         69  
71              
72 2     2   10 use constant NF_OSPF_LSA_HDR_LEN => 20;
  2         1  
  2         63  
73              
74 2     2   6 use constant NF_OSPF_LSTYPE_ROUTER => 0x01;
  2         0  
  2         72  
75 2     2   6 use constant NF_OSPF_LSTYPE_NETWORK => 0x02;
  2         2  
  2         58  
76 2     2   6 use constant NF_OSPF_LSTYPE_SUMMARYIP => 0x03;
  2         2  
  2         62  
77 2     2   6 use constant NF_OSPF_LSTYPE_SUMMARYASBR => 0x04;
  2         2  
  2         61  
78 2     2   6 use constant NF_OSPF_LSTYPE_ASEXTERNAL => 0x05;
  2         1  
  2         56  
79 2     2   5 use constant NF_OSPF_LSTYPE_OPAQUELINKLOCAL => 0x0a;
  2         1  
  2         70  
80 2     2   7 use constant NF_OSPF_LSTYPE_OPAQUEAREALOCAL => 0x0b;
  2         1  
  2         63  
81 2     2   8 use constant NF_OSPF_LSTYPE_OPAQUEDOMAIN => 0x0c;
  2         2  
  2         94  
82              
83 2     2   7 use constant NF_OSPF_HELLO_OPTIONS_UNK => 0x01; # Not in RFC 2328
  2         2  
  2         67  
84 2     2   6 use constant NF_OSPF_HELLO_OPTIONS_E => 0x02;
  2         2  
  2         58  
85 2     2   4 use constant NF_OSPF_HELLO_OPTIONS_MC => 0x04;
  2         2  
  2         60  
86 2     2   5 use constant NF_OSPF_HELLO_OPTIONS_NP => 0x08;
  2         2  
  2         61  
87 2     2   5 use constant NF_OSPF_HELLO_OPTIONS_EA => 0x10;
  2         4  
  2         63  
88 2     2   6 use constant NF_OSPF_HELLO_OPTIONS_DC => 0x20;
  2         0  
  2         65  
89 2     2   6 use constant NF_OSPF_HELLO_OPTIONS_O => 0x40; # Not in RFC 2328
  2         0  
  2         71  
90 2     2   6 use constant NF_OSPF_HELLO_OPTIONS_DN => 0x80; # Not in RFC 2328
  2         2  
  2         69  
91              
92 2     2   6 use constant NF_OSPF_DATABASEDESC_OPTIONS_DN => 0x01;
  2         11  
  2         64  
93 2     2   6 use constant NF_OSPF_DATABASEDESC_OPTIONS_0 => 0x02;
  2         0  
  2         58  
94 2     2   4 use constant NF_OSPF_DATABASEDESC_OPTIONS_DC => 0x04;
  2         7  
  2         59  
95 2     2   6 use constant NF_OSPF_DATABASEDESC_OPTIONS_L => 0x08;
  2         2  
  2         59  
96 2     2   5 use constant NF_OSPF_DATABASEDESC_OPTIONS_NP => 0x10;
  2         11  
  2         75  
97 2     2   8 use constant NF_OSPF_DATABASEDESC_OPTIONS_MC => 0x20;
  2         3  
  2         67  
98 2     2   7 use constant NF_OSPF_DATABASEDESC_OPTIONS_E => 0x40;
  2         1  
  2         65  
99              
100 2     2   6 use constant NF_OSPF_DATABASEDESC_FLAGS_MS => 0x01;
  2         2  
  2         67  
101 2     2   7 use constant NF_OSPF_DATABASEDESC_FLAGS_M => 0x02;
  2         0  
  2         73  
102 2     2   7 use constant NF_OSPF_DATABASEDESC_FLAGS_I => 0x04;
  2         2  
  2         1489  
103              
104             our @AS = qw(
105             version
106             type
107             length
108             routerId
109             areaId
110             checksum
111             authType
112             authData
113             packet
114             );
115             __PACKAGE__->cgBuildIndices;
116             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
117              
118             require Net::Frame::Layer::OSPF::Hello;
119             require Net::Frame::Layer::OSPF::DatabaseDesc;
120             require Net::Frame::Layer::OSPF::LinkStateUpdate;
121             require Net::Frame::Layer::OSPF::LinkStateRequest;
122             require Net::Frame::Layer::OSPF::LinkStateAck;
123             require Net::Frame::Layer::OSPF::Lls;
124              
125             sub new {
126             shift->SUPER::new(
127 1     1 1 19 version => 2,
128             type => 0,
129             length => NF_OSPF_HDR_LEN,
130             routerId => '127.0.0.1',
131             areaId => '127.0.0.1',
132             checksum => 0,
133             authType => NF_OSPF_AUTH_TYPE_NULL,
134             authData => "0000000000000000",
135             @_,
136             );
137             }
138              
139             sub match {
140 0     0 0 0 my $self = shift;
141 0         0 my ($with) = @_;
142 0 0 0     0 if ($self->packet && $with->packet) {
143 0         0 my $s = $self->packet->layer;
144 0         0 my $sHdr = $self->packet;
145 0         0 my $w = $with->packet->layer;
146 0         0 my $wHdr = $with->packet;
147 0 0 0     0 if (($s eq 'OSPF::Hello') && ($w eq 'OSPF::DatabaseDesc')) {
    0 0        
    0 0        
148 0         0 return 1;
149             }
150             elsif (($s eq 'OSPF::DatabaseDesc') && ($w eq 'OSPF::DatabaseDesc')) {
151 0 0 0     0 if ($sHdr->flags == 0x07 && $wHdr->flags == 0x02) {
    0 0        
    0 0        
152 0         0 return 1;
153             }
154             elsif ($sHdr->flags == 0x03 && $wHdr->flags == 0x00) {
155 0         0 return 1;
156             }
157             elsif ($sHdr->flags == 0x01 && $wHdr->flags == 0x00) {
158 0         0 return 1;
159             }
160             }
161             elsif (($s eq 'OSPF::LinkStateRequest')
162             && ($w eq 'OSPF::LinkStateRequest')) {
163 0         0 return 1;
164             }
165             }
166 0         0 0;
167             }
168              
169 0     0 1 0 sub getLength { shift->length }
170              
171             sub computeLengths {
172 0     0 1 0 my $self = shift;
173 0         0 my $len = $self->getLength;
174              
175             # If packet is not a ref, it is not an object, but a raw data (LinkStateAck)
176 0 0 0     0 if ($self->packet && ! ref($self->packet)) {
    0          
177 0         0 $len += length($self->packet);
178             }
179             # Else, standard object
180             elsif ($self->packet) {
181 0         0 $len += $self->packet->getLength;
182             }
183 0         0 $self->length($len);
184             }
185              
186             sub computeChecksums {
187 0     0 1 0 my $self = shift;
188              
189 0         0 $self->checksum(0);
190 0         0 $self->checksum(inetChecksum($self->pack));
191             }
192              
193             sub pack {
194 1     1 1 263 my $self = shift;
195              
196 1 50       4 my $raw = $self->SUPER::pack('CCna4a4nnH16',
197             $self->version, $self->type, $self->length,
198             inetAton($self->routerId), inetAton($self->areaId),
199             $self->checksum, $self->authType, $self->authData,
200             ) or return undef;
201              
202 1 50 33     89 if ($self->packet && ref($self->packet)) {
    50          
203 0         0 $raw .= $self->packet->pack;
204             }
205             elsif ($self->packet) {
206 0         0 $raw .= $self->packet;
207             }
208              
209 1         20 $self->raw($raw);
210             }
211              
212             sub unpack {
213 1     1 1 9 my $self = shift;
214              
215 1 50       3 my ($version, $type, $length, $routerId, $areaId, $checksum,
216             $authType, $authData, $payload) =
217             $self->SUPER::unpack('CCna4a4nnH16 a*', $self->raw)
218             or return undef;
219              
220 1         30 $self->version($version);
221 1         6 $self->type($type);
222 1         7 $self->length($length);
223 1         7 $self->routerId(inetNtoa($routerId));
224 1         11 $self->areaId(inetNtoa($areaId));
225 1         10 $self->checksum($checksum);
226 1         5 $self->authType($authType);
227 1         6 $self->authData($authData);
228              
229 1         5 my $keep = $length - NF_OSPF_HDR_LEN;
230 1         2 my $tail = substr($payload, 0, $keep);
231 1         2 $payload = substr($payload, $keep);
232              
233             # Handle type of OSPF frame
234 1         1 my $next;
235 1 50       2 if ($tail) {
236 0 0       0 if ($type == NF_OSPF_TYPE_HELLO) {
    0          
    0          
    0          
    0          
237 0         0 $next = Net::Frame::Layer::OSPF::Hello->new(raw => $tail);
238             }
239             elsif ($type == NF_OSPF_TYPE_DATABASEDESC) {
240 0         0 $next = Net::Frame::Layer::OSPF::DatabaseDesc->new(raw => $tail);
241             }
242             elsif ($type == NF_OSPF_TYPE_LINKSTATEUPDATE) {
243 0         0 $next = Net::Frame::Layer::OSPF::LinkStateUpdate->new(raw => $tail);
244             }
245             elsif ($type == NF_OSPF_TYPE_LINKSTATEREQUEST) {
246 0         0 $next = Net::Frame::Layer::OSPF::LinkStateRequest->new(raw => $tail);
247             }
248             elsif ($type == NF_OSPF_TYPE_LINKSTATEACK) {
249 0         0 $next = Net::Frame::Layer::OSPF::LinkStateAck->new(raw => $tail);
250             }
251             }
252              
253 1 50       3 if ($next) {
254 0         0 $next->unpack;
255 0         0 $next->payload($next->payload.$payload);
256 0         0 $self->packet($next);
257 0         0 $payload = $next->payload;
258              
259             # Handle special options for OSPF::Hello frame
260 0 0       0 if ($next->layer eq 'OSPF::Hello') {
261 0 0       0 if ($next->options & NF_OSPF_HELLO_OPTIONS_EA) {
262 0         0 my $lls = Net::Frame::Layer::OSPF::Lls->new(raw => $payload);
263 0         0 $lls->unpack;
264 0         0 $next->lls($lls);
265 0         0 $payload = $lls->payload;
266             }
267             }
268             }
269             else {
270 1         2 $payload = $tail.$payload;
271             }
272              
273 1         5 $self->payload($payload);
274              
275 1         7 $self;
276             }
277              
278 0     0 1   sub encapsulate { shift->nextLayer }
279              
280             sub print {
281 0     0 1   my $self = shift;
282              
283 0           my $l = $self->layer;
284 0           my $buf = sprintf "$l: version:%d type:0x%02x length:%d\n".
285             "$l: routerId:%s areaId:%s\n".
286             "$l: checksum:0x%04x authType:0x%04x\n".
287             "$l: authData:%s",
288             $self->version, $self->type, $self->length,
289             $self->routerId, $self->areaId, $self->checksum,
290             $self->authType, $self->authData;
291              
292 0 0 0       if ($self->packet && ref($self->packet)) {
293 0           $buf .= "\n".$self->packet->print;
294             }
295              
296 0           $buf;
297             }
298              
299             1;
300              
301             __END__