File Coverage

blib/lib/Net/DNS/Parameters.pm
Criterion Covered Total %
statement 57 57 100.0
branch 16 16 100.0
condition 16 16 100.0
subroutine 19 19 100.0
pod 12 12 100.0
total 120 120 100.0


line stmt bran cond sub pod time code
1             package Net::DNS::Parameters;
2              
3             ################################################
4             ##
5             ## Domain Name System (DNS) Parameters
6             ## (last updated 2023-04-28)
7             ##
8             ################################################
9              
10 96     96   74778 use strict;
  96         210  
  96         2845  
11 96     96   473 use warnings;
  96         178  
  96         4180  
12             our $VERSION = (qw$Id: Parameters.pm 1921 2023-05-08 18:39:59Z willem $)[2];
13              
14 96     96   1070 use integer;
  96         236  
  96         528  
15 96     96   2238 use Carp;
  96         234  
  96         6964  
16              
17 96     96   720 use base qw(Exporter);
  96         299  
  96         191704  
18              
19             our @EXPORT_OK = qw(
20             classbyname classbyval %classbyname
21             typebyname typebyval %typebyname
22             opcodebyname opcodebyval
23             rcodebyname rcodebyval
24             ednsoptionbyname ednsoptionbyval
25             dsotypebyname dsotypebyval
26             );
27              
28             our %EXPORT_TAGS = (
29             class => [qw(classbyname classbyval)],
30             type => [qw(typebyname typebyval)],
31             opcode => [qw(opcodebyname opcodebyval)],
32             rcode => [qw(rcodebyname rcodebyval)],
33             ednsoption => [qw(ednsoptionbyname ednsoptionbyval)],
34             dsotype => [qw(dsotypebyname dsotypebyval)],
35             );
36              
37              
38             # Registry: DNS CLASSes
39             my @classbyname = (
40             IN => 1, # RFC1035
41             CH => 3, # Chaosnet
42             HS => 4, # Hesiod
43             NONE => 254, # RFC2136
44             ANY => 255, # RFC1035
45             );
46             our %classbyval = reverse( CLASS0 => 0, @classbyname );
47             push @classbyname, map { /^\d/ ? $_ : lc($_) } @classbyname;
48             our %classbyname = ( '*' => 255, @classbyname );
49              
50              
51             # Registry: Resource Record (RR) TYPEs
52             my @typebyname = (
53             A => 1, # RFC1035
54             NS => 2, # RFC1035
55             MD => 3, # RFC1035
56             MF => 4, # RFC1035
57             CNAME => 5, # RFC1035
58             SOA => 6, # RFC1035
59             MB => 7, # RFC1035
60             MG => 8, # RFC1035
61             MR => 9, # RFC1035
62             NULL => 10, # RFC1035
63             WKS => 11, # RFC1035
64             PTR => 12, # RFC1035
65             HINFO => 13, # RFC1035
66             MINFO => 14, # RFC1035
67             MX => 15, # RFC1035
68             TXT => 16, # RFC1035
69             RP => 17, # RFC1183
70             AFSDB => 18, # RFC1183 RFC5864
71             X25 => 19, # RFC1183
72             ISDN => 20, # RFC1183
73             RT => 21, # RFC1183
74             NSAP => 22, # RFC1706 https://datatracker.ietf.org/doc/status-change-int-tlds-to-historic
75             'NSAP-PTR' => 23, # RFC1706 https://datatracker.ietf.org/doc/status-change-int-tlds-to-historic
76             SIG => 24, # RFC2536 RFC2931 RFC3110 RFC4034
77             KEY => 25, # RFC2536 RFC2539 RFC3110 RFC4034
78             PX => 26, # RFC2163
79             GPOS => 27, # RFC1712
80             AAAA => 28, # RFC3596
81             LOC => 29, # RFC1876
82             NXT => 30, # RFC2535 RFC3755
83             EID => 31, # http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
84             NIMLOC => 32, # http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
85             SRV => 33, # RFC2782
86             ATMA => 34, # http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf
87             NAPTR => 35, # RFC3403
88             KX => 36, # RFC2230
89             CERT => 37, # RFC4398
90             A6 => 38, # RFC2874 RFC3226 RFC6563
91             DNAME => 39, # RFC6672
92             SINK => 40, # draft-eastlake-kitchen-sink
93             OPT => 41, # RFC3225 RFC6891
94             APL => 42, # RFC3123
95             DS => 43, # RFC4034
96             SSHFP => 44, # RFC4255
97             IPSECKEY => 45, # RFC4025
98             RRSIG => 46, # RFC4034
99             NSEC => 47, # RFC4034 RFC9077
100             DNSKEY => 48, # RFC4034
101             DHCID => 49, # RFC4701
102             NSEC3 => 50, # RFC5155 RFC9077
103             NSEC3PARAM => 51, # RFC5155
104             TLSA => 52, # RFC6698
105             SMIMEA => 53, # RFC8162
106             HIP => 55, # RFC8005
107             NINFO => 56, #
108             RKEY => 57, #
109             TALINK => 58, #
110             CDS => 59, # RFC7344
111             CDNSKEY => 60, # RFC7344
112             OPENPGPKEY => 61, # RFC7929
113             CSYNC => 62, # RFC7477
114             ZONEMD => 63, # RFC8976
115             SVCB => 64, # RFC-ietf-dnsop-svcb-https-12
116             HTTPS => 65, # RFC-ietf-dnsop-svcb-https-12
117             SPF => 99, # RFC7208
118             UINFO => 100, # IANA-Reserved
119             UID => 101, # IANA-Reserved
120             GID => 102, # IANA-Reserved
121             UNSPEC => 103, # IANA-Reserved
122             NID => 104, # RFC6742
123             L32 => 105, # RFC6742
124             L64 => 106, # RFC6742
125             LP => 107, # RFC6742
126             EUI48 => 108, # RFC7043
127             EUI64 => 109, # RFC7043
128             TKEY => 249, # RFC2930
129             TSIG => 250, # RFC8945
130             IXFR => 251, # RFC1995
131             AXFR => 252, # RFC1035 RFC5936
132             MAILB => 253, # RFC1035
133             MAILA => 254, # RFC1035
134             ANY => 255, # RFC1035 RFC6895 RFC8482
135             URI => 256, # RFC7553
136             CAA => 257, # RFC8659
137             AVC => 258, #
138             DOA => 259, # draft-durand-doa-over-dns
139             AMTRELAY => 260, # RFC8777
140             TA => 32768, # http://cameo.library.cmu.edu/ http://www.watson.org/~weiler/INI1999-19.pdf
141             DLV => 32769, # RFC8749 RFC4431
142             );
143             our %typebyval = reverse( TYPE0 => 0, @typebyname );
144             push @typebyname, map { /^\d/ ? $_ : lc($_) } @typebyname;
145             our %typebyname = ( '*' => 255, @typebyname );
146              
147              
148             # Registry: DNS OpCodes
149             my @opcodebyname = (
150             QUERY => 0, # RFC1035
151             IQUERY => 1, # RFC3425
152             STATUS => 2, # RFC1035
153             NOTIFY => 4, # RFC1996
154             UPDATE => 5, # RFC2136
155             DSO => 6, # RFC8490
156             );
157             our %opcodebyval = reverse @opcodebyname;
158             push @opcodebyname, map { /^\d/ ? $_ : lc($_) } @opcodebyname;
159             our %opcodebyname = ( NS_NOTIFY_OP => 4, @opcodebyname );
160              
161              
162             # Registry: DNS RCODEs
163             my @rcodebyname = (
164             NOERROR => 0, # RFC1035
165             FORMERR => 1, # RFC1035
166             SERVFAIL => 2, # RFC1035
167             NXDOMAIN => 3, # RFC1035
168             NOTIMP => 4, # RFC1035
169             REFUSED => 5, # RFC1035
170             YXDOMAIN => 6, # RFC2136 RFC6672
171             YXRRSET => 7, # RFC2136
172             NXRRSET => 8, # RFC2136
173             NOTAUTH => 9, # RFC2136
174             NOTAUTH => 9, # RFC8945
175             NOTZONE => 10, # RFC2136
176             DSOTYPENI => 11, # RFC8490
177             BADVERS => 16, # RFC6891
178             BADSIG => 16, # RFC8945
179             BADKEY => 17, # RFC8945
180             BADTIME => 18, # RFC8945
181             BADMODE => 19, # RFC2930
182             BADNAME => 20, # RFC2930
183             BADALG => 21, # RFC2930
184             BADTRUNC => 22, # RFC8945
185             BADCOOKIE => 23, # RFC7873
186             );
187             our %rcodebyval = reverse( BADSIG => 16, @rcodebyname );
188             push @rcodebyname, map { /^\d/ ? $_ : lc($_) } @rcodebyname;
189             our %rcodebyname = @rcodebyname;
190              
191              
192             # Registry: DNS EDNS0 Option Codes (OPT)
193             my @ednsoptionbyname = (
194             LLQ => 1, # RFC8764
195             UL => 2, # http://files.dns-sd.org/draft-sekar-dns-ul.txt
196             NSID => 3, # RFC5001
197             DAU => 5, # RFC6975
198             DHU => 6, # RFC6975
199             N3U => 7, # RFC6975
200             'CLIENT-SUBNET' => 8, # RFC7871
201             EXPIRE => 9, # RFC7314
202             COOKIE => 10, # RFC7873
203             'TCP-KEEPALIVE' => 11, # RFC7828
204             PADDING => 12, # RFC7830
205             CHAIN => 13, # RFC7901
206             'KEY-TAG' => 14, # RFC8145
207             'EXTENDED-ERROR' => 15, # RFC8914
208             'CLIENT-TAG' => 16, # draft-bellis-dnsop-edns-tags
209             'SERVER-TAG' => 17, # draft-bellis-dnsop-edns-tags
210             'UMBRELLA-IDENT' => 20292, # https://developer.cisco.com/docs/cloud-security/#!integrating-network-devic
211             DEVICEID => 26946, # https://developer.cisco.com/docs/cloud-security/#!network-devices-getting-s
212             );
213             our %ednsoptionbyval = reverse @ednsoptionbyname;
214             push @ednsoptionbyname, map { /^\d/ ? $_ : lc($_) } @ednsoptionbyname;
215             our %ednsoptionbyname = @ednsoptionbyname;
216              
217              
218             # Registry: DNS Header Flags
219             my @dnsflagbyname = (
220             AA => 0x0400, # RFC1035
221             TC => 0x0200, # RFC1035
222             RD => 0x0100, # RFC1035
223             RA => 0x0080, # RFC1035
224             AD => 0x0020, # RFC4035 RFC6840
225             CD => 0x0010, # RFC4035 RFC6840
226             );
227             push @dnsflagbyname, map { /^\d/ ? $_ : lc($_) } @dnsflagbyname;
228             our %dnsflagbyname = @dnsflagbyname;
229              
230              
231             # Registry: EDNS Header Flags (16 bits)
232             my @ednsflagbyname = (
233             DO => 0x8000, # RFC4035 RFC3225 RFC6840
234             );
235             push @ednsflagbyname, map { /^\d/ ? $_ : lc($_) } @ednsflagbyname;
236             our %ednsflagbyname = @ednsflagbyname;
237              
238              
239             # Registry: DSO Type Codes
240             my @dsotypebyname = (
241             KEEPALIVE => 0x0001, # RFC8490
242             RETRYDELAY => 0x0002, # RFC8490
243             ENCRYPTIONPADDING => 0x0003, # RFC8490
244             SUBSCRIBE => 0x0040, # RFC8765
245             PUSH => 0x0041, # RFC8765
246             UNSUBSCRIBE => 0x0042, # RFC8765
247             RECONFIRM => 0x0043, # RFC8765
248             );
249             our %dsotypebyval = reverse @dsotypebyname;
250             push @dsotypebyname, map { /^\d/ ? $_ : lc($_) } @dsotypebyname;
251             our %dsotypebyname = @dsotypebyname;
252              
253              
254             # Registry: Extended DNS Error Codes
255             my @dnserrorbyval = (
256             0 => 'Other Error', # RFC8914
257             1 => 'Unsupported DNSKEY Algorithm', # RFC8914
258             2 => 'Unsupported DS Digest Type', # RFC8914
259             3 => 'Stale Answer', # RFC8914 RFC8767
260             4 => 'Forged Answer', # RFC8914
261             5 => 'DNSSEC Indeterminate', # RFC8914
262             6 => 'DNSSEC Bogus', # RFC8914
263             7 => 'Signature Expired', # RFC8914
264             8 => 'Signature Not Yet Valid', # RFC8914
265             9 => 'DNSKEY Missing', # RFC8914
266             10 => 'RRSIGs Missing', # RFC8914
267             11 => 'No Zone Key Bit Set', # RFC8914
268             12 => 'NSEC Missing', # RFC8914
269             13 => 'Cached Error', # RFC8914
270             14 => 'Not Ready', # RFC8914
271             15 => 'Blocked', # RFC8914
272             16 => 'Censored', # RFC8914
273             17 => 'Filtered', # RFC8914
274             18 => 'Prohibited', # RFC8914
275             19 => 'Stale NXDomain Answer', # RFC8914
276             20 => 'Not Authoritative', # RFC8914
277             21 => 'Not Supported', # RFC8914
278             22 => 'No Reachable Authority', # RFC8914
279             23 => 'Network Error', # RFC8914
280             24 => 'Invalid Data', # RFC8914
281             25 => 'Signature Expired before Valid', # https://github.com/NLnetLabs/unbound/pull/604#discussion_r802678343
282             26 => 'Too Early', # RFC9250
283             27 => 'Unsupported NSEC3 Iterations Value', # RFC9276
284             28 => 'Unable to conform to policy', # draft-homburg-dnsop-codcp-00
285             29 => 'Synthesized', # https://github.com/PowerDNS/pdns/pull/12334
286             );
287             our %dnserrorbyval = @dnserrorbyval;
288              
289              
290             ########
291              
292             # The following functions are wrappers around similarly named hashes.
293              
294             sub classbyname {
295 1142     1142 1 3052 my $name = shift;
296              
297 1142   100     5343 return $classbyname{$name} || $classbyname{uc $name} || return do {
298             croak qq[unknown class "$name"] unless $name =~ m/^(CLASS)?(\d+)/i;
299             my $val = 0 + $2;
300             croak qq[classbyname("$name") out of range] if $val > 0x7fff;
301             return $val;
302             }
303             }
304              
305             sub classbyval {
306 1092     1092 1 6732 my $arg = shift;
307              
308 1092   100     4455 return $classbyval{$arg} || return do {
309             my $val = ( $arg += 0 ) & 0x7fff; # MSB used by mDNS
310             croak qq[classbyval($arg) out of range] if $arg > 0xffff;
311             return $classbyval{$arg} = $classbyval{$val} || "CLASS$val";
312             }
313             }
314              
315              
316             sub typebyname {
317 1041     1041 1 3758 my $name = shift;
318              
319 1041   100     89754 return $typebyname{$name} || return do {
320             if ( $name =~ m/^(TYPE)?(\d+)/i ) {
321             my $val = 0 + $2;
322             croak qq[typebyname("$name") out of range] if $val > 0xffff;
323             return $val;
324             }
325             _typespec("$name.RRNAME") unless $typebyname{uc $name};
326             return $typebyname{uc $name} || croak qq[unknown type "$name"];
327             }
328             }
329              
330             sub typebyval {
331 2989     2989 1 130352 my $val = shift;
332              
333 2989   100     13054 return $typebyval{$val} || return do {
334             $val += 0;
335             croak qq[typebyval($val) out of range] if $val > 0xffff;
336             $typebyval{$val} = "TYPE$val";
337             _typespec("$val.RRTYPE");
338             return $typebyval{$val};
339             }
340             }
341              
342              
343             sub opcodebyname {
344 71     71 1 977 my $arg = shift;
345 71         179 my $val = $opcodebyname{$arg};
346 71 100       216 return $val if defined $val;
347 2 100       15 return $arg if $arg =~ /^\d/;
348 1         96 croak qq[unknown opcode "$arg"];
349             }
350              
351             sub opcodebyval {
352 72     72 1 3222 my $val = shift;
353 72   100     353 return $opcodebyval{$val} || return "$val";
354             }
355              
356              
357             sub rcodebyname {
358 58     58 1 1006 my $arg = shift;
359 58         201 my $val = $rcodebyname{$arg};
360 58 100       227 return $val if defined $val;
361 8 100       107 return $arg if $arg =~ /^\d/;
362 1         92 croak qq[unknown rcode "$arg"];
363             }
364              
365             sub rcodebyval {
366 325     325 1 10894 my $val = shift;
367 325   100     2125 return $rcodebyval{$val} || return "$val";
368             }
369              
370              
371             sub ednsoptionbyname {
372 156     156 1 619 my $arg = shift;
373 156         338 my $val = $ednsoptionbyname{$arg};
374 156 100       416 return $val if defined $val;
375 38 100       161 return $arg if $arg =~ /^\d/;
376 1         93 croak qq[unknown option "$arg"];
377             }
378              
379             sub ednsoptionbyval {
380 118     118 1 9375 my $val = shift;
381 118   100     409 return $ednsoptionbyval{$val} || return "$val";
382             }
383              
384              
385             sub dsotypebyname {
386 9     9 1 357 my $arg = shift;
387 9         58 my $val = $dsotypebyname{$arg};
388 9 100       37 return $val if defined $val;
389 2 100       12 return $arg if $arg =~ /^\d/;
390 1         95 croak qq[unknown DSO type "$arg"];
391             }
392              
393             sub dsotypebyval {
394 9     9 1 4207 my $val = shift;
395 9   100     41 return $dsotypebyval{$val} || return "$val";
396             }
397              
398              
399 96     96   934 use constant EXTLANG => defined eval { require Net::DNS::Extlang };
  96         227  
  96         254  
  96         34760  
