File Coverage

blib/lib/Net/DNS/RR/SOA.pm
Criterion Covered Total %
statement 92 92 100.0
branch 24 24 100.0
condition 12 12 100.0
subroutine 20 20 100.0
pod 7 7 100.0
total 155 155 100.0


line stmt bran cond sub pod time code
1             package Net::DNS::RR::SOA;
2              
3 7     7   56 use strict;
  7         16  
  7         253  
4 7     7   42 use warnings;
  7         13  
  7         447  
5             our $VERSION = (qw$Id: SOA.pm 1931 2023-08-23 13:14:15Z willem $)[2];
6              
7 7     7   55 use base qw(Net::DNS::RR);
  7         18  
  7         664  
8              
9              
10             =head1 NAME
11              
12             Net::DNS::RR::SOA - DNS SOA resource record
13              
14             =cut
15              
16 7     7   84 use integer;
  7         18  
  7         55  
17              
18 7     7   255 use Net::DNS::DomainName;
  7         14  
  7         197  
19 7     7   3820 use Net::DNS::Mailbox;
  7         19  
  7         7919  
20              
21              
22             sub _decode_rdata { ## decode rdata from wire-format octet string
23 29     29   167 my ( $self, @argument ) = @_;
24 29         98 my ( $data, $offset, @opaque ) = @argument;
25              
26 29         118 ( $self->{mname}, $offset ) = Net::DNS::DomainName1035->decode(@argument);
27 29         235 ( $self->{rname}, $offset ) = Net::DNS::Mailbox1035->decode( $data, $offset, @opaque );
28 29         187 @{$self}{qw(serial refresh retry expire minimum)} = unpack "\@$offset N5", $$data;
  29         153  
29 29         96 return;
30             }
31              
32              
33             sub _encode_rdata { ## encode rdata as wire-format octet string
34 12     12   32 my ( $self, @argument ) = @_;
35 12         26 my ( $offset, @opaque ) = @argument;
36              
37 12         23 my $rname = $self->{rname};
38 12         47 my $rdata = $self->{mname}->encode(@argument);
39 12         49 $rdata .= $rname->encode( $offset + length($rdata), @opaque );
40 12         45 $rdata .= pack 'N5', $self->serial, @{$self}{qw(refresh retry expire minimum)};
  12         45  
41 12         127 return $rdata;
42             }
43              
44              
45             sub _format_rdata { ## format rdata portion of RR string.
46 8     8   13 my $self = shift;
47              
48 8         19 my $mname = $self->{mname}->string;
49 8         35 my $rname = $self->{rname}->string;
50 8         19 my $serial = $self->serial;
51 8 100       26 my $spacer = length "$serial" > 7 ? "" : "\t";
52 8         52 return ($mname, $rname,
53             join( "\n\t\t\t\t",
54             "\t\t\t$serial$spacer\t;serial", "$self->{refresh}\t\t;refresh",
55             "$self->{retry}\t\t;retry", "$self->{expire}\t\t;expire",
56             "$self->{minimum}\t\t;minimum\n" ) );
57             }
58              
59              
60             sub _parse_rdata { ## populate RR from rdata in argument list
61 22     22   83 my ( $self, @argument ) = @_;
62              
63 22         82 for (qw(mname rname)) { $self->$_( shift @argument ) }
  44         123  
64 22 100       85 $self->serial( shift @argument ) if scalar @argument; # possibly undefined
65 22         64 for (qw(refresh retry expire minimum)) {
66 70 100       142 last unless scalar @argument;
67 64         161 $self->$_( Net::DNS::RR::ttl( {}, shift @argument ) );
68             }
69 22         45 return;
70             }
71              
72              
73             sub _defaults { ## specify RR attribute default values
74 7     7   14 my $self = shift;
75              
76 7         26 $self->_parse_rdata(qw(. . 0 4h 1h 3w 1h));
77 7         15 delete $self->{serial};
78 7         26 return;
79             }
80              
81              
82             sub mname {
83 25     25 1 63 my ( $self, @value ) = @_;
84 25         45 for (@value) { $self->{mname} = Net::DNS::DomainName1035->new($_) }
  23         100  
85 25 100       130 return $self->{mname} ? $self->{mname}->name : undef;
86             }
87              
88              
89             sub rname {
90 25     25 1 953 my ( $self, @value ) = @_;
91 25         57 for (@value) { $self->{rname} = Net::DNS::Mailbox1035->new($_) }
  23         85  
92 25 100       125 return $self->{rname} ? $self->{rname}->address : undef;
93             }
94              
95              
96             sub serial {
97 81     81 1 1774 my ( $self, @value ) = @_;
98              
99 81 100 100     243 return $self->{serial} || 0 unless scalar @value; # current/default value
100              
101 57         100 my $value = shift @value; # replace if in sequence
102 57 100       139 return $self->{serial} = ( $value & 0xFFFFFFFF ) if _ordered( $self->{serial}, $value );
103              
104             # unwise to assume 64-bit arithmetic, or that 32-bit integer overflow goes unpunished
105 22   100     55 my $serial = 0xFFFFFFFF & ( $self->{serial} || 0 );
106 22 100       57 return $self->{serial} = 0x80000000 if $serial == 0x7FFFFFFF; # wrap
107 21 100       57 return $self->{serial} = 0x00000000 if $serial == 0xFFFFFFFF; # wrap
108 20         101 return $self->{serial} = $serial + 1; # increment
109             }
110              
111              
112             sub refresh {
113 19     19 1 842 my ( $self, @value ) = @_;
114 19         43 for (@value) { $self->{refresh} = 0 + $_ }
  17         34  
115 19   100     73 return $self->{refresh} || 0;
116             }
117              
118              
119             sub retry {
120 19     19 1 831 my ( $self, @value ) = @_;
121 19         38 for (@value) { $self->{retry} = 0 + $_ }
  17         34  
122 19   100     67 return $self->{retry} || 0;
123             }
124              
125              
126             sub expire {
127 19     19 1 826 my ( $self, @value ) = @_;
128 19         30 for (@value) { $self->{expire} = 0 + $_ }
  17         36  
129 19   100     66 return $self->{expire} || 0;
130             }
131              
132              
133             sub minimum {
134 24     24 1 829 my ( $self, @value ) = @_;
135 24         49 for (@value) { $self->{minimum} = 0 + $_ }
  17         36  
136 24   100     109 return $self->{minimum} || 0;
137             }
138              
139              
140             ########################################
141              
142             sub _ordered() { ## irreflexive 32-bit partial ordering
143 57     57   124 my ( $n1, $n2 ) = @_;
144              
145 57 100       127 return 0 unless defined $n2; # ( any, undef )
146 53 100       210 return 1 unless defined $n1; # ( undef, any )
147              
148             # unwise to assume 64-bit arithmetic, or that 32-bit integer overflow goes unpunished
149 7     7   60 use integer; # fold, leaving $n2 non-negative
  7         17  
  7         32  
150 31         54 $n1 = ( $n1 & 0xFFFFFFFF ) ^ ( $n2 & 0x80000000 ); # -2**31 <= $n1 < 2**32
151 31         41 $n2 = ( $n2 & 0x7FFFFFFF ); # 0 <= $n2 < 2**31
152              
153 31 100       195 return $n1 < $n2 ? ( $n1 > ( $n2 - 0x80000000 ) ) : ( $n2 < ( $n1 - 0x80000000 ) );
154             }
155              
156             ########################################
157              
158              
159             1;
160             __END__