2010-08-04 07:57:59 +10:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
2020-01-03 23:41:45 +11:00
|
|
|
"bytes"
|
2012-04-30 22:50:52 +10:00
|
|
|
"fmt"
|
2010-08-04 07:57:59 +10:00
|
|
|
"net"
|
|
|
|
"strconv"
|
2010-12-30 02:11:23 +11:00
|
|
|
"strings"
|
2011-12-14 21:30:29 +11:00
|
|
|
"time"
|
2010-08-04 07:57:59 +10:00
|
|
|
)
|
|
|
|
|
2013-06-08 23:09:37 +10:00
|
|
|
type (
|
2015-02-19 20:58:33 +11:00
|
|
|
// Type is a DNS type.
|
|
|
|
Type uint16
|
|
|
|
// Class is a DNS class.
|
|
|
|
Class uint16
|
|
|
|
// Name is a DNS domain name.
|
|
|
|
Name string
|
2013-06-08 23:09:37 +10:00
|
|
|
)
|
|
|
|
|
2010-08-04 07:57:59 +10:00
|
|
|
// Packet formats
|
|
|
|
|
2011-01-27 19:29:11 +11:00
|
|
|
// Wire constants and supported types.
|
2010-08-04 07:57:59 +10:00
|
|
|
const (
|
|
|
|
// valid RR_Header.Rrtype and Question.qtype
|
2015-02-20 22:39:15 +11:00
|
|
|
|
2013-05-07 17:44:21 +10:00
|
|
|
TypeNone uint16 = 0
|
2012-02-19 06:07:25 +11:00
|
|
|
TypeA uint16 = 1
|
|
|
|
TypeNS uint16 = 2
|
|
|
|
TypeMD uint16 = 3
|
|
|
|
TypeMF uint16 = 4
|
|
|
|
TypeCNAME uint16 = 5
|
|
|
|
TypeSOA uint16 = 6
|
|
|
|
TypeMB uint16 = 7
|
|
|
|
TypeMG uint16 = 8
|
|
|
|
TypeMR uint16 = 9
|
|
|
|
TypeNULL uint16 = 10
|
|
|
|
TypePTR uint16 = 12
|
|
|
|
TypeHINFO uint16 = 13
|
|
|
|
TypeMINFO uint16 = 14
|
|
|
|
TypeMX uint16 = 15
|
|
|
|
TypeTXT uint16 = 16
|
2012-05-02 06:57:22 +10:00
|
|
|
TypeRP uint16 = 17
|
2012-06-01 21:34:14 +10:00
|
|
|
TypeAFSDB uint16 = 18
|
2012-11-21 00:32:06 +11:00
|
|
|
TypeX25 uint16 = 19
|
2012-11-21 00:14:00 +11:00
|
|
|
TypeISDN uint16 = 20
|
2012-08-10 17:22:50 +10:00
|
|
|
TypeRT uint16 = 21
|
2013-10-13 22:25:08 +11:00
|
|
|
TypeNSAPPTR uint16 = 23
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeSIG uint16 = 24
|
|
|
|
TypeKEY uint16 = 25
|
2013-10-13 23:23:02 +11:00
|
|
|
TypePX uint16 = 26
|
2013-10-13 23:01:33 +11:00
|
|
|
TypeGPOS uint16 = 27
|
2012-02-19 06:07:25 +11:00
|
|
|
TypeAAAA uint16 = 28
|
|
|
|
TypeLOC uint16 = 29
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeNXT uint16 = 30
|
2013-10-20 07:31:12 +11:00
|
|
|
TypeEID uint16 = 31
|
|
|
|
TypeNIMLOC uint16 = 32
|
2012-02-19 06:07:25 +11:00
|
|
|
TypeSRV uint16 = 33
|
2012-11-21 00:32:06 +11:00
|
|
|
TypeATMA uint16 = 34
|
2012-02-19 06:07:25 +11:00
|
|
|
TypeNAPTR uint16 = 35
|
|
|
|
TypeKX uint16 = 36
|
|
|
|
TypeCERT uint16 = 37
|
|
|
|
TypeDNAME uint16 = 39
|
|
|
|
TypeOPT uint16 = 41 // EDNS
|
2020-01-03 23:41:45 +11:00
|
|
|
TypeAPL uint16 = 42
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeDS uint16 = 43
|
|
|
|
TypeSSHFP uint16 = 44
|
|
|
|
TypeRRSIG uint16 = 46
|
|
|
|
TypeNSEC uint16 = 47
|
|
|
|
TypeDNSKEY uint16 = 48
|
|
|
|
TypeDHCID uint16 = 49
|
|
|
|
TypeNSEC3 uint16 = 50
|
|
|
|
TypeNSEC3PARAM uint16 = 51
|
2012-04-14 18:44:32 +10:00
|
|
|
TypeTLSA uint16 = 52
|
2016-10-18 04:09:52 +11:00
|
|
|
TypeSMIMEA uint16 = 53
|
2012-02-19 06:07:25 +11:00
|
|
|
TypeHIP uint16 = 55
|
2012-11-21 02:42:16 +11:00
|
|
|
TypeNINFO uint16 = 56
|
2012-11-21 02:48:28 +11:00
|
|
|
TypeRKEY uint16 = 57
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeTALINK uint16 = 58
|
2012-11-21 02:52:18 +11:00
|
|
|
TypeCDS uint16 = 59
|
2014-10-24 08:18:23 +11:00
|
|
|
TypeCDNSKEY uint16 = 60
|
2014-08-14 18:18:08 +10:00
|
|
|
TypeOPENPGPKEY uint16 = 61
|
Implement CSYNC (#585)
Implement the CSYNC record.
Fixes #290
Long overdue, lets add this record. Similar in vain as NSEC/NSEC3, we
need to implement len() our selves. Presentation format parsing and
tests are done as well.
This is CoreDNS running with CSYNC support, `dig` doesn't support this
at the moment, so:
~~~
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40323
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;csync.example.org. IN TYPE62
;; ANSWER SECTION:
csync.example.org. 10 IN TYPE62 \# 12 000335240042000460000008
;; AUTHORITY SECTION:
example.org. 10 IN NS a.iana-servers.net.
example.org. 10 IN NS b.iana-servers.net.
~~~
2017-11-25 19:19:06 +11:00
|
|
|
TypeCSYNC uint16 = 62
|
2021-02-27 02:35:05 +11:00
|
|
|
TypeZONEMD uint16 = 63
|
Implement SVCB (#1067)
* Implement SVCB
* Fix serialization and deserialization of double quotes
* More effort (?)
4 months old commit
* DEBUG
* _
* Presentation format serialization/deserialization
* _
Remove generated
* Progress on presentation format parse & write
* _
* Finish parsing presentation format
* Regenerate
* Pack unpack
* Move to svcb.go
Scan_rr.go and types.go should be untouched now
* :bug:
Thanks ghedo
* Definitions
* TypeHTTPSSVC
* Generated
and isDuplicate
* Goodbye lenient functions
Now private key=value pairs have to be defined as structs too. They are no longer automatically named as KeyNNNNN
* Encode/decode
* Experimental svc
* Read method
* Implement some of the methods, use trick...
to report where the error is while reading it. This should be applied to EDNS too. Todo: Find if case can only contain e := new(SVC_ALPN) and rest moved out
Also fix two compile errors
* Add SVC_LOCAL methods, reorder, remove alpn value, bugs
* Errors
* Alpn, make it build
* Correct testsuite
* Fully implement parser
Change from keeping a state variable to reading in one iteration until the key=value pair is fully consumed
* Simplify and document
EDNS should be simplified too
* Attempt to fix fuzzer
And Alpn bug
* A bug and change type values to match @ghedo's implementation
* IP bug
Also there are two ip duplicating patterns, one with copy, one with append. Maybe change it to be consistent.
* Check for strictly increasing keys as required
* Don't panic on invalid alpn
* Redundant check, don't modify original array
* Size calculation
* Fix the fuzzer, match the style
* 65535 is reserved too, don't delay errors
* Check keyNNN, check for aliasform having values
* IPvNHint is an array
* Fix ipvNHint
* Rename everything
* Unrecognized keys according to the updated specification
* Skip zero-length structs in generators. Fix CI
* Doc cleanup
* Off by one
* Add parse tests
* Check if private key doesn't collide with known key, invalid tests
* Disallow IPv4 as IPv6. More tests.
Related #1107
* Style fixes
* More consistency, more tests
* :bug: Deep copy as in the documentation
a := make([]net.IP, 1)
a[0] = net.ParseIP("1.1.1.1").To4()
b := append(make([]net.IP, 0, 1), a...)
b[0] = net.ParseIP("3.1.1.1").To4()
fmt.Println(a[0][0])
* Make tests readable
* Move valid parse tests to different file
* :bug: One of previous commits not fully committed
* Test binary single value encoding/decoding and full encode/decode
* Add worst-case grows to builders, :bug: Wrong visible character range, redundant tests
* Testing improvements
And don't convert to IPv4 twice
* Doc update only
* Document worst case allocations
and ipv6 can be at most of length 39, not 40
* Redundant IP copy, consistent IPv6 behavior, fix deep copy
* isDuplicate for SVCB
* Optimizations
* echoconfig
* Svc => SVCB
* Fix CI
* Regenerate after REBASE (2)
Rebased twice on 15th and 20th May
* Rename svc, use escapeByte.
* Fix parsing whitespaces between quotes, rename ECHOHOConfig
* resolve
Remove svcbFieldLen
Use reverseInt
Uppercase SVCB
Rename key_value
"invalid" => bad
Alpn comments
> 65535 check
Unneeded slices
* a little more
read => parse
IP array meaning
Force pushed because forgot to change read in svcb_test.go
* HTTPSSVC -> HTTPS
* Use new values
* mandatory code
https://github.com/MikeBishop/dns-alt-svc/pull/205
* Resolve comments
Rename svcb-pairs
Remove SVCB_PRIVATE ranges
Comment on SVCB_KEY65535
ParseError return l.token
rename svcbKeyToString and svcbStringToKey
privatize SVCBKeyToString, SVCBStringToKey
* Refactor 1
Rename sorted, originalPairs
Use append instead of copy
Use svcb_RESERVED instead of 65535, with it now being private
"type SVCBKey uint16"
* Refactor 2
svcbKeyToString as method
svcbStringToKey updated after key 0
:bug: mandatory has missing key
Rename str
idx < 0
* Refactor 3
Use l.token as z
var key, value string
Comment wrap
0:
Sentences with '.'
keyValue => kv
* Refactor 4
* Refactor 5
len() int
* Refactor 6
* Refactor 7
* Test remove parsing
* Error messages
* Rewrite two estimate comments
* parse shouldn't modify original array :bug:
* Remove two unneeded comments
* Address review comments
Push 2 because can't build fuzzer python
Push 3 to try again
* Simplify argument duplication as per tmthrgd's suggestion
And add the relevant test
Force push edit: Make sorting code fit into one line
* Rewrite ECHConfig and address the review
* Remove the optional tab
* Add To4() Check
* More cleanup and fix mandatory not sorting bug
2020-10-11 18:09:36 +11:00
|
|
|
TypeSVCB uint16 = 64
|
|
|
|
TypeHTTPS uint16 = 65
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeSPF uint16 = 99
|
2013-04-30 23:20:01 +10:00
|
|
|
TypeUINFO uint16 = 100
|
|
|
|
TypeUID uint16 = 101
|
|
|
|
TypeGID uint16 = 102
|
|
|
|
TypeUNSPEC uint16 = 103
|
2012-11-18 07:26:48 +11:00
|
|
|
TypeNID uint16 = 104
|
|
|
|
TypeL32 uint16 = 105
|
|
|
|
TypeL64 uint16 = 106
|
|
|
|
TypeLP uint16 = 107
|
2013-04-16 02:34:21 +10:00
|
|
|
TypeEUI48 uint16 = 108
|
|
|
|
TypeEUI64 uint16 = 109
|
2015-08-23 21:55:01 +10:00
|
|
|
TypeURI uint16 = 256
|
|
|
|
TypeCAA uint16 = 257
|
2017-03-30 07:17:13 +11:00
|
|
|
TypeAVC uint16 = 258
|
2011-08-22 22:11:41 +10:00
|
|
|
|
|
|
|
TypeTKEY uint16 = 249
|
|
|
|
TypeTSIG uint16 = 250
|
2015-02-20 22:39:15 +11:00
|
|
|
|
2011-03-25 21:19:35 +11:00
|
|
|
// valid Question.Qtype only
|
2011-08-22 22:11:41 +10:00
|
|
|
TypeIXFR uint16 = 251
|
|
|
|
TypeAXFR uint16 = 252
|
|
|
|
TypeMAILB uint16 = 253
|
|
|
|
TypeMAILA uint16 = 254
|
|
|
|
TypeANY uint16 = 255
|
2012-09-02 01:06:24 +10:00
|
|
|
|
2013-10-13 23:27:50 +11:00
|
|
|
TypeTA uint16 = 32768
|
|
|
|
TypeDLV uint16 = 32769
|
|
|
|
TypeReserved uint16 = 65535
|
2011-02-21 23:16:07 +11:00
|
|
|
|
2011-03-25 21:19:35 +11:00
|
|
|
// valid Question.Qclass
|
2010-08-04 07:57:59 +10:00
|
|
|
ClassINET = 1
|
|
|
|
ClassCSNET = 2
|
|
|
|
ClassCHAOS = 3
|
|
|
|
ClassHESIOD = 4
|
2011-07-23 17:21:24 +10:00
|
|
|
ClassNONE = 254
|
2010-08-04 07:57:59 +10:00
|
|
|
ClassANY = 255
|
|
|
|
|
2017-07-22 01:02:54 +10:00
|
|
|
// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
|
|
|
|
RcodeSuccess = 0 // NoError - No Error [DNS]
|
|
|
|
RcodeFormatError = 1 // FormErr - Format Error [DNS]
|
|
|
|
RcodeServerFailure = 2 // ServFail - Server Failure [DNS]
|
|
|
|
RcodeNameError = 3 // NXDomain - Non-Existent Domain [DNS]
|
|
|
|
RcodeNotImplemented = 4 // NotImp - Not Implemented [DNS]
|
|
|
|
RcodeRefused = 5 // Refused - Query Refused [DNS]
|
|
|
|
RcodeYXDomain = 6 // YXDomain - Name Exists when it should not [DNS Update]
|
|
|
|
RcodeYXRrset = 7 // YXRRSet - RR Set Exists when it should not [DNS Update]
|
|
|
|
RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update]
|
|
|
|
RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update]
|
|
|
|
RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG]
|
|
|
|
RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG]
|
|
|
|
RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0]
|
|
|
|
RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG]
|
|
|
|
RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG]
|
|
|
|
RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY]
|
|
|
|
RcodeBadName = 20 // BADNAME - Duplicate key name [TKEY]
|
|
|
|
RcodeBadAlg = 21 // BADALG - Algorithm not supported [TKEY]
|
|
|
|
RcodeBadTrunc = 22 // BADTRUNC - Bad Truncation [TSIG]
|
|
|
|
RcodeBadCookie = 23 // BADCOOKIE - Bad/missing Server Cookie [DNS Cookies]
|
2011-01-02 05:51:25 +11:00
|
|
|
|
2015-08-23 21:55:01 +10:00
|
|
|
// Message Opcodes. There is no 3.
|
2011-01-02 05:51:25 +11:00
|
|
|
OpcodeQuery = 0
|
|
|
|
OpcodeIQuery = 1
|
|
|
|
OpcodeStatus = 2
|
|
|
|
OpcodeNotify = 4
|
2011-01-02 06:51:34 +11:00
|
|
|
OpcodeUpdate = 5
|
2010-08-04 07:57:59 +10:00
|
|
|
)
|
|
|
|
|
2021-02-27 02:35:05 +11:00
|
|
|
// Used in ZONEMD https://tools.ietf.org/html/rfc8976
|
|
|
|
const (
|
|
|
|
ZoneMDSchemeSimple = 1
|
|
|
|
|
|
|
|
ZoneMDHashAlgSHA384 = 1
|
|
|
|
ZoneMDHashAlgSHA512 = 2
|
|
|
|
)
|
|
|
|
|
2017-02-16 07:40:16 +11:00
|
|
|
// Header is the wire format for the DNS packet header.
|
2010-08-04 07:57:59 +10:00
|
|
|
type Header struct {
|
|
|
|
Id uint16
|
|
|
|
Bits uint16
|
|
|
|
Qdcount, Ancount, Nscount, Arcount uint16
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2015-07-03 18:31:53 +10:00
|
|
|
headerSize = 12
|
2015-06-29 10:20:16 +10:00
|
|
|
|
2010-08-04 07:57:59 +10:00
|
|
|
// Header.Bits
|
|
|
|
_QR = 1 << 15 // query/response (response=1)
|
|
|
|
_AA = 1 << 10 // authoritative
|
|
|
|
_TC = 1 << 9 // truncated
|
|
|
|
_RD = 1 << 8 // recursion desired
|
|
|
|
_RA = 1 << 7 // recursion available
|
2010-12-22 00:41:48 +11:00
|
|
|
_Z = 1 << 6 // Z
|
2020-02-15 08:47:21 +11:00
|
|
|
_AD = 1 << 5 // authenticated data
|
2010-12-22 00:41:48 +11:00
|
|
|
_CD = 1 << 4 // checking disabled
|
2017-11-08 00:45:27 +11:00
|
|
|
)
|
2012-04-30 22:50:52 +10:00
|
|
|
|
2020-02-15 08:47:21 +11:00
|
|
|
// Various constants used in the LOC RR. See RFC 1887.
|
2017-11-08 00:45:27 +11:00
|
|
|
const (
|
2014-03-27 23:43:13 +11:00
|
|
|
LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
|
|
|
|
LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
|
2017-11-08 00:45:27 +11:00
|
|
|
LOC_HOURS = 60 * 1000
|
|
|
|
LOC_DEGREES = 60 * LOC_HOURS
|
|
|
|
LOC_ALTITUDEBASE = 100000
|
2014-03-27 23:43:13 +11:00
|
|
|
)
|
2014-10-08 12:27:25 +11:00
|
|
|
|
2015-08-23 19:21:18 +10:00
|
|
|
// Different Certificate Types, see RFC 4398, Section 2.1
|
2014-10-08 12:27:25 +11:00
|
|
|
const (
|
|
|
|
CertPKIX = 1 + iota
|
|
|
|
CertSPKI
|
|
|
|
CertPGP
|
|
|
|
CertIPIX
|
|
|
|
CertISPKI
|
|
|
|
CertIPGP
|
|
|
|
CertACPKIX
|
|
|
|
CertIACPKIX
|
|
|
|
CertURI = 253
|
|
|
|
CertOID = 254
|
|
|
|
)
|
|
|
|
|
2015-08-23 19:21:18 +10:00
|
|
|
// CertTypeToString converts the Cert Type to its string representation.
|
|
|
|
// See RFC 4398 and RFC 6944.
|
2014-10-08 12:27:25 +11:00
|
|
|
var CertTypeToString = map[uint16]string{
|
|
|
|
CertPKIX: "PKIX",
|
|
|
|
CertSPKI: "SPKI",
|
|
|
|
CertPGP: "PGP",
|
|
|
|
CertIPIX: "IPIX",
|
|
|
|
CertISPKI: "ISPKI",
|
|
|
|
CertIPGP: "IPGP",
|
|
|
|
CertACPKIX: "ACPKIX",
|
|
|
|
CertIACPKIX: "IACPKIX",
|
|
|
|
CertURI: "URI",
|
|
|
|
CertOID: "OID",
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
//go:generate go run types_generate.go
|
|
|
|
|
2020-03-30 04:46:09 +11:00
|
|
|
// Question holds a DNS question. Usually there is just one. While the
|
|
|
|
// original DNS RFCs allow multiple questions in the question section of a
|
|
|
|
// message, in practice it never works. Because most DNS servers see multiple
|
|
|
|
// questions as an error, it is recommended to only have one question per
|
|
|
|
// message.
|
2010-08-04 07:57:59 +10:00
|
|
|
type Question struct {
|
2012-04-30 05:55:29 +10:00
|
|
|
Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
|
2010-08-04 07:57:59 +10:00
|
|
|
Qtype uint16
|
|
|
|
Qclass uint16
|
|
|
|
}
|
|
|
|
|
2018-11-30 10:33:41 +11:00
|
|
|
func (q *Question) len(off int, compression map[string]struct{}) int {
|
|
|
|
l := domainNameLen(q.Name, off, compression, true)
|
|
|
|
l += 2 + 2
|
|
|
|
return l
|
2015-10-07 14:33:08 +11:00
|
|
|
}
|
|
|
|
|
2011-12-20 22:53:47 +11:00
|
|
|
func (q *Question) String() (s string) {
|
2010-08-04 07:57:59 +10:00
|
|
|
// prefix with ; (as in dig)
|
2014-04-24 06:06:17 +10:00
|
|
|
s = ";" + sprintName(q.Name) + "\t"
|
2013-06-08 23:09:37 +10:00
|
|
|
s += Class(q.Qclass).String() + "\t"
|
|
|
|
s += " " + Type(q.Qtype).String()
|
2010-08-04 07:57:59 +10:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-02-15 08:47:21 +11:00
|
|
|
// ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
|
2015-08-23 19:21:18 +10:00
|
|
|
// is named "*" there.
|
2012-12-10 05:23:25 +11:00
|
|
|
type ANY struct {
|
2011-11-03 09:06:54 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
// Does not have any rdata
|
2011-08-22 22:13:43 +10:00
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *ANY) String() string { return rr.Hdr.String() }
|
2012-01-10 20:43:28 +11:00
|
|
|
|
Support parsing known RR types in RFC 3597 format (#1211)
* Support parsing known RR types in RFC 3597 format
This is the format used for "Unknown DNS Resource Records", but it's
also useful to support parsing known RR types in this way.
RFC 3597 says:
An implementation MAY also choose to represent some RRs of known type
using the above generic representations for the type, class and/or
RDATA, which carries the benefit of making the resulting master file
portable to servers where these types are unknown. Using the generic
representation for the RDATA of an RR of known type can also be
useful in the case of an RR type where the text format varies
depending on a version, protocol, or similar field (or several)
embedded in the RDATA when such a field has a value for which no text
format is known, e.g., a LOC RR [RFC1876] with a VERSION other than
0.
Even though an RR of known type represented in the \# format is
effectively treated as an unknown type for the purpose of parsing the
RDATA text representation, all further processing by the server MUST
treat it as a known type and take into account any applicable type-
specific rules regarding compression, canonicalization, etc.
* Correct mistakes in TestZoneParserAddressAAAA
This was spotted when writing TestParseKnownRRAsRFC3597.
* Eliminate canParseAsRR
This has the advantage that concrete types will now be returned for
parsed ANY, NULL, OPT and TSIG records.
* Expand TestDynamicUpdateParsing for RFC 3597
This ensures we're properly handling empty RDATA for RFC 3597 parsed
records.
2021-01-31 00:05:25 +11:00
|
|
|
func (*ANY) parse(c *zlexer, origin string) *ParseError {
|
|
|
|
return &ParseError{err: "ANY records do not have a presentation format"}
|
2019-01-06 15:06:16 +11:00
|
|
|
}
|
|
|
|
|
2018-12-30 20:45:18 +11:00
|
|
|
// NULL RR. See RFC 1035.
|
|
|
|
type NULL struct {
|
2019-01-03 21:33:38 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Data string `dns:"any"`
|
2018-12-30 20:45:18 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *NULL) String() string {
|
|
|
|
// There is no presentation format; prefix string with a comment.
|
2019-01-03 21:33:38 +11:00
|
|
|
return ";" + rr.Hdr.String() + rr.Data
|
2018-12-30 20:45:18 +11:00
|
|
|
}
|
|
|
|
|
Support parsing known RR types in RFC 3597 format (#1211)
* Support parsing known RR types in RFC 3597 format
This is the format used for "Unknown DNS Resource Records", but it's
also useful to support parsing known RR types in this way.
RFC 3597 says:
An implementation MAY also choose to represent some RRs of known type
using the above generic representations for the type, class and/or
RDATA, which carries the benefit of making the resulting master file
portable to servers where these types are unknown. Using the generic
representation for the RDATA of an RR of known type can also be
useful in the case of an RR type where the text format varies
depending on a version, protocol, or similar field (or several)
embedded in the RDATA when such a field has a value for which no text
format is known, e.g., a LOC RR [RFC1876] with a VERSION other than
0.
Even though an RR of known type represented in the \# format is
effectively treated as an unknown type for the purpose of parsing the
RDATA text representation, all further processing by the server MUST
treat it as a known type and take into account any applicable type-
specific rules regarding compression, canonicalization, etc.
* Correct mistakes in TestZoneParserAddressAAAA
This was spotted when writing TestParseKnownRRAsRFC3597.
* Eliminate canParseAsRR
This has the advantage that concrete types will now be returned for
parsed ANY, NULL, OPT and TSIG records.
* Expand TestDynamicUpdateParsing for RFC 3597
This ensures we're properly handling empty RDATA for RFC 3597 parsed
records.
2021-01-31 00:05:25 +11:00
|
|
|
func (*NULL) parse(c *zlexer, origin string) *ParseError {
|
|
|
|
return &ParseError{err: "NULL records do not have a presentation format"}
|
2019-01-06 15:06:16 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// CNAME RR. See RFC 1034.
|
2012-12-10 05:23:25 +11:00
|
|
|
type CNAME struct {
|
2012-03-02 08:40:34 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Target string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2015-10-07 15:06:31 +11:00
|
|
|
func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
|
2012-01-10 20:43:28 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// HINFO RR. See RFC 1034.
|
2012-12-10 05:23:25 +11:00
|
|
|
type HINFO struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Cpu string
|
|
|
|
Os string
|
|
|
|
}
|
|
|
|
|
2015-05-08 02:09:05 +10:00
|
|
|
func (rr *HINFO) String() string {
|
|
|
|
return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
|
|
|
|
}
|
2012-01-10 20:43:28 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MB RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MB struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Mb string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2015-10-07 15:06:31 +11:00
|
|
|
func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
|
2012-01-10 20:43:28 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MG RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MG struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Mg string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
|
2012-01-10 20:43:28 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MINFO RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MINFO struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Rmail string `dns:"cdomain-name"`
|
|
|
|
Email string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *MINFO) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MR RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MR struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Mr string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *MR) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Mr)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MF RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MF struct {
|
2012-06-01 21:25:54 +10:00
|
|
|
Hdr RR_Header
|
2012-06-01 21:34:14 +10:00
|
|
|
Mf string `dns:"cdomain-name"`
|
2012-06-01 21:25:54 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *MF) String() string {
|
2014-11-29 06:03:55 +11:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Mf)
|
2012-06-01 21:25:54 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MD RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MD struct {
|
2012-06-01 21:25:54 +10:00
|
|
|
Hdr RR_Header
|
2012-06-01 21:34:14 +10:00
|
|
|
Md string `dns:"cdomain-name"`
|
2012-06-01 21:25:54 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *MD) String() string {
|
2014-11-29 06:03:55 +11:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Md)
|
2012-06-01 21:25:54 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// MX RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type MX struct {
|
2012-11-21 00:32:06 +11:00
|
|
|
Hdr RR_Header
|
2012-11-18 19:13:43 +11:00
|
|
|
Preference uint16
|
2012-11-21 00:32:06 +11:00
|
|
|
Mx string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *MX) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// AFSDB RR. See RFC 1183.
|
2012-12-10 05:23:25 +11:00
|
|
|
type AFSDB struct {
|
2012-06-01 21:35:52 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Subtype uint16
|
2018-06-23 18:43:19 +10:00
|
|
|
Hostname string `dns:"domain-name"`
|
2012-06-01 21:34:14 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *AFSDB) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
|
2012-06-01 21:34:14 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// X25 RR. See RFC 1183, Section 3.1.
|
2012-12-10 05:23:25 +11:00
|
|
|
type X25 struct {
|
2012-11-21 00:32:06 +11:00
|
|
|
Hdr RR_Header
|
2012-11-21 00:07:16 +11:00
|
|
|
PSDNAddress string
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *X25) String() string {
|
2012-11-21 00:07:16 +11:00
|
|
|
return rr.Hdr.String() + rr.PSDNAddress
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// RT RR. See RFC 1183, Section 3.3.
|
2012-12-10 05:23:25 +11:00
|
|
|
type RT struct {
|
2012-08-10 17:22:50 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
2018-11-30 23:20:24 +11:00
|
|
|
Host string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
|
2012-08-10 17:22:50 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *RT) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
|
2012-08-10 17:22:50 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NS RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NS struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Ns string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NS) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Ns)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// PTR RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type PTR struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Ptr string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *PTR) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Ptr)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// RP RR. See RFC 1138, Section 2.2.
|
2012-12-10 05:23:25 +11:00
|
|
|
type RP struct {
|
2012-05-02 06:57:22 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Mbox string `dns:"domain-name"`
|
|
|
|
Txt string `dns:"domain-name"`
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *RP) String() string {
|
2019-02-28 17:28:44 +11:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
|
2012-05-02 06:57:22 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SOA RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type SOA struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Ns string `dns:"cdomain-name"`
|
|
|
|
Mbox string `dns:"cdomain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
Serial uint32
|
|
|
|
Refresh uint32
|
|
|
|
Retry uint32
|
|
|
|
Expire uint32
|
|
|
|
Minttl uint32
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *SOA) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
|
2012-02-20 04:36:59 +11:00
|
|
|
" " + strconv.FormatInt(int64(rr.Serial), 10) +
|
|
|
|
" " + strconv.FormatInt(int64(rr.Refresh), 10) +
|
|
|
|
" " + strconv.FormatInt(int64(rr.Retry), 10) +
|
|
|
|
" " + strconv.FormatInt(int64(rr.Expire), 10) +
|
|
|
|
" " + strconv.FormatInt(int64(rr.Minttl), 10)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// TXT RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type TXT struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Txt []string `dns:"txt"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2014-02-26 21:33:33 +11:00
|
|
|
func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
|
|
|
|
2014-04-24 06:06:17 +10:00
|
|
|
func sprintName(s string) string {
|
2018-10-06 02:36:59 +10:00
|
|
|
var dst strings.Builder
|
2019-09-23 16:17:00 +10:00
|
|
|
|
2018-10-06 02:36:59 +10:00
|
|
|
for i := 0; i < len(s); {
|
2020-07-06 18:07:56 +10:00
|
|
|
if s[i] == '.' {
|
2019-09-23 16:17:00 +10:00
|
|
|
if dst.Len() != 0 {
|
2020-07-06 18:07:56 +10:00
|
|
|
dst.WriteByte('.')
|
2019-09-23 16:17:00 +10:00
|
|
|
}
|
2020-07-06 18:07:56 +10:00
|
|
|
i++
|
2018-10-06 02:36:59 +10:00
|
|
|
continue
|
2012-02-19 06:07:25 +11:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
|
|
|
|
b, n := nextByte(s, i)
|
2019-09-23 16:17:00 +10:00
|
|
|
if n == 0 {
|
2020-07-06 18:07:56 +10:00
|
|
|
// Drop "dangling" incomplete escapes.
|
|
|
|
if dst.Len() == 0 {
|
|
|
|
return s[:i]
|
2019-09-23 16:17:00 +10:00
|
|
|
}
|
2020-07-06 18:07:56 +10:00
|
|
|
break
|
2019-09-23 16:17:00 +10:00
|
|
|
}
|
2020-07-06 18:07:56 +10:00
|
|
|
if isDomainNameLabelSpecial(b) {
|
2019-09-23 16:17:00 +10:00
|
|
|
if dst.Len() == 0 {
|
|
|
|
dst.Grow(len(s) * 2)
|
|
|
|
dst.WriteString(s[:i])
|
|
|
|
}
|
|
|
|
dst.WriteByte('\\')
|
|
|
|
dst.WriteByte(b)
|
2020-07-06 18:07:56 +10:00
|
|
|
} else if b < ' ' || b > '~' { // unprintable, use \DDD
|
|
|
|
if dst.Len() == 0 {
|
|
|
|
dst.Grow(len(s) * 2)
|
|
|
|
dst.WriteString(s[:i])
|
|
|
|
}
|
|
|
|
dst.WriteString(escapeByte(b))
|
|
|
|
} else {
|
|
|
|
if dst.Len() != 0 {
|
|
|
|
dst.WriteByte(b)
|
2019-09-23 16:17:00 +10:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
}
|
|
|
|
i += n
|
2012-02-19 06:07:25 +11:00
|
|
|
}
|
2019-09-23 16:17:00 +10:00
|
|
|
if dst.Len() == 0 {
|
|
|
|
return s
|
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
return dst.String()
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
|
|
|
|
2015-07-21 16:47:38 +10:00
|
|
|
func sprintTxtOctet(s string) string {
|
2018-10-06 02:36:59 +10:00
|
|
|
var dst strings.Builder
|
|
|
|
dst.Grow(2 + len(s))
|
|
|
|
dst.WriteByte('"')
|
|
|
|
for i := 0; i < len(s); {
|
|
|
|
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
|
|
|
|
dst.WriteString(s[i : i+2])
|
2015-06-18 09:06:31 +10:00
|
|
|
i += 2
|
2018-10-06 02:36:59 +10:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
b, n := nextByte(s, i)
|
2020-05-14 05:24:22 +10:00
|
|
|
if n == 0 {
|
2018-10-06 02:36:59 +10:00
|
|
|
i++ // dangling back slash
|
2020-05-14 05:24:22 +10:00
|
|
|
} else {
|
|
|
|
writeTXTStringByte(&dst, b)
|
2015-06-18 09:06:31 +10:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
i += n
|
2015-06-18 09:06:31 +10:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
dst.WriteByte('"')
|
|
|
|
return dst.String()
|
2015-06-18 09:06:31 +10:00
|
|
|
}
|
|
|
|
|
2014-02-26 21:33:33 +11:00
|
|
|
func sprintTxt(txt []string) string {
|
2018-10-06 02:36:59 +10:00
|
|
|
var out strings.Builder
|
2014-02-26 21:33:33 +11:00
|
|
|
for i, s := range txt {
|
2018-10-06 02:36:59 +10:00
|
|
|
out.Grow(3 + len(s))
|
2014-02-26 21:33:33 +11:00
|
|
|
if i > 0 {
|
2018-10-06 02:36:59 +10:00
|
|
|
out.WriteString(` "`)
|
2014-03-01 13:42:47 +11:00
|
|
|
} else {
|
2018-10-06 02:36:59 +10:00
|
|
|
out.WriteByte('"')
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
for j := 0; j < len(s); {
|
|
|
|
b, n := nextByte(s, j)
|
2014-02-26 21:33:33 +11:00
|
|
|
if n == 0 {
|
|
|
|
break
|
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
writeTXTStringByte(&out, b)
|
2014-02-26 21:33:33 +11:00
|
|
|
j += n
|
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
out.WriteByte('"')
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
return out.String()
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
|
|
|
|
2018-10-06 02:36:59 +10:00
|
|
|
func writeTXTStringByte(s *strings.Builder, b byte) {
|
|
|
|
switch {
|
|
|
|
case b == '"' || b == '\\':
|
|
|
|
s.WriteByte('\\')
|
|
|
|
s.WriteByte(b)
|
|
|
|
case b < ' ' || b > '~':
|
2018-11-30 06:57:48 +11:00
|
|
|
s.WriteString(escapeByte(b))
|
2018-10-06 02:36:59 +10:00
|
|
|
default:
|
|
|
|
s.WriteByte(b)
|
2014-09-11 05:56:23 +10:00
|
|
|
}
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
|
|
|
|
2018-11-30 06:57:48 +11:00
|
|
|
const (
|
|
|
|
escapedByteSmall = "" +
|
|
|
|
`\000\001\002\003\004\005\006\007\008\009` +
|
|
|
|
`\010\011\012\013\014\015\016\017\018\019` +
|
|
|
|
`\020\021\022\023\024\025\026\027\028\029` +
|
|
|
|
`\030\031`
|
|
|
|
escapedByteLarge = `\127\128\129` +
|
|
|
|
`\130\131\132\133\134\135\136\137\138\139` +
|
|
|
|
`\140\141\142\143\144\145\146\147\148\149` +
|
|
|
|
`\150\151\152\153\154\155\156\157\158\159` +
|
|
|
|
`\160\161\162\163\164\165\166\167\168\169` +
|
|
|
|
`\170\171\172\173\174\175\176\177\178\179` +
|
|
|
|
`\180\181\182\183\184\185\186\187\188\189` +
|
|
|
|
`\190\191\192\193\194\195\196\197\198\199` +
|
|
|
|
`\200\201\202\203\204\205\206\207\208\209` +
|
|
|
|
`\210\211\212\213\214\215\216\217\218\219` +
|
|
|
|
`\220\221\222\223\224\225\226\227\228\229` +
|
|
|
|
`\230\231\232\233\234\235\236\237\238\239` +
|
|
|
|
`\240\241\242\243\244\245\246\247\248\249` +
|
|
|
|
`\250\251\252\253\254\255`
|
|
|
|
)
|
|
|
|
|
|
|
|
// escapeByte returns the \DDD escaping of b which must
|
|
|
|
// satisfy b < ' ' || b > '~'.
|
|
|
|
func escapeByte(b byte) string {
|
|
|
|
if b < ' ' {
|
|
|
|
return escapedByteSmall[b*4 : b*4+4]
|
2015-06-18 09:06:31 +10:00
|
|
|
}
|
2018-11-30 06:57:48 +11:00
|
|
|
|
|
|
|
b -= '~' + 1
|
|
|
|
// The cast here is needed as b*4 may overflow byte.
|
|
|
|
return escapedByteLarge[int(b)*4 : int(b)*4+4]
|
2015-06-18 09:06:31 +10:00
|
|
|
}
|
|
|
|
|
2020-07-06 18:07:56 +10:00
|
|
|
// isDomainNameLabelSpecial returns true if
|
|
|
|
// a domain name label byte should be prefixed
|
|
|
|
// with an escaping backslash.
|
|
|
|
func isDomainNameLabelSpecial(b byte) bool {
|
|
|
|
switch b {
|
|
|
|
case '.', ' ', '\'', '@', ';', '(', ')', '"', '\\':
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-10-06 02:36:59 +10:00
|
|
|
func nextByte(s string, offset int) (byte, int) {
|
|
|
|
if offset >= len(s) {
|
2014-02-26 21:33:33 +11:00
|
|
|
return 0, 0
|
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
if s[offset] != '\\' {
|
2014-02-26 21:33:33 +11:00
|
|
|
// not an escape sequence
|
2018-10-06 02:36:59 +10:00
|
|
|
return s[offset], 1
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
2018-10-06 02:36:59 +10:00
|
|
|
switch len(s) - offset {
|
2014-02-26 21:33:33 +11:00
|
|
|
case 1: // dangling escape
|
|
|
|
return 0, 0
|
|
|
|
case 2, 3: // too short to be \ddd
|
|
|
|
default: // maybe \ddd
|
2018-10-06 02:36:59 +10:00
|
|
|
if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
|
|
|
|
return dddStringToByte(s[offset+1:]), 4
|
2014-02-26 21:33:33 +11:00
|
|
|
}
|
|
|
|
}
|
2016-12-02 20:34:49 +11:00
|
|
|
// not \ddd, just an RFC 1035 "quoted" character
|
2018-10-06 02:36:59 +10:00
|
|
|
return s[offset+1], 2
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SPF RR. See RFC 4408, Section 3.1.1.
|
2012-12-10 05:23:25 +11:00
|
|
|
type SPF struct {
|
2012-02-19 04:59:19 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Txt []string `dns:"txt"`
|
2012-02-19 04:59:19 +11:00
|
|
|
}
|
|
|
|
|
2014-02-26 21:33:33 +11:00
|
|
|
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
2017-03-30 07:17:13 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
|
2017-03-30 07:17:13 +11:00
|
|
|
type AVC struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Txt []string `dns:"txt"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
2012-02-19 04:59:19 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SRV RR. See RFC 2782.
|
2012-12-10 05:23:25 +11:00
|
|
|
type SRV struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Priority uint16
|
|
|
|
Weight uint16
|
|
|
|
Port uint16
|
2012-04-30 05:55:29 +10:00
|
|
|
Target string `dns:"domain-name"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *SRV) String() string {
|
2010-08-04 07:57:59 +10:00
|
|
|
return rr.Hdr.String() +
|
|
|
|
strconv.Itoa(int(rr.Priority)) + " " +
|
|
|
|
strconv.Itoa(int(rr.Weight)) + " " +
|
2014-04-24 06:06:17 +10:00
|
|
|
strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NAPTR RR. See RFC 2915.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NAPTR struct {
|
2010-12-31 06:50:31 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Order uint16
|
2012-11-21 00:32:06 +11:00
|
|
|
Preference uint16
|
2010-12-31 06:50:31 +11:00
|
|
|
Flags string
|
|
|
|
Service string
|
|
|
|
Regexp string
|
2012-04-30 05:55:29 +10:00
|
|
|
Replacement string `dns:"domain-name"`
|
2010-12-31 06:50:31 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NAPTR) String() string {
|
2011-01-18 02:03:06 +11:00
|
|
|
return rr.Hdr.String() +
|
2011-01-17 20:30:20 +11:00
|
|
|
strconv.Itoa(int(rr.Order)) + " " +
|
2012-11-18 19:13:43 +11:00
|
|
|
strconv.Itoa(int(rr.Preference)) + " " +
|
2011-01-17 20:30:20 +11:00
|
|
|
"\"" + rr.Flags + "\" " +
|
|
|
|
"\"" + rr.Service + "\" " +
|
|
|
|
"\"" + rr.Regexp + "\" " +
|
|
|
|
rr.Replacement
|
2010-12-31 06:50:31 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// CERT RR. See RFC 4398.
|
2012-12-10 05:23:25 +11:00
|
|
|
type CERT struct {
|
2011-01-25 23:57:54 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Type uint16
|
|
|
|
KeyTag uint16
|
|
|
|
Algorithm uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
Certificate string `dns:"base64"`
|
2011-01-25 23:57:54 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *CERT) String() string {
|
2014-10-08 12:27:25 +11:00
|
|
|
var (
|
|
|
|
ok bool
|
|
|
|
certtype, algorithm string
|
|
|
|
)
|
|
|
|
if certtype, ok = CertTypeToString[rr.Type]; !ok {
|
|
|
|
certtype = strconv.Itoa(int(rr.Type))
|
|
|
|
}
|
|
|
|
if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok {
|
|
|
|
algorithm = strconv.Itoa(int(rr.Algorithm))
|
|
|
|
}
|
|
|
|
return rr.Hdr.String() + certtype +
|
2011-01-25 23:57:54 +11:00
|
|
|
" " + strconv.Itoa(int(rr.KeyTag)) +
|
2014-10-08 12:27:25 +11:00
|
|
|
" " + algorithm +
|
2011-01-25 23:57:54 +11:00
|
|
|
" " + rr.Certificate
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// DNAME RR. See RFC 2672.
|
2012-12-10 05:23:25 +11:00
|
|
|
type DNAME struct {
|
2011-01-25 23:57:54 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Target string `dns:"domain-name"`
|
2011-01-25 23:47:12 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *DNAME) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + sprintName(rr.Target)
|
2011-01-25 23:47:12 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// A RR. See RFC 1035.
|
2012-12-10 05:23:25 +11:00
|
|
|
type A struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
A net.IP `dns:"a"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2013-09-01 05:07:13 +10:00
|
|
|
func (rr *A) String() string {
|
|
|
|
if rr.A == nil {
|
|
|
|
return rr.Hdr.String()
|
|
|
|
}
|
|
|
|
return rr.Hdr.String() + rr.A.String()
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// AAAA RR. See RFC 3596.
|
2012-12-10 05:23:25 +11:00
|
|
|
type AAAA struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
AAAA net.IP `dns:"aaaa"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2013-09-01 05:07:13 +10:00
|
|
|
func (rr *AAAA) String() string {
|
|
|
|
if rr.AAAA == nil {
|
|
|
|
return rr.Hdr.String()
|
|
|
|
}
|
|
|
|
return rr.Hdr.String() + rr.AAAA.String()
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// PX RR. See RFC 2163.
|
2013-10-13 23:23:02 +11:00
|
|
|
type PX struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
Map822 string `dns:"domain-name"`
|
|
|
|
Mapx400 string `dns:"domain-name"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *PX) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
|
2013-10-13 23:23:02 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// GPOS RR. See RFC 1712.
|
2013-10-13 23:01:33 +11:00
|
|
|
type GPOS struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Longitude string
|
|
|
|
Latitude string
|
|
|
|
Altitude string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *GPOS) String() string {
|
|
|
|
return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// LOC RR. See RFC RFC 1876.
|
2012-12-10 05:23:25 +11:00
|
|
|
type LOC struct {
|
2011-01-02 05:26:08 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Version uint8
|
|
|
|
Size uint8
|
|
|
|
HorizPre uint8
|
|
|
|
VertPre uint8
|
|
|
|
Latitude uint32
|
|
|
|
Longitude uint32
|
|
|
|
Altitude uint32
|
2010-12-31 06:55:25 +11:00
|
|
|
}
|
|
|
|
|
2020-02-15 08:47:21 +11:00
|
|
|
// cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
|
|
|
|
// format and returns a string in m (two decimals for the cm).
|
2014-03-27 23:43:13 +11:00
|
|
|
func cmToM(m, e uint8) string {
|
|
|
|
if e < 2 {
|
|
|
|
if e == 1 {
|
|
|
|
m *= 10
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("0.%02d", m)
|
|
|
|
}
|
|
|
|
|
|
|
|
s := fmt.Sprintf("%d", m)
|
|
|
|
for e > 2 {
|
|
|
|
s += "0"
|
2015-02-19 20:58:33 +11:00
|
|
|
e--
|
2014-03-27 23:43:13 +11:00
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *LOC) String() string {
|
2012-04-30 22:50:52 +10:00
|
|
|
s := rr.Hdr.String()
|
2014-03-27 23:43:13 +11:00
|
|
|
|
2012-04-30 22:50:52 +10:00
|
|
|
lat := rr.Latitude
|
2014-03-27 23:43:13 +11:00
|
|
|
ns := "N"
|
|
|
|
if lat > LOC_EQUATOR {
|
|
|
|
lat = lat - LOC_EQUATOR
|
2012-04-30 22:50:52 +10:00
|
|
|
} else {
|
2014-03-27 23:43:13 +11:00
|
|
|
ns = "S"
|
|
|
|
lat = LOC_EQUATOR - lat
|
2012-04-30 22:50:52 +10:00
|
|
|
}
|
2014-03-27 23:43:13 +11:00
|
|
|
h := lat / LOC_DEGREES
|
|
|
|
lat = lat % LOC_DEGREES
|
|
|
|
m := lat / LOC_HOURS
|
|
|
|
lat = lat % LOC_HOURS
|
2018-08-17 02:05:27 +10:00
|
|
|
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns)
|
2014-03-27 23:43:13 +11:00
|
|
|
|
2012-04-30 22:50:52 +10:00
|
|
|
lon := rr.Longitude
|
2014-03-27 23:43:13 +11:00
|
|
|
ew := "E"
|
|
|
|
if lon > LOC_PRIMEMERIDIAN {
|
|
|
|
lon = lon - LOC_PRIMEMERIDIAN
|
2012-04-30 22:50:52 +10:00
|
|
|
} else {
|
2014-03-27 23:43:13 +11:00
|
|
|
ew = "W"
|
|
|
|
lon = LOC_PRIMEMERIDIAN - lon
|
2012-04-30 22:50:52 +10:00
|
|
|
}
|
2014-03-27 23:43:13 +11:00
|
|
|
h = lon / LOC_DEGREES
|
|
|
|
lon = lon % LOC_DEGREES
|
|
|
|
m = lon / LOC_HOURS
|
|
|
|
lon = lon % LOC_HOURS
|
2018-08-17 02:05:27 +10:00
|
|
|
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
|
2014-03-27 23:43:13 +11:00
|
|
|
|
2015-02-19 22:41:12 +11:00
|
|
|
var alt = float64(rr.Altitude) / 100
|
2014-03-27 23:43:13 +11:00
|
|
|
alt -= LOC_ALTITUDEBASE
|
|
|
|
if rr.Altitude%100 != 0 {
|
|
|
|
s += fmt.Sprintf("%.2fm ", alt)
|
2012-04-30 22:50:52 +10:00
|
|
|
} else {
|
2014-03-27 23:43:13 +11:00
|
|
|
s += fmt.Sprintf("%.0fm ", alt)
|
2012-04-30 22:50:52 +10:00
|
|
|
}
|
2014-03-27 23:43:13 +11:00
|
|
|
|
2018-08-17 02:05:27 +10:00
|
|
|
s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m "
|
|
|
|
s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m "
|
|
|
|
s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m"
|
2014-03-27 23:43:13 +11:00
|
|
|
|
2012-04-30 22:50:52 +10:00
|
|
|
return s
|
2010-12-31 06:55:25 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
|
2014-11-01 22:32:46 +11:00
|
|
|
type SIG struct {
|
2014-11-10 03:09:49 +11:00
|
|
|
RRSIG
|
2014-11-01 22:32:46 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// RRSIG RR. See RFC 4034 and RFC 3755.
|
2012-12-10 05:23:25 +11:00
|
|
|
type RRSIG struct {
|
2010-12-23 21:02:01 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
TypeCovered uint16
|
|
|
|
Algorithm uint8
|
|
|
|
Labels uint8
|
|
|
|
OrigTtl uint32
|
|
|
|
Expiration uint32
|
|
|
|
Inception uint32
|
|
|
|
KeyTag uint16
|
2012-04-30 05:55:29 +10:00
|
|
|
SignerName string `dns:"domain-name"`
|
|
|
|
Signature string `dns:"base64"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *RRSIG) String() string {
|
2013-06-08 22:59:49 +10:00
|
|
|
s := rr.Hdr.String()
|
2013-06-08 23:09:37 +10:00
|
|
|
s += Type(rr.TypeCovered).String()
|
2013-06-08 22:59:49 +10:00
|
|
|
s += " " + strconv.Itoa(int(rr.Algorithm)) +
|
2010-12-21 08:20:13 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Labels)) +
|
2012-02-20 04:36:59 +11:00
|
|
|
" " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
|
2012-09-12 05:45:21 +10:00
|
|
|
" " + TimeToString(rr.Expiration) +
|
|
|
|
" " + TimeToString(rr.Inception) +
|
2010-12-21 08:20:13 +11:00
|
|
|
" " + strconv.Itoa(int(rr.KeyTag)) +
|
2014-04-24 06:06:17 +10:00
|
|
|
" " + sprintName(rr.SignerName) +
|
2010-12-29 00:57:30 +11:00
|
|
|
" " + rr.Signature
|
2013-06-08 22:59:49 +10:00
|
|
|
return s
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NSEC RR. See RFC 4034 and RFC 3755.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NSEC struct {
|
2010-12-24 02:37:54 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
NextDomain string `dns:"domain-name"`
|
|
|
|
TypeBitMap []uint16 `dns:"nsec"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NSEC) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
s := rr.Hdr.String() + sprintName(rr.NextDomain)
|
2019-03-18 18:06:44 +11:00
|
|
|
for _, t := range rr.TypeBitMap {
|
|
|
|
s += " " + Type(t).String()
|
2011-01-17 20:30:20 +11:00
|
|
|
}
|
|
|
|
return s
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2018-11-30 10:33:41 +11:00
|
|
|
func (rr *NSEC) len(off int, compression map[string]struct{}) int {
|
|
|
|
l := rr.Hdr.len(off, compression)
|
|
|
|
l += domainNameLen(rr.NextDomain, off+l, compression, false)
|
2019-05-21 16:27:24 +10:00
|
|
|
l += typeBitMapLen(rr.TypeBitMap)
|
2013-06-28 05:19:02 +10:00
|
|
|
return l
|
2012-01-10 20:43:28 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// DLV RR. See RFC 4431.
|
|
|
|
type DLV struct{ DS }
|
2014-11-02 22:29:55 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// CDS RR. See RFC 7344.
|
|
|
|
type CDS struct{ DS }
|
2014-11-02 22:29:55 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// DS RR. See RFC 4034 and RFC 3658.
|
2012-12-10 05:23:25 +11:00
|
|
|
type DS struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
KeyTag uint16
|
|
|
|
Algorithm uint8
|
|
|
|
DigestType uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
Digest string `dns:"hex"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *DS) String() string {
|
2011-01-18 02:03:06 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
|
2010-12-27 19:58:45 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Algorithm)) +
|
2010-08-04 07:57:59 +10:00
|
|
|
" " + strconv.Itoa(int(rr.DigestType)) +
|
2010-12-27 23:56:58 +11:00
|
|
|
" " + strings.ToUpper(rr.Digest)
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// KX RR. See RFC 2230.
|
2012-12-10 05:23:25 +11:00
|
|
|
type KX struct {
|
2012-11-21 00:32:06 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
Exchanger string `dns:"domain-name"`
|
2011-03-13 23:04:54 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *KX) String() string {
|
2012-11-18 19:13:43 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
|
2014-04-24 06:06:17 +10:00
|
|
|
" " + sprintName(rr.Exchanger)
|
2011-03-13 23:04:54 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
|
2012-12-10 05:23:25 +11:00
|
|
|
type TA struct {
|
2011-02-21 23:16:07 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
KeyTag uint16
|
|
|
|
Algorithm uint8
|
|
|
|
DigestType uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
Digest string `dns:"hex"`
|
2011-02-21 23:16:07 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *TA) String() string {
|
2011-02-21 23:16:07 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Algorithm)) +
|
|
|
|
" " + strconv.Itoa(int(rr.DigestType)) +
|
|
|
|
" " + strings.ToUpper(rr.Digest)
|
|
|
|
}
|
2011-01-17 20:30:20 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
|
2012-12-10 05:23:25 +11:00
|
|
|
type TALINK struct {
|
2011-02-21 23:24:45 +11:00
|
|
|
Hdr RR_Header
|
2013-08-27 14:11:24 +10:00
|
|
|
PreviousName string `dns:"domain-name"`
|
|
|
|
NextName string `dns:"domain-name"`
|
2011-02-21 23:24:45 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *TALINK) String() string {
|
2011-02-21 23:24:45 +11:00
|
|
|
return rr.Hdr.String() +
|
2014-11-29 06:03:55 +11:00
|
|
|
sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
|
2011-02-21 23:24:45 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SSHFP RR. See RFC RFC 4255.
|
2012-12-10 05:23:25 +11:00
|
|
|
type SSHFP struct {
|
2011-01-17 20:30:20 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Algorithm uint8
|
|
|
|
Type uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
FingerPrint string `dns:"hex"`
|
2011-01-17 20:30:20 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *SSHFP) String() string {
|
2011-01-18 02:03:06 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
|
2011-01-17 20:30:20 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Type)) +
|
|
|
|
" " + strings.ToUpper(rr.FingerPrint)
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// KEY RR. See RFC RFC 2535.
|
2014-11-01 22:32:46 +11:00
|
|
|
type KEY struct {
|
2014-11-10 03:09:49 +11:00
|
|
|
DNSKEY
|
2014-11-01 22:32:46 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// CDNSKEY RR. See RFC 7344.
|
2014-11-02 22:29:55 +11:00
|
|
|
type CDNSKEY struct {
|
2014-11-10 03:09:49 +11:00
|
|
|
DNSKEY
|
2014-11-02 22:29:55 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// DNSKEY RR. See RFC 4034 and RFC 3755.
|
2012-12-10 05:23:25 +11:00
|
|
|
type DNSKEY struct {
|
2010-08-04 07:57:59 +10:00
|
|
|
Hdr RR_Header
|
|
|
|
Flags uint16
|
|
|
|
Protocol uint8
|
|
|
|
Algorithm uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
PublicKey string `dns:"base64"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *DNSKEY) String() string {
|
2012-02-19 06:07:25 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
|
2010-08-04 07:57:59 +10:00
|
|
|
" " + strconv.Itoa(int(rr.Protocol)) +
|
2010-12-21 08:20:13 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Algorithm)) +
|
2011-01-25 23:57:54 +11:00
|
|
|
" " + rr.PublicKey
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
|
2012-12-10 05:23:25 +11:00
|
|
|
type RKEY struct {
|
2012-11-21 02:48:28 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Flags uint16
|
|
|
|
Protocol uint8
|
|
|
|
Algorithm uint8
|
|
|
|
PublicKey string `dns:"base64"`
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *RKEY) String() string {
|
2012-11-21 02:48:28 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Protocol)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Algorithm)) +
|
|
|
|
" " + rr.PublicKey
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NSAPPTR RR. See RFC 1348.
|
2013-10-13 22:25:08 +11:00
|
|
|
type NSAPPTR struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Ptr string `dns:"domain-name"`
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
|
2013-10-13 22:25:08 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NSEC3 RR. See RFC 5155.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NSEC3 struct {
|
2010-12-24 02:37:54 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Hash uint8
|
|
|
|
Flags uint8
|
|
|
|
Iterations uint16
|
|
|
|
SaltLength uint8
|
2016-06-13 03:31:50 +10:00
|
|
|
Salt string `dns:"size-hex:SaltLength"`
|
2010-12-24 02:37:54 +11:00
|
|
|
HashLength uint8
|
2016-06-13 03:31:50 +10:00
|
|
|
NextDomain string `dns:"size-base32:HashLength"`
|
2012-04-30 05:55:29 +10:00
|
|
|
TypeBitMap []uint16 `dns:"nsec"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NSEC3) String() string {
|
2011-01-17 20:30:20 +11:00
|
|
|
s := rr.Hdr.String()
|
2011-01-18 02:03:06 +11:00
|
|
|
s += strconv.Itoa(int(rr.Hash)) +
|
2011-01-17 20:30:20 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Flags)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Iterations)) +
|
2013-04-16 02:34:21 +10:00
|
|
|
" " + saltToString(rr.Salt) +
|
2011-02-22 02:21:16 +11:00
|
|
|
" " + rr.NextDomain
|
2019-03-18 18:06:44 +11:00
|
|
|
for _, t := range rr.TypeBitMap {
|
|
|
|
s += " " + Type(t).String()
|
2011-01-17 20:30:20 +11:00
|
|
|
}
|
|
|
|
return s
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2018-11-30 10:33:41 +11:00
|
|
|
func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
|
|
|
|
l := rr.Hdr.len(off, compression)
|
|
|
|
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
|
2019-05-21 16:27:24 +10:00
|
|
|
l += typeBitMapLen(rr.TypeBitMap)
|
2013-06-28 05:19:02 +10:00
|
|
|
return l
|
2012-01-10 20:43:28 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NSEC3PARAM RR. See RFC 5155.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NSEC3PARAM struct {
|
2010-12-24 02:37:54 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Hash uint8
|
|
|
|
Flags uint8
|
|
|
|
Iterations uint16
|
|
|
|
SaltLength uint8
|
2016-07-26 13:20:27 +10:00
|
|
|
Salt string `dns:"size-hex:SaltLength"`
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NSEC3PARAM) String() string {
|
2011-01-18 02:03:06 +11:00
|
|
|
s := rr.Hdr.String()
|
2011-01-25 23:57:54 +11:00
|
|
|
s += strconv.Itoa(int(rr.Hash)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Flags)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Iterations)) +
|
2013-04-16 02:34:21 +10:00
|
|
|
" " + saltToString(rr.Salt)
|
2011-01-25 23:57:54 +11:00
|
|
|
return s
|
2010-08-04 07:57:59 +10:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// TKEY RR. See RFC 2930.
|
2012-12-10 05:23:25 +11:00
|
|
|
type TKEY struct {
|
2011-01-02 05:26:08 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Algorithm string `dns:"domain-name"`
|
2011-01-02 05:26:08 +11:00
|
|
|
Inception uint32
|
|
|
|
Expiration uint32
|
|
|
|
Mode uint16
|
|
|
|
Error uint16
|
|
|
|
KeySize uint16
|
2017-11-28 18:48:02 +11:00
|
|
|
Key string `dns:"size-hex:KeySize"`
|
2012-06-21 01:12:10 +10:00
|
|
|
OtherLen uint16
|
2017-11-28 18:48:02 +11:00
|
|
|
OtherData string `dns:"size-hex:OtherLen"`
|
2011-01-02 05:26:08 +11:00
|
|
|
}
|
|
|
|
|
2017-11-28 18:48:02 +11:00
|
|
|
// TKEY has no official presentation format, but this will suffice.
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *TKEY) String() string {
|
2018-12-04 18:31:40 +11:00
|
|
|
s := ";" + rr.Hdr.String() +
|
|
|
|
" " + rr.Algorithm +
|
|
|
|
" " + TimeToString(rr.Inception) +
|
|
|
|
" " + TimeToString(rr.Expiration) +
|
|
|
|
" " + strconv.Itoa(int(rr.Mode)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Error)) +
|
|
|
|
" " + strconv.Itoa(int(rr.KeySize)) +
|
|
|
|
" " + rr.Key +
|
|
|
|
" " + strconv.Itoa(int(rr.OtherLen)) +
|
|
|
|
" " + rr.OtherData
|
2017-11-28 18:48:02 +11:00
|
|
|
return s
|
2011-01-02 05:26:08 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// RFC3597 represents an unknown/generic RR. See RFC 3597.
|
2012-12-10 05:23:25 +11:00
|
|
|
type RFC3597 struct {
|
2011-02-25 02:22:14 +11:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Rdata string `dns:"hex"`
|
2011-02-22 01:19:52 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *RFC3597) String() string {
|
2014-11-02 22:06:05 +11:00
|
|
|
// Let's call it a hack
|
|
|
|
s := rfc3597Header(rr.Hdr)
|
|
|
|
|
2011-02-25 02:22:14 +11:00
|
|
|
s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
|
|
|
|
return s
|
2011-02-22 01:19:52 +11:00
|
|
|
}
|
|
|
|
|
2014-11-02 22:06:05 +11:00
|
|
|
func rfc3597Header(h RR_Header) string {
|
|
|
|
var s string
|
|
|
|
|
|
|
|
s += sprintName(h.Name) + "\t"
|
|
|
|
s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
|
|
|
|
s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t"
|
|
|
|
s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t"
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// URI RR. See RFC 7553.
|
2012-12-10 05:23:25 +11:00
|
|
|
type URI struct {
|
2011-02-25 02:22:14 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Priority uint16
|
|
|
|
Weight uint16
|
2015-07-21 16:47:38 +10:00
|
|
|
Target string `dns:"octet"`
|
2011-02-23 19:11:03 +11:00
|
|
|
}
|
|
|
|
|
2020-05-14 05:24:22 +10:00
|
|
|
// rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *URI) String() string {
|
2014-02-26 21:33:33 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
|
2015-07-28 07:12:46 +10:00
|
|
|
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
|
2012-01-10 20:43:28 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// DHCID RR. See RFC 4701.
|
2012-12-10 05:23:25 +11:00
|
|
|
type DHCID struct {
|
2011-07-23 17:21:24 +10:00
|
|
|
Hdr RR_Header
|
2012-04-30 05:55:29 +10:00
|
|
|
Digest string `dns:"base64"`
|
2011-03-13 23:11:11 +11:00
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
|
2012-01-10 20:43:28 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// TLSA RR. See RFC 6698.
|
2012-12-10 05:23:25 +11:00
|
|
|
type TLSA struct {
|
2012-01-16 20:11:05 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Usage uint8
|
|
|
|
Selector uint8
|
|
|
|
MatchingType uint8
|
2012-04-30 05:55:29 +10:00
|
|
|
Certificate string `dns:"hex"`
|
2012-01-16 20:06:21 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *TLSA) String() string {
|
2012-01-16 20:06:21 +11:00
|
|
|
return rr.Hdr.String() +
|
2014-11-29 06:03:55 +11:00
|
|
|
strconv.Itoa(int(rr.Usage)) +
|
2012-01-16 20:06:21 +11:00
|
|
|
" " + strconv.Itoa(int(rr.Selector)) +
|
|
|
|
" " + strconv.Itoa(int(rr.MatchingType)) +
|
|
|
|
" " + rr.Certificate
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// SMIMEA RR. See RFC 8162.
|
2016-10-18 04:09:52 +11:00
|
|
|
type SMIMEA struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Usage uint8
|
|
|
|
Selector uint8
|
|
|
|
MatchingType uint8
|
|
|
|
Certificate string `dns:"hex"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *SMIMEA) String() string {
|
|
|
|
s := rr.Hdr.String() +
|
|
|
|
strconv.Itoa(int(rr.Usage)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Selector)) +
|
|
|
|
" " + strconv.Itoa(int(rr.MatchingType))
|
|
|
|
|
|
|
|
// Every Nth char needs a space on this output. If we output
|
|
|
|
// this as one giant line, we can't read it can in because in some cases
|
|
|
|
// the cert length overflows scan.maxTok (2048).
|
|
|
|
sx := splitN(rr.Certificate, 1024) // conservative value here
|
|
|
|
s += " " + strings.Join(sx, " ")
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// HIP RR. See RFC 8005.
|
2012-12-10 05:23:25 +11:00
|
|
|
type HIP struct {
|
2012-02-19 06:07:25 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
HitLength uint8
|
|
|
|
PublicKeyAlgorithm uint8
|
|
|
|
PublicKeyLength uint16
|
2016-06-13 03:31:50 +10:00
|
|
|
Hit string `dns:"size-hex:HitLength"`
|
|
|
|
PublicKey string `dns:"size-base64:PublicKeyLength"`
|
2012-04-30 05:55:29 +10:00
|
|
|
RendezvousServers []string `dns:"domain-name"`
|
2012-02-19 06:07:25 +11:00
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *HIP) String() string {
|
2012-02-20 01:24:26 +11:00
|
|
|
s := rr.Hdr.String() +
|
2014-11-29 06:03:55 +11:00
|
|
|
strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
|
2012-02-19 06:07:25 +11:00
|
|
|
" " + rr.Hit +
|
|
|
|
" " + rr.PublicKey
|
2012-02-20 01:24:26 +11:00
|
|
|
for _, d := range rr.RendezvousServers {
|
2014-04-24 06:06:17 +10:00
|
|
|
s += " " + sprintName(d)
|
2012-02-20 01:24:26 +11:00
|
|
|
}
|
|
|
|
return s
|
2012-02-19 06:07:25 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NINFO struct {
|
2012-11-21 02:52:18 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
ZSData []string `dns:"txt"`
|
2012-11-21 02:42:16 +11:00
|
|
|
}
|
|
|
|
|
2014-02-26 21:33:33 +11:00
|
|
|
func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
|
2012-11-21 02:42:16 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NID RR. See RFC RFC 6742.
|
2012-12-10 05:23:25 +11:00
|
|
|
type NID struct {
|
2012-11-18 07:26:48 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
NodeID uint64
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *NID) String() string {
|
2012-11-18 07:26:48 +11:00
|
|
|
s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
|
2012-11-18 09:01:35 +11:00
|
|
|
node := fmt.Sprintf("%0.16x", rr.NodeID)
|
2012-11-18 20:29:05 +11:00
|
|
|
s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
|
2012-11-18 07:26:48 +11:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// L32 RR, See RFC 6742.
|
2012-12-10 05:23:25 +11:00
|
|
|
type L32 struct {
|
2012-11-18 07:32:02 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
Locator32 net.IP `dns:"a"`
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *L32) String() string {
|
2013-09-01 05:24:52 +10:00
|
|
|
if rr.Locator32 == nil {
|
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
|
|
|
|
}
|
2012-11-18 20:29:05 +11:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
|
|
|
|
" " + rr.Locator32.String()
|
2012-11-18 07:32:02 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// L64 RR, See RFC 6742.
|
2012-12-10 05:23:25 +11:00
|
|
|
type L64 struct {
|
2012-11-18 07:37:15 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
Locator64 uint64
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *L64) String() string {
|
2012-11-18 07:37:15 +11:00
|
|
|
s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
|
2012-11-18 19:10:28 +11:00
|
|
|
node := fmt.Sprintf("%0.16X", rr.Locator64)
|
2012-11-18 20:29:05 +11:00
|
|
|
s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
|
2012-11-18 07:37:15 +11:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// LP RR. See RFC 6742.
|
2012-12-10 05:23:25 +11:00
|
|
|
type LP struct {
|
2012-11-18 07:43:09 +11:00
|
|
|
Hdr RR_Header
|
|
|
|
Preference uint16
|
|
|
|
Fqdn string `dns:"domain-name"`
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:23:25 +11:00
|
|
|
func (rr *LP) String() string {
|
2014-04-24 06:06:17 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
|
2012-11-18 07:43:09 +11:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// EUI48 RR. See RFC 7043.
|
2013-04-16 02:34:21 +10:00
|
|
|
type EUI48 struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Address uint64 `dns:"uint48"`
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
|
2013-04-16 02:34:21 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// EUI64 RR. See RFC 7043.
|
2013-04-16 02:34:21 +10:00
|
|
|
type EUI64 struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Address uint64
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
|
2013-04-16 02:34:21 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// CAA RR. See RFC 6844.
|
2013-04-30 23:04:07 +10:00
|
|
|
type CAA struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Flag uint8
|
|
|
|
Tag string
|
2015-06-18 09:06:31 +10:00
|
|
|
Value string `dns:"octet"`
|
2013-04-30 23:04:07 +10:00
|
|
|
}
|
|
|
|
|
2020-05-14 05:24:22 +10:00
|
|
|
// rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
|
2015-06-29 10:20:16 +10:00
|
|
|
func (rr *CAA) String() string {
|
2015-07-21 16:47:38 +10:00
|
|
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
|
2015-06-29 10:20:16 +10:00
|
|
|
}
|
2013-04-30 23:04:07 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// UID RR. Deprecated, IANA-Reserved.
|
2013-05-01 00:42:04 +10:00
|
|
|
type UID struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Uid uint32
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
|
2013-05-01 00:42:04 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// GID RR. Deprecated, IANA-Reserved.
|
2013-05-01 00:42:04 +10:00
|
|
|
type GID struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Gid uint32
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
|
2013-05-01 00:42:04 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// UINFO RR. Deprecated, IANA-Reserved.
|
2013-05-01 00:42:04 +10:00
|
|
|
type UINFO struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Uinfo string
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
|
2013-05-01 00:42:04 +10:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
|
2013-10-20 07:31:12 +11:00
|
|
|
type EID struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Endpoint string `dns:"hex"`
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
|
2013-10-20 07:31:12 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
|
2013-10-20 07:31:12 +11:00
|
|
|
type NIMLOC struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Locator string `dns:"hex"`
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
|
2013-10-20 07:31:12 +11:00
|
|
|
|
2017-11-08 00:45:27 +11:00
|
|
|
// OPENPGPKEY RR. See RFC 7929.
|
2014-07-24 18:29:42 +10:00
|
|
|
type OPENPGPKEY struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
PublicKey string `dns:"base64"`
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:33:08 +11:00
|
|
|
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
|
2014-07-24 18:29:42 +10:00
|
|
|
|
Implement CSYNC (#585)
Implement the CSYNC record.
Fixes #290
Long overdue, lets add this record. Similar in vain as NSEC/NSEC3, we
need to implement len() our selves. Presentation format parsing and
tests are done as well.
This is CoreDNS running with CSYNC support, `dig` doesn't support this
at the moment, so:
~~~
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40323
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;csync.example.org. IN TYPE62
;; ANSWER SECTION:
csync.example.org. 10 IN TYPE62 \# 12 000335240042000460000008
;; AUTHORITY SECTION:
example.org. 10 IN NS a.iana-servers.net.
example.org. 10 IN NS b.iana-servers.net.
~~~
2017-11-25 19:19:06 +11:00
|
|
|
// CSYNC RR. See RFC 7477.
|
|
|
|
type CSYNC struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Serial uint32
|
|
|
|
Flags uint16
|
|
|
|
TypeBitMap []uint16 `dns:"nsec"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *CSYNC) String() string {
|
|
|
|
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
|
|
|
|
|
2019-03-18 18:06:44 +11:00
|
|
|
for _, t := range rr.TypeBitMap {
|
|
|
|
s += " " + Type(t).String()
|
Implement CSYNC (#585)
Implement the CSYNC record.
Fixes #290
Long overdue, lets add this record. Similar in vain as NSEC/NSEC3, we
need to implement len() our selves. Presentation format parsing and
tests are done as well.
This is CoreDNS running with CSYNC support, `dig` doesn't support this
at the moment, so:
~~~
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40323
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;csync.example.org. IN TYPE62
;; ANSWER SECTION:
csync.example.org. 10 IN TYPE62 \# 12 000335240042000460000008
;; AUTHORITY SECTION:
example.org. 10 IN NS a.iana-servers.net.
example.org. 10 IN NS b.iana-servers.net.
~~~
2017-11-25 19:19:06 +11:00
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2018-11-30 10:33:41 +11:00
|
|
|
func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
|
|
|
|
l := rr.Hdr.len(off, compression)
|
|
|
|
l += 4 + 2
|
2019-05-21 16:27:24 +10:00
|
|
|
l += typeBitMapLen(rr.TypeBitMap)
|
Implement CSYNC (#585)
Implement the CSYNC record.
Fixes #290
Long overdue, lets add this record. Similar in vain as NSEC/NSEC3, we
need to implement len() our selves. Presentation format parsing and
tests are done as well.
This is CoreDNS running with CSYNC support, `dig` doesn't support this
at the moment, so:
~~~
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40323
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;csync.example.org. IN TYPE62
;; ANSWER SECTION:
csync.example.org. 10 IN TYPE62 \# 12 000335240042000460000008
;; AUTHORITY SECTION:
example.org. 10 IN NS a.iana-servers.net.
example.org. 10 IN NS b.iana-servers.net.
~~~
2017-11-25 19:19:06 +11:00
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2021-02-27 02:35:05 +11:00
|
|
|
// ZONEMD RR, from draft-ietf-dnsop-dns-zone-digest
|
|
|
|
type ZONEMD struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Serial uint32
|
|
|
|
Scheme uint8
|
|
|
|
Hash uint8
|
|
|
|
Digest string `dns:"hex"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rr *ZONEMD) String() string {
|
|
|
|
return rr.Hdr.String() +
|
|
|
|
strconv.Itoa(int(rr.Serial)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Scheme)) +
|
|
|
|
" " + strconv.Itoa(int(rr.Hash)) +
|
|
|
|
" " + rr.Digest
|
|
|
|
}
|
|
|
|
|
2020-01-03 23:41:45 +11:00
|
|
|
// APL RR. See RFC 3123.
|
|
|
|
type APL struct {
|
|
|
|
Hdr RR_Header
|
|
|
|
Prefixes []APLPrefix `dns:"apl"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// APLPrefix is an address prefix hold by an APL record.
|
|
|
|
type APLPrefix struct {
|
|
|
|
Negation bool
|
|
|
|
Network net.IPNet
|
|
|
|
}
|
|
|
|
|
|
|
|
// String returns presentation form of the APL record.
|
|
|
|
func (rr *APL) String() string {
|
|
|
|
var sb strings.Builder
|
|
|
|
sb.WriteString(rr.Hdr.String())
|
|
|
|
for i, p := range rr.Prefixes {
|
|
|
|
if i > 0 {
|
|
|
|
sb.WriteByte(' ')
|
|
|
|
}
|
|
|
|
sb.WriteString(p.str())
|
|
|
|
}
|
|
|
|
return sb.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// str returns presentation form of the APL prefix.
|
2021-06-17 19:05:49 +10:00
|
|
|
func (a *APLPrefix) str() string {
|
2020-01-03 23:41:45 +11:00
|
|
|
var sb strings.Builder
|
2021-06-17 19:05:49 +10:00
|
|
|
if a.Negation {
|
2020-01-03 23:41:45 +11:00
|
|
|
sb.WriteByte('!')
|
|
|
|
}
|
|
|
|
|
2021-06-17 19:05:49 +10:00
|
|
|
switch len(a.Network.IP) {
|
2020-01-03 23:41:45 +11:00
|
|
|
case net.IPv4len:
|
|
|
|
sb.WriteByte('1')
|
|
|
|
case net.IPv6len:
|
|
|
|
sb.WriteByte('2')
|
|
|
|
}
|
|
|
|
|
|
|
|
sb.WriteByte(':')
|
|
|
|
|
2021-06-17 19:05:49 +10:00
|
|
|
switch len(a.Network.IP) {
|
2020-01-03 23:41:45 +11:00
|
|
|
case net.IPv4len:
|
2021-06-17 19:05:49 +10:00
|
|
|
sb.WriteString(a.Network.IP.String())
|
2020-01-03 23:41:45 +11:00
|
|
|
case net.IPv6len:
|
|
|
|
// add prefix for IPv4-mapped IPv6
|
2021-06-17 19:05:49 +10:00
|
|
|
if v4 := a.Network.IP.To4(); v4 != nil {
|
2020-01-03 23:41:45 +11:00
|
|
|
sb.WriteString("::ffff:")
|
|
|
|
}
|
2021-06-17 19:05:49 +10:00
|
|
|
sb.WriteString(a.Network.IP.String())
|
2020-01-03 23:41:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
sb.WriteByte('/')
|
|
|
|
|
2021-06-17 19:05:49 +10:00
|
|
|
prefix, _ := a.Network.Mask.Size()
|
2020-01-03 23:41:45 +11:00
|
|
|
sb.WriteString(strconv.Itoa(prefix))
|
|
|
|
|
|
|
|
return sb.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// equals reports whether two APL prefixes are identical.
|
|
|
|
func (a *APLPrefix) equals(b *APLPrefix) bool {
|
|
|
|
return a.Negation == b.Negation &&
|
|
|
|
bytes.Equal(a.Network.IP, b.Network.IP) &&
|
|
|
|
bytes.Equal(a.Network.Mask, b.Network.Mask)
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy returns a copy of the APL prefix.
|
2021-06-17 19:05:49 +10:00
|
|
|
func (a *APLPrefix) copy() APLPrefix {
|
2020-01-03 23:41:45 +11:00
|
|
|
return APLPrefix{
|
2021-06-17 19:05:49 +10:00
|
|
|
Negation: a.Negation,
|
|
|
|
Network: copyNet(a.Network),
|
2020-01-03 23:41:45 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// len returns size of the prefix in wire format.
|
2021-06-17 19:05:49 +10:00
|
|
|
func (a *APLPrefix) len() int {
|
2020-01-03 23:41:45 +11:00
|
|
|
// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
|
2021-06-17 19:05:49 +10:00
|
|
|
prefix, _ := a.Network.Mask.Size()
|
2020-01-03 23:41:45 +11:00
|
|
|
return 4 + (prefix+7)/8
|
|
|
|
}
|
|
|
|
|
2012-09-12 05:45:21 +10:00
|
|
|
// TimeToString translates the RRSIG's incep. and expir. times to the
|
2012-04-11 23:13:17 +10:00
|
|
|
// string representation used when printing the record.
|
2012-05-15 20:27:40 +10:00
|
|
|
// It takes serial arithmetic (RFC 1982) into account.
|
2012-09-12 05:45:21 +10:00
|
|
|
func TimeToString(t uint32) string {
|
2018-08-17 02:05:27 +10:00
|
|
|
mod := (int64(t)-time.Now().Unix())/year68 - 1
|
2012-05-15 20:24:57 +10:00
|
|
|
if mod < 0 {
|
|
|
|
mod = 0
|
|
|
|
}
|
2018-08-17 02:05:27 +10:00
|
|
|
ti := time.Unix(int64(t)-mod*year68, 0).UTC()
|
2011-07-25 05:29:16 +10:00
|
|
|
return ti.Format("20060102150405")
|
2011-12-15 22:41:24 +11:00
|
|
|
}
|
|
|
|
|
2013-04-16 02:34:21 +10:00
|
|
|
// StringToTime translates the RRSIG's incep. and expir. times from
|
2012-04-11 23:13:17 +10:00
|
|
|
// string values like "20110403154150" to an 32 bit integer.
|
2012-05-15 20:24:57 +10:00
|
|
|
// It takes serial arithmetic (RFC 1982) into account.
|
2012-09-12 05:45:21 +10:00
|
|
|
func StringToTime(s string) (uint32, error) {
|
2016-06-09 16:00:08 +10:00
|
|
|
t, err := time.Parse("20060102150405", s)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
2011-12-17 00:48:30 +11:00
|
|
|
}
|
2018-08-17 02:05:27 +10:00
|
|
|
mod := t.Unix()/year68 - 1
|
2012-05-15 20:24:57 +10:00
|
|
|
if mod < 0 {
|
|
|
|
mod = 0
|
|
|
|
}
|
2018-08-17 02:05:27 +10:00
|
|
|
return uint32(t.Unix() - mod*year68), nil
|
2010-12-30 23:42:52 +11:00
|
|
|
}
|
|
|
|
|
2016-07-26 13:20:27 +10:00
|
|
|
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
|
2013-04-16 02:34:21 +10:00
|
|
|
func saltToString(s string) string {
|
2021-02-26 03:01:55 +11:00
|
|
|
if s == "" {
|
2012-01-10 20:43:28 +11:00
|
|
|
return "-"
|
|
|
|
}
|
|
|
|
return strings.ToUpper(s)
|
|
|
|
}
|
|
|
|
|
2013-04-16 02:34:21 +10:00
|
|
|
func euiToString(eui uint64, bits int) (hex string) {
|
|
|
|
switch bits {
|
|
|
|
case 64:
|
2013-04-16 03:42:07 +10:00
|
|
|
hex = fmt.Sprintf("%16.16x", eui)
|
|
|
|
hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
|
|
|
|
"-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16]
|
2013-04-16 02:34:21 +10:00
|
|
|
case 48:
|
2013-04-16 03:42:07 +10:00
|
|
|
hex = fmt.Sprintf("%12.12x", eui)
|
|
|
|
hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
|
|
|
|
"-" + hex[8:10] + "-" + hex[10:12]
|
2013-04-16 02:34:21 +10:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2014-01-12 21:11:23 +11:00
|
|
|
// copyIP returns a copy of ip.
|
|
|
|
func copyIP(ip net.IP) net.IP {
|
|
|
|
p := make(net.IP, len(ip))
|
|
|
|
copy(p, ip)
|
|
|
|
return p
|
|
|
|
}
|
2016-10-18 04:09:52 +11:00
|
|
|
|
2020-01-03 23:41:45 +11:00
|
|
|
// copyNet returns a copy of a subnet.
|
|
|
|
func copyNet(n net.IPNet) net.IPNet {
|
|
|
|
m := make(net.IPMask, len(n.Mask))
|
|
|
|
copy(m, n.Mask)
|
|
|
|
|
|
|
|
return net.IPNet{
|
|
|
|
IP: copyIP(n.IP),
|
|
|
|
Mask: m,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 04:09:52 +11:00
|
|
|
// SplitN splits a string into N sized string chunks.
|
|
|
|
// This might become an exported function once.
|
|
|
|
func splitN(s string, n int) []string {
|
|
|
|
if len(s) < n {
|
|
|
|
return []string{s}
|
|
|
|
}
|
|
|
|
sx := []string{}
|
|
|
|
p, i := 0, n
|
|
|
|
for {
|
|
|
|
if i <= len(s) {
|
|
|
|
sx = append(sx, s[p:i])
|
|
|
|
} else {
|
|
|
|
sx = append(sx, s[p:])
|
|
|
|
break
|
|
|
|
|
|
|
|
}
|
|
|
|
p, i = p+n, i+n
|
|
|
|
}
|
|
|
|
|
|
|
|
return sx
|
|
|
|
}
|