400              
401             sub _typespec {
402 5     5   12 my $generate = defined wantarray;
403 5         11 return EXTLANG ? eval <<'END' : ''; ## no critic
404             my ($node) = @_; ## draft-levine-dnsextlang
405             my $instance = Net::DNS::Extlang->new();
406             my $basename = $instance->domain || return '';
407              
408             require Net::DNS::Resolver;
409             my $resolver = Net::DNS::Resolver->new();
410             my $response = $resolver->send( "$node.$basename", 'TXT' ) || return '';
411              
412             foreach my $txt ( grep { $_->type eq 'TXT' } $response->answer ) {
413             my @stanza = $txt->txtdata;
414             my ( $tag, $identifier, @attribute ) = @stanza;
415             next unless defined($tag) && $tag =~ /^RRTYPE=\d+$/;
416             if ( $identifier =~ /^(\w+):(\d+)\W*/ ) {
417             my ( $mnemonic, $rrtype ) = ( uc($1), $2 );
418             croak qq["$mnemonic" is a CLASS identifier] if $classbyname{$mnemonic};
419             for ( typebyval($rrtype) ) {
420             next if /^$mnemonic$/i; # duplicate registration
421             croak qq["$mnemonic" conflicts with TYPE$rrtype ($_)] unless /^TYPE\d+$/;
422             my $known = $typebyname{$mnemonic};
423             croak qq["$mnemonic" conflicts with TYPE$known] if $known;
424             $typebyval{$rrtype} = $mnemonic;
425             $typebyname{$mnemonic} = $rrtype;
426             }
427             }
428             return unless $generate;
429              
430             my $recipe = $instance->xlstorerecord( $identifier, @attribute );
431             return $instance->compilerr($recipe);
432             }
433             END
434             }
435              
436              
437             1;
438             __END__