File Coverage

blib/lib/Net/Frame/Layer/UDP.pm
Criterion Covered Total %
statement 34 81 41.9
branch 3 28 10.7
condition 1 9 11.1
subroutine 10 16 62.5
pod 11 11 100.0
total 59 145 40.6


line stmt bran cond sub pod time code
1             #
2             # $Id: UDP.pm,v ce68fbcc7f6d 2019/05/23 05:58:40 gomor $
3             #
4             package Net::Frame::Layer::UDP;
5 2     2   4878 use strict;
  2         7  
  2         49  
6 2     2   8 use warnings;
  2         2  
  2         47  
7              
8 2     2   360 use Net::Frame::Layer qw(:consts :subs);
  2         5  
  2         416  
9             require Exporter;
10             our @ISA = qw(Net::Frame::Layer Exporter);
11              
12             our %EXPORT_TAGS = (
13             consts => [qw(
14             NF_UDP_HDR_LEN
15             )],
16             );
17             our @EXPORT_OK = (
18             @{$EXPORT_TAGS{consts}},
19             );
20              
21 2     2   14 use constant NF_UDP_HDR_LEN => 8;
  2         4  
  2         168  
22              
23             our @AS = qw(
24             src
25             dst
26             length
27             checksum
28             );
29             __PACKAGE__->cgBuildIndices;
30             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
31              
32 2     2   12 no strict 'vars';
  2         4  
  2         1627  
33              
34             sub new {
35 1     1 1 12 my $self = shift->SUPER::new(
36             src => getRandomHighPort(),
37             dst => 0,
38             length => 0,
39             checksum => 0,
40             @_,
41             );
42              
43 1         238 return $self;
44             }
45              
46             sub pack {
47 1     1 1 4 my $self = shift;
48              
49 1 50       11 $self->[$__raw] = $self->SUPER::pack('nnnn',
50             $self->[$__src],
51             $self->[$__dst],
52             $self->[$__length],
53             $self->[$__checksum],
54             ) or return;
55              
56 1         3 return $self->[$__raw];
57             }
58              
59             sub unpack {
60 1     1 1 4 my $self = shift;
61              
62             # Pad it if less than the required length
63 1 50       3 if (length($self->[$__raw]) < NF_UDP_HDR_LEN) {
64 0         0 $self->[$__raw] .= ("\x00" x (NF_UDP_HDR_LEN - length($self->[$__raw])));
65             }
66              
67 1 50       5 my ($src, $dst, $len, $checksum, $payload) =
68             $self->SUPER::unpack('nnnn a*', $self->[$__raw])
69             or return;
70              
71 1         3 $self->[$__src] = $src;
72 1         1 $self->[$__dst] = $dst;
73 1         2 $self->[$__length] = $len;
74 1         2 $self->[$__checksum] = $checksum;
75 1         3 $self->[$__payload] = $payload;
76              
77 1         2 return $self;
78             }
79              
80             sub getLength {
81 0     0 1 0 return NF_UDP_HDR_LEN;
82             }
83              
84             sub computeLengths {
85 0     0 1 0 my $self = shift;
86 0         0 my ($layers) = @_;
87              
88 0         0 my $len = $self->getLength;
89              
90 0         0 my $start = 0;
91 0         0 my $last = $self;
92 0         0 for my $l (@$layers) {
93 0         0 $last = $l;
94 0 0       0 if (! $start) {
95 0 0       0 $start++ if $l->layer eq 'UDP';
96 0         0 next;
97             }
98 0         0 $len += $l->getLength;
99             }
100              
101 0 0 0     0 if (defined($last->payload) && length($last->payload)) {
102 0         0 $len += length($last->payload);
103             }
104              
105 0         0 $self->[$__length] = $len;
106              
107 0         0 return 1;
108             }
109              
110             sub computeChecksums {
111 0     0 1 0 my $self = shift;
112 0         0 my ($layers) = @_;
113              
114 0         0 my $phpkt;
115 0         0 for my $l (@$layers) {
116 0 0       0 if ($l->layer eq 'IPv4') {
    0          
117 0         0 $phpkt = $self->SUPER::pack('a4a4CCn',
118             inetAton($l->src), inetAton($l->dst), 0, 17, $self->[$__length]);
119             }
120             elsif ($l->layer eq 'IPv6') {
121 0         0 $phpkt = $self->SUPER::pack('a*a*NnCC',
122             inet6Aton($l->src), inet6Aton($l->dst), $self->[$__length],
123             0, 0, 17);
124             }
125             }
126              
127 0 0       0 $phpkt .= $self->SUPER::pack('nnnn',
128             $self->[$__src], $self->[$__dst], $self->[$__length], 0)
129             or return;
130              
131 0         0 my $start = 0;
132 0         0 my $last = $self;
133 0         0 my $payload = '';
134 0         0 for my $l (@$layers) {
135 0         0 $last = $l;
136 0 0       0 if (! $start) {
137 0 0       0 $start++ if $l->layer eq 'UDP';
138 0         0 next;
139             }
140 0         0 $payload .= $l->pack;
141             }
142              
143 0 0 0     0 if (defined($last->payload) && length($last->payload)) {
144 0         0 $payload .= $last->payload;
145             }
146              
147 0 0       0 if (length($payload)) {
148 0 0       0 $phpkt .= $self->SUPER::pack('a*', $payload)
149             or return;
150             }
151              
152 0         0 $self->[$__checksum] = inetChecksum($phpkt);
153              
154 0         0 return 1;
155             }
156              
157             our $Next = {
158             };
159              
160             sub encapsulate {
161 1     1 1 8 my $self = shift;
162 1   33     12 return $Next->{$self->[$__dst]} || $Next->{$self->[$__src]}
163             || $self->[$__nextLayer];
164             }
165              
166             sub getKey {
167 0     0 1 0 my $self = shift;
168 0         0 return $self->layer.':'.$self->[$__src].'-'.$self->[$__dst];
169             }
170              
171             sub getKeyReverse {
172 0     0 1 0 my $self = shift;
173 0         0 return $self->layer.':'.$self->[$__dst].'-'.$self->[$__src];
174             }
175              
176             sub match {
177 0     0 1 0 my $self = shift;
178 0         0 my ($with) = @_;
179 0         0 return 1;
180             }
181              
182             sub print {
183 1     1 1 4 my $self = shift;
184              
185 1         5 my $l = $self->layer;
186              
187 1         47 return sprintf
188             "$l: src:%d dst:%d length:%d checksum:0x%02x",
189             $self->[$__src], $self->[$__dst], $self->[$__length],
190             $self->[$__checksum];
191             }
192              
193             1;
194              
195             __END__