File Coverage

blib/lib/Net/Frame/Layer/OSPF/Lsa.pm
Criterion Covered Total %
statement 32 86 37.2
branch 5 30 16.6
condition 1 9 11.1
subroutine 7 11 63.6
pod 7 7 100.0
total 52 143 36.3


line stmt bran cond sub pod time code
1             #
2             # $Id: Lsa.pm,v 1.8 2007/03/05 08:47:03 gomor Exp $
3             #
4             package Net::Frame::Layer::OSPF::Lsa;
5 2     2   6 use strict;
  2         2  
  2         43  
6 2     2   4 use warnings;
  2         2  
  2         45  
7              
8 2     2   6 use Net::Frame::Layer qw(:consts :subs);
  2         2  
  2         311  
9             our @ISA = qw(Net::Frame::Layer);
10              
11             our @AS = qw(
12             lsAge
13             options
14             lsType
15             linkStateId
16             advertisingRouter
17             lsSequenceNumber
18             lsChecksum
19             length
20             lsa
21             full
22             );
23             __PACKAGE__->cgBuildIndices;
24             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
25              
26 2     2   8 use Net::Frame::Layer::OSPF qw(:consts);
  2         2  
  2         1491  
27             require Net::Frame::Layer::OSPF::Lsa::Opaque;
28             require Net::Frame::Layer::OSPF::Lsa::Router;
29             require Net::Frame::Layer::OSPF::Lsa::Network;
30             require Net::Frame::Layer::OSPF::Lsa::SummaryIp;
31              
32             sub new {
33             shift->SUPER::new(
34 1     1 1 12 lsAge => 30,
35             options => 0,
36             lsType => NF_OSPF_LSTYPE_ROUTER,
37             linkStateId => '0.0.0.0',
38             advertisingRouter => '0.0.0.0',
39             lsSequenceNumber => 0,
40             lsChecksum => 0,
41             length => NF_OSPF_LSA_HDR_LEN,
42             full => 1,
43             @_,
44             );
45             }
46              
47             # Lsa begins with standard 20 bytes header
48             sub getLength {
49 0     0 1 0 my $self = shift;
50 0         0 my $len = NF_OSPF_LSA_HDR_LEN;
51 0 0       0 $len += $self->lsa->getLength if $self->lsa;
52 0         0 $len;
53             }
54              
55             sub computeLengths {
56 0     0 1 0 my $self = shift;
57 0         0 my $len = $self->getLength;
58 0         0 $self->length($len);
59             }
60              
61             sub computeChecksums {
62 0     0 1 0 my $self = shift;
63              
64 0         0 $self->lsChecksum(0);
65 0         0 my $raw = $self->pack;
66 0         0 my $data = substr($raw, 2);
67             # We pad the data to the possibly fake length
68 0         0 my @chars = unpack('C*', $data.("0"x($self->length - length($data))));
69              
70 0         0 my $c0 = 0;
71 0         0 my $c1 = 0;
72 0         0 my $length = $self->length - 2;
73 0         0 my $MODX = 4102;
74 0         0 my ($sp, $ep, $p, $q);
75 0         0 $sp = 0;
76 0         0 for ($ep = $length; $sp < $ep; $sp = $q) {
77 0         0 $q = $sp + $MODX;
78 0 0       0 if ($q > $ep) {
79 0         0 $q = $ep;
80             }
81 0         0 for ($p = $sp; $p < $q; $p++) {
82 0         0 $c0 += $chars[$p];
83 0         0 $c1 += $c0;
84             }
85 0         0 $c0 %= 255;
86 0         0 $c1 %= 255;
87             }
88 0         0 my $x = (($length - 15) * $c0 - $c1) % 255;
89 0 0       0 if ($x <= 0) {
90 0         0 $x += 255;
91             }
92 0         0 my $y = 510 - $c0 - $x;
93 0 0       0 if ($y > 255) {
94 0         0 $y -= 255;
95             }
96              
97 0         0 $self->lsChecksum(($x << 8) + $y);
98             }
99              
100             sub pack {
101 1     1 1 177 my $self = shift;
102              
103 1 50       4 my $raw = $self->SUPER::pack('nCCa4a4Nnn a*',
104             $self->lsAge, $self->options, $self->lsType, inetAton($self->linkStateId),
105             inetAton($self->advertisingRouter), $self->lsSequenceNumber,
106             $self->lsChecksum, $self->length,
107             ) or return undef;
108              
109 1 50       58 $raw .= $self->lsa->pack if $self->lsa;
110              
111 1         12 $self->raw($raw);
112             }
113              
114             sub unpack {
115 1     1 1 7 my $self = shift;
116              
117 1 50       3 my ($lsAge, $options, $lsType, $linkStateId, $advertisingRouter,
118             $lsSequenceNumber, $lsChecksum, $length, $payload)
119             = $self->SUPER::unpack('nCCa4a4Nnn a*', $self->raw)
120             or return undef;
121              
122 1         21 $self->lsAge($lsAge);
123 1         8 $self->options($options);
124 1         6 $self->lsType($lsType);
125 1         8 $self->linkStateId(inetNtoa($linkStateId));
126 1         9 $self->advertisingRouter(inetNtoa($advertisingRouter));
127 1         10 $self->lsSequenceNumber($lsSequenceNumber);
128 1         6 $self->lsChecksum($lsChecksum);
129 1         6 $self->length($length);
130              
131 1         5 my $next;
132 1 50 33     2 if ($self->full && $payload) {
133 0 0 0     0 if ($lsType == NF_OSPF_LSTYPE_OPAQUELINKLOCAL
    0 0        
    0          
    0          
134             || $lsType == NF_OSPF_LSTYPE_OPAQUEAREALOCAL
135             || $lsType == NF_OSPF_LSTYPE_OPAQUEDOMAIN) {
136 0         0 my $pLen = length($payload);
137 0 0       0 if ($length > $pLen) {
138 0         0 my $oLen = $length - NF_OSPF_LSA_HDR_LEN;
139 0         0 my $opaque = substr($payload, 0, $oLen);
140 0         0 $next = Net::Frame::Layer::OSPF::Lsa::Opaque->new(raw => $opaque);
141 0         0 $payload = substr($payload, $oLen);
142 0         0 $next->payload($payload);
143             }
144             }
145             elsif ($lsType == NF_OSPF_LSTYPE_ROUTER) {
146 0         0 $next = Net::Frame::Layer::OSPF::Lsa::Router->new(raw => $payload);
147             }
148             elsif ($lsType == NF_OSPF_LSTYPE_NETWORK) {
149 0         0 $next = Net::Frame::Layer::OSPF::Lsa::Network->new(raw => $payload);
150             }
151             elsif ($lsType == NF_OSPF_LSTYPE_SUMMARYIP) {
152 0         0 $next = Net::Frame::Layer::OSPF::Lsa::SummaryIp->new(raw => $payload);
153             }
154             }
155              
156 1 50       11 if ($next) {
157 0         0 $next->unpack;
158 0         0 $self->lsa($next);
159 0         0 $payload = $next->payload;
160             }
161              
162 1         4 $self->payload($payload);
163              
164 1         6 $self;
165             }
166              
167             sub print {
168 0     0 1   my $self = shift;
169              
170 0           my $l = $self->layer;
171 0           my $buf = sprintf
172             "$l: lsAge:%d options:0x%02x lsType:0x%02x linkStateId:%s\n".
173             "$l: advertisingRouter:%s lsSequenceNumber:0x%08x\n".
174             "$l: lsChecksum:0x%04x length:%d",
175             $self->lsAge,
176             $self->options,
177             $self->lsType,
178             $self->linkStateId,
179             $self->advertisingRouter,
180             $self->lsSequenceNumber,
181             $self->lsChecksum,
182             $self->length,
183             ;
184              
185 0 0         if ($self->lsa) {
186 0           $buf .= "\n".$self->lsa->print;
187             }
188              
189 0           $buf;
190             }
191              
192             1;
193              
194             __END__