Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • renovate/git.autistici.org-ai3-go-common-digest
  • renovate/github.com-miekg-dns-1.x
  • renovate/github.com-prometheus-client_golang-1.x
  • renovate/golang.org-x-crypto-0.x
  • renovate/golang.org-x-net-0.x
  • v2
  • v3
8 results

Target

Select target project
  • ai3/tools/acmeserver
  • godog/acmeserver
  • svp-bot/acmeserver
3 results
Select Git revision
  • lintian-fixes
  • master
  • renovate/github.com-miekg-dns-1.x
  • renovate/golang.org-x-crypto-digest
4 results
Show changes
Showing
with 9271 additions and 0 deletions
package dns
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"net"
"sort"
"strconv"
"strings"
)
// SVCBKey is the type of the keys used in the SVCB RR.
type SVCBKey uint16
// Keys defined in draft-ietf-dnsop-svcb-https-08 Section 14.3.2.
const (
SVCB_MANDATORY SVCBKey = iota
SVCB_ALPN
SVCB_NO_DEFAULT_ALPN
SVCB_PORT
SVCB_IPV4HINT
SVCB_ECHCONFIG
SVCB_IPV6HINT
SVCB_DOHPATH // draft-ietf-add-svcb-dns-02 Section 9
svcb_RESERVED SVCBKey = 65535
)
var svcbKeyToStringMap = map[SVCBKey]string{
SVCB_MANDATORY: "mandatory",
SVCB_ALPN: "alpn",
SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
SVCB_PORT: "port",
SVCB_IPV4HINT: "ipv4hint",
SVCB_ECHCONFIG: "ech",
SVCB_IPV6HINT: "ipv6hint",
SVCB_DOHPATH: "dohpath",
}
var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey {
n := make(map[string]SVCBKey, len(m))
for u, s := range m {
n[s] = u
}
return n
}
// String takes the numerical code of an SVCB key and returns its name.
// Returns an empty string for reserved keys.
// Accepts unassigned keys as well as experimental/private keys.
func (key SVCBKey) String() string {
if x := svcbKeyToStringMap[key]; x != "" {
return x
}
if key == svcb_RESERVED {
return ""
}
return "key" + strconv.FormatUint(uint64(key), 10)
}
// svcbStringToKey returns the numerical code of an SVCB key.
// Returns svcb_RESERVED for reserved/invalid keys.
// Accepts unassigned keys as well as experimental/private keys.
func svcbStringToKey(s string) SVCBKey {
if strings.HasPrefix(s, "key") {
a, err := strconv.ParseUint(s[3:], 10, 16)
// no leading zeros
// key shouldn't be registered
if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" {
return svcb_RESERVED
}
return SVCBKey(a)
}
if key, ok := svcbStringToKeyMap[s]; ok {
return key
}
return svcb_RESERVED
}
func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{l.token, "bad SVCB priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Target = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{l.token, "bad SVCB Target", l}
}
rr.Target = name
// Values (if any)
l, _ = c.Next()
var xs []SVCBKeyValue
// Helps require whitespace between pairs.
// Prevents key1000="a"key1001=...
canHaveNextKey := true
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
if !canHaveNextKey {
// The key we can now read was probably meant to be
// a part of the last value.
return &ParseError{l.token, "bad SVCB value quotation", l}
}
// In key=value pairs, value does not have to be quoted unless value
// contains whitespace. And keys don't need to have values.
// Similarly, keys with an equality signs after them don't need values.
// l.token includes at least up to the first equality sign.
idx := strings.IndexByte(l.token, '=')
var key, value string
if idx < 0 {
// Key with no value and no equality sign
key = l.token
} else if idx == 0 {
return &ParseError{l.token, "bad SVCB key", l}
} else {
key, value = l.token[:idx], l.token[idx+1:]
if value == "" {
// We have a key and an equality sign. Maybe we have nothing
// after "=" or we have a double quote.
l, _ = c.Next()
if l.value == zQuote {
// Only needed when value ends with double quotes.
// Any value starting with zQuote ends with it.
canHaveNextKey = false
l, _ = c.Next()
switch l.value {
case zString:
// We have a value in double quotes.
value = l.token
l, _ = c.Next()
if l.value != zQuote {
return &ParseError{l.token, "SVCB unterminated value", l}
}
case zQuote:
// There's nothing in double quotes.
default:
return &ParseError{l.token, "bad SVCB value", l}
}
}
}
}
kv := makeSVCBKeyValue(svcbStringToKey(key))
if kv == nil {
return &ParseError{l.token, "bad SVCB key", l}
}
if err := kv.parse(value); err != nil {
return &ParseError{l.token, err.Error(), l}
}
xs = append(xs, kv)
case zQuote:
return &ParseError{l.token, "SVCB key can't contain double quotes", l}
case zBlank:
canHaveNextKey = true
default:
return &ParseError{l.token, "bad SVCB values", l}
}
l, _ = c.Next()
}
// "In AliasMode, records SHOULD NOT include any SvcParams, and recipients MUST
// ignore any SvcParams that are present."
// However, we don't check rr.Priority == 0 && len(xs) > 0 here
// It is the responsibility of the user of the library to check this.
// This is to encourage the fixing of the source of this error.
rr.Value = xs
return nil
}
// makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys.
func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
switch key {
case SVCB_MANDATORY:
return new(SVCBMandatory)
case SVCB_ALPN:
return new(SVCBAlpn)
case SVCB_NO_DEFAULT_ALPN:
return new(SVCBNoDefaultAlpn)
case SVCB_PORT:
return new(SVCBPort)
case SVCB_IPV4HINT:
return new(SVCBIPv4Hint)
case SVCB_ECHCONFIG:
return new(SVCBECHConfig)
case SVCB_IPV6HINT:
return new(SVCBIPv6Hint)
case SVCB_DOHPATH:
return new(SVCBDoHPath)
case svcb_RESERVED:
return nil
default:
e := new(SVCBLocal)
e.KeyCode = key
return e
}
}
// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-08).
//
// NOTE: The HTTPS/SVCB RFCs are in the draft stage.
// The API, including constants and types related to SVCBKeyValues, may
// change in future versions in accordance with the latest drafts.
type SVCB struct {
Hdr RR_Header
Priority uint16 // If zero, Value must be empty or discarded by the user of this library
Target string `dns:"domain-name"`
Value []SVCBKeyValue `dns:"pairs"`
}
// HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
// Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
//
// NOTE: The HTTPS/SVCB RFCs are in the draft stage.
// The API, including constants and types related to SVCBKeyValues, may
// change in future versions in accordance with the latest drafts.
type HTTPS struct {
SVCB
}
func (rr *HTTPS) String() string {
return rr.SVCB.String()
}
func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
return rr.SVCB.parse(c, o)
}
// SVCBKeyValue defines a key=value pair for the SVCB RR type.
// An SVCB RR can have multiple SVCBKeyValues appended to it.
type SVCBKeyValue interface {
Key() SVCBKey // Key returns the numerical key code.
pack() ([]byte, error) // pack returns the encoded value.
unpack([]byte) error // unpack sets the value.
String() string // String returns the string representation of the value.
parse(string) error // parse sets the value to the given string representation of the value.
copy() SVCBKeyValue // copy returns a deep-copy of the pair.
len() int // len returns the length of value in the wire format.
}
// SVCBMandatory pair adds to required keys that must be interpreted for the RR
// to be functional. If ignored, the whole RRSet must be ignored.
// "port" and "no-default-alpn" are mandatory by default if present,
// so they shouldn't be included here.
//
// It is incumbent upon the user of this library to reject the RRSet if
// or avoid constructing such an RRSet that:
// - "mandatory" is included as one of the keys of mandatory
// - no key is listed multiple times in mandatory
// - all keys listed in mandatory are present
// - escape sequences are not used in mandatory
// - mandatory, when present, lists at least one key
//
// Basic use pattern for creating a mandatory option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBMandatory)
// e.Code = []uint16{dns.SVCB_ALPN}
// s.Value = append(s.Value, e)
// t := new(dns.SVCBAlpn)
// t.Alpn = []string{"xmpp-client"}
// s.Value = append(s.Value, t)
type SVCBMandatory struct {
Code []SVCBKey
}
func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
func (s *SVCBMandatory) String() string {
str := make([]string, len(s.Code))
for i, e := range s.Code {
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBMandatory) pack() ([]byte, error) {
codes := append([]SVCBKey(nil), s.Code...)
sort.Slice(codes, func(i, j int) bool {
return codes[i] < codes[j]
})
b := make([]byte, 2*len(codes))
for i, e := range codes {
binary.BigEndian.PutUint16(b[2*i:], uint16(e))
}
return b, nil
}
func (s *SVCBMandatory) unpack(b []byte) error {
if len(b)%2 != 0 {
return errors.New("dns: svcbmandatory: value length is not a multiple of 2")
}
codes := make([]SVCBKey, 0, len(b)/2)
for i := 0; i < len(b); i += 2 {
// We assume strictly increasing order.
codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:])))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) parse(b string) error {
str := strings.Split(b, ",")
codes := make([]SVCBKey, 0, len(str))
for _, e := range str {
codes = append(codes, svcbStringToKey(e))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) len() int {
return 2 * len(s.Code)
}
func (s *SVCBMandatory) copy() SVCBKeyValue {
return &SVCBMandatory{
append([]SVCBKey(nil), s.Code...),
}
}
// SVCBAlpn pair is used to list supported connection protocols.
// The user of this library must ensure that at least one protocol is listed when alpn is present.
// Protocol IDs can be found at:
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
// Basic use pattern for creating an alpn option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "http/1.1"}
// h.Value = append(h.Value, e)
type SVCBAlpn struct {
Alpn []string
}
func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
func (s *SVCBAlpn) String() string {
// An ALPN value is a comma-separated list of values, each of which can be
// an arbitrary binary value. In order to allow parsing, the comma and
// backslash characters are themselves excaped.
//
// However, this escaping is done in addition to the normal escaping which
// happens in zone files, meaning that these values must be
// double-escaped. This looks terrible, so if you see a never-ending
// sequence of backslash in a zone file this may be why.
//
// https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-08#appendix-A.1
var str strings.Builder
for i, alpn := range s.Alpn {
// 4*len(alpn) is the worst case where we escape every character in the alpn as \123, plus 1 byte for the ',' separating the alpn from others
str.Grow(4*len(alpn) + 1)
if i > 0 {
str.WriteByte(',')
}
for j := 0; j < len(alpn); j++ {
e := alpn[j]
if ' ' > e || e > '~' {
str.WriteString(escapeByte(e))
continue
}
switch e {
// We escape a few characters which may confuse humans or parsers.
case '"', ';', ' ':
str.WriteByte('\\')
str.WriteByte(e)
// The comma and backslash characters themselves must be
// doubly-escaped. We use `\\` for the first backslash and
// the escaped numeric value for the other value. We especially
// don't want a comma in the output.
case ',':
str.WriteString(`\\\044`)
case '\\':
str.WriteString(`\\\092`)
default:
str.WriteByte(e)
}
}
}
return str.String()
}
func (s *SVCBAlpn) pack() ([]byte, error) {
// Liberally estimate the size of an alpn as 10 octets
b := make([]byte, 0, 10*len(s.Alpn))
for _, e := range s.Alpn {
if e == "" {
return nil, errors.New("dns: svcbalpn: empty alpn-id")
}
if len(e) > 255 {
return nil, errors.New("dns: svcbalpn: alpn-id too long")
}
b = append(b, byte(len(e)))
b = append(b, e...)
}
return b, nil
}
func (s *SVCBAlpn) unpack(b []byte) error {
// Estimate the size of the smallest alpn as 4 bytes
alpn := make([]string, 0, len(b)/4)
for i := 0; i < len(b); {
length := int(b[i])
i++
if i+length > len(b) {
return errors.New("dns: svcbalpn: alpn array overflowing")
}
alpn = append(alpn, string(b[i:i+length]))
i += length
}
s.Alpn = alpn
return nil
}
func (s *SVCBAlpn) parse(b string) error {
if len(b) == 0 {
s.Alpn = []string{}
return nil
}
alpn := []string{}
a := []byte{}
for p := 0; p < len(b); {
c, q := nextByte(b, p)
if q == 0 {
return errors.New("dns: svcbalpn: unterminated escape")
}
p += q
// If we find a comma, we have finished reading an alpn.
if c == ',' {
if len(a) == 0 {
return errors.New("dns: svcbalpn: empty protocol identifier")
}
alpn = append(alpn, string(a))
a = []byte{}
continue
}
// If it's a backslash, we need to handle a comma-separated list.
if c == '\\' {
dc, dq := nextByte(b, p)
if dq == 0 {
return errors.New("dns: svcbalpn: unterminated escape decoding comma-separated list")
}
if dc != '\\' && dc != ',' {
return errors.New("dns: svcbalpn: bad escaped character decoding comma-separated list")
}
p += dq
c = dc
}
a = append(a, c)
}
// Add the final alpn.
if len(a) == 0 {
return errors.New("dns: svcbalpn: last protocol identifier empty")
}
s.Alpn = append(alpn, string(a))
return nil
}
func (s *SVCBAlpn) len() int {
var l int
for _, e := range s.Alpn {
l += 1 + len(e)
}
return l
}
func (s *SVCBAlpn) copy() SVCBKeyValue {
return &SVCBAlpn{
append([]string(nil), s.Alpn...),
}
}
// SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
// Should be used in conjunction with alpn.
// Basic use pattern for creating a no-default-alpn option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// t := new(dns.SVCBAlpn)
// t.Alpn = []string{"xmpp-client"}
// s.Value = append(s.Value, t)
// e := new(dns.SVCBNoDefaultAlpn)
// s.Value = append(s.Value, e)
type SVCBNoDefaultAlpn struct{}
func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN }
func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} }
func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil }
func (*SVCBNoDefaultAlpn) String() string { return "" }
func (*SVCBNoDefaultAlpn) len() int { return 0 }
func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value")
}
return nil
}
func (*SVCBNoDefaultAlpn) parse(b string) error {
if b != "" {
return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value")
}
return nil
}
// SVCBPort pair defines the port for connection.
// Basic use pattern for creating a port option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBPort)
// e.Port = 80
// s.Value = append(s.Value, e)
type SVCBPort struct {
Port uint16
}
func (*SVCBPort) Key() SVCBKey { return SVCB_PORT }
func (*SVCBPort) len() int { return 2 }
func (s *SVCBPort) String() string { return strconv.FormatUint(uint64(s.Port), 10) }
func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} }
func (s *SVCBPort) unpack(b []byte) error {
if len(b) != 2 {
return errors.New("dns: svcbport: port length is not exactly 2 octets")
}
s.Port = binary.BigEndian.Uint16(b)
return nil
}
func (s *SVCBPort) pack() ([]byte, error) {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, s.Port)
return b, nil
}
func (s *SVCBPort) parse(b string) error {
port, err := strconv.ParseUint(b, 10, 16)
if err != nil {
return errors.New("dns: svcbport: port out of range")
}
s.Port = uint16(port)
return nil
}
// SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the connection
// to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv4hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv4Hint)
// e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
//
// Or
//
// e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
// h.Value = append(h.Value, e)
type SVCBIPv4Hint struct {
Hint []net.IP
}
func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT }
func (s *SVCBIPv4Hint) len() int { return 4 * len(s.Hint) }
func (s *SVCBIPv4Hint) pack() ([]byte, error) {
b := make([]byte, 0, 4*len(s.Hint))
for _, e := range s.Hint {
x := e.To4()
if x == nil {
return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6")
}
b = append(b, x...)
}
return b, nil
}
func (s *SVCBIPv4Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%4 != 0 {
return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
}
x := make([]net.IP, 0, len(b)/4)
for i := 0; i < len(b); i += 4 {
x = append(x, net.IP(b[i:i+4]))
}
s.Hint = x
return nil
}
func (s *SVCBIPv4Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
x := e.To4()
if x == nil {
return "<nil>"
}
str[i] = x.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv4Hint) parse(b string) error {
if strings.Contains(b, ":") {
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e).To4()
if ip == nil {
return errors.New("dns: svcbipv4hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
hint := make([]net.IP, len(s.Hint))
for i, ip := range s.Hint {
hint[i] = copyIP(ip)
}
return &SVCBIPv4Hint{
Hint: hint,
}
}
// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
// Basic use pattern for creating an ech option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBECHConfig)
// e.ECH = []byte{0xfe, 0x08, ...}
// h.Value = append(h.Value, e)
type SVCBECHConfig struct {
ECH []byte // Specifically ECHConfigList including the redundant length prefix
}
func (*SVCBECHConfig) Key() SVCBKey { return SVCB_ECHCONFIG }
func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
func (s *SVCBECHConfig) len() int { return len(s.ECH) }
func (s *SVCBECHConfig) pack() ([]byte, error) {
return append([]byte(nil), s.ECH...), nil
}
func (s *SVCBECHConfig) copy() SVCBKeyValue {
return &SVCBECHConfig{
append([]byte(nil), s.ECH...),
}
}
func (s *SVCBECHConfig) unpack(b []byte) error {
s.ECH = append([]byte(nil), b...)
return nil
}
func (s *SVCBECHConfig) parse(b string) error {
x, err := fromBase64([]byte(b))
if err != nil {
return errors.New("dns: svcbech: bad base64 ech")
}
s.ECH = x
return nil
}
// SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the
// connection to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv6hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv6Hint)
// e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
// h.Value = append(h.Value, e)
type SVCBIPv6Hint struct {
Hint []net.IP
}
func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT }
func (s *SVCBIPv6Hint) len() int { return 16 * len(s.Hint) }
func (s *SVCBIPv6Hint) pack() ([]byte, error) {
b := make([]byte, 0, 16*len(s.Hint))
for _, e := range s.Hint {
if len(e) != net.IPv6len || e.To4() != nil {
return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4")
}
b = append(b, e...)
}
return b, nil
}
func (s *SVCBIPv6Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%16 != 0 {
return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
}
x := make([]net.IP, 0, len(b)/16)
for i := 0; i < len(b); i += 16 {
ip := net.IP(b[i : i+16])
if ip.To4() != nil {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
x = append(x, ip)
}
s.Hint = x
return nil
}
func (s *SVCBIPv6Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
if x := e.To4(); x != nil {
return "<nil>"
}
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv6Hint) parse(b string) error {
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e)
if ip == nil {
return errors.New("dns: svcbipv6hint: bad ip")
}
if ip.To4() != nil {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4-mapped-ipv6")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
hint := make([]net.IP, len(s.Hint))
for i, ip := range s.Hint {
hint[i] = copyIP(ip)
}
return &SVCBIPv6Hint{
Hint: hint,
}
}
// SVCBDoHPath pair is used to indicate the URI template that the
// clients may use to construct a DNS over HTTPS URI.
//
// See RFC xxxx (https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02)
// and RFC yyyy (https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-06).
//
// A basic example of using the dohpath option together with the alpn
// option to indicate support for DNS over HTTPS on a certain path:
//
// s := new(dns.SVCB)
// s.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}
// e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "h3"}
// p := new(dns.SVCBDoHPath)
// p.Template = "/dns-query{?dns}"
// s.Value = append(s.Value, e, p)
//
// The parsing currently doesn't validate that Template is a valid
// RFC 6570 URI template.
type SVCBDoHPath struct {
Template string
}
func (*SVCBDoHPath) Key() SVCBKey { return SVCB_DOHPATH }
func (s *SVCBDoHPath) String() string { return svcbParamToStr([]byte(s.Template)) }
func (s *SVCBDoHPath) len() int { return len(s.Template) }
func (s *SVCBDoHPath) pack() ([]byte, error) { return []byte(s.Template), nil }
func (s *SVCBDoHPath) unpack(b []byte) error {
s.Template = string(b)
return nil
}
func (s *SVCBDoHPath) parse(b string) error {
template, err := svcbParseParam(b)
if err != nil {
return fmt.Errorf("dns: svcbdohpath: %w", err)
}
s.Template = string(template)
return nil
}
func (s *SVCBDoHPath) copy() SVCBKeyValue {
return &SVCBDoHPath{
Template: s.Template,
}
}
// SVCBLocal pair is intended for experimental/private use. The key is recommended
// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
// Basic use pattern for creating a keyNNNNN option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBLocal)
// e.KeyCode = 65400
// e.Data = []byte("abc")
// h.Value = append(h.Value, e)
type SVCBLocal struct {
KeyCode SVCBKey // Never 65535 or any assigned keys.
Data []byte // All byte sequences are allowed.
}
func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode }
func (s *SVCBLocal) String() string { return svcbParamToStr(s.Data) }
func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
func (s *SVCBLocal) len() int { return len(s.Data) }
func (s *SVCBLocal) unpack(b []byte) error {
s.Data = append([]byte(nil), b...)
return nil
}
func (s *SVCBLocal) parse(b string) error {
data, err := svcbParseParam(b)
if err != nil {
return fmt.Errorf("dns: svcblocal: svcb private/experimental key %w", err)
}
s.Data = data
return nil
}
func (s *SVCBLocal) copy() SVCBKeyValue {
return &SVCBLocal{s.KeyCode,
append([]byte(nil), s.Data...),
}
}
func (rr *SVCB) String() string {
s := rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
sprintName(rr.Target)
for _, e := range rr.Value {
s += " " + e.Key().String() + "=\"" + e.String() + "\""
}
return s
}
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
a = append([]SVCBKeyValue(nil), a...)
b = append([]SVCBKeyValue(nil), b...)
sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
for i, e := range a {
if e.Key() != b[i].Key() {
return false
}
b1, err1 := e.pack()
b2, err2 := b[i].pack()
if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
return false
}
}
return true
}
// svcbParamStr converts the value of an SVCB parameter into a DNS presentation-format string.
func svcbParamToStr(s []byte) string {
var str strings.Builder
str.Grow(4 * len(s))
for _, e := range s {
if ' ' <= e && e <= '~' {
switch e {
case '"', ';', ' ', '\\':
str.WriteByte('\\')
str.WriteByte(e)
default:
str.WriteByte(e)
}
} else {
str.WriteString(escapeByte(e))
}
}
return str.String()
}
// svcbParseParam parses a DNS presentation-format string into an SVCB parameter value.
func svcbParseParam(b string) ([]byte, error) {
data := make([]byte, 0, len(b))
for i := 0; i < len(b); {
if b[i] != '\\' {
data = append(data, b[i])
i++
continue
}
if i+1 == len(b) {
return nil, errors.New("escape unterminated")
}
if isDigit(b[i+1]) {
if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
a, err := strconv.ParseUint(b[i+1:i+4], 10, 8)
if err == nil {
i += 4
data = append(data, byte(a))
continue
}
}
return nil, errors.New("bad escaped octet")
} else {
data = append(data, b[i+1])
i += 2
}
}
return data, nil
}
package dns
import (
"crypto/x509"
"net"
"strconv"
)
// Sign creates a TLSA record from an SSL certificate.
func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
r.Hdr.Rrtype = TypeTLSA
r.Usage = uint8(usage)
r.Selector = uint8(selector)
r.MatchingType = uint8(matchingType)
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
return err
}
// Verify verifies a TLSA record against an SSL certificate. If it is OK
// a nil error is returned.
func (r *TLSA) Verify(cert *x509.Certificate) error {
c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
if err != nil {
return err // Not also ErrSig?
}
if r.Certificate == c {
return nil
}
return ErrSig // ErrSig, really?
}
// TLSAName returns the ownername of a TLSA resource record as per the
// rules specified in RFC 6698, Section 3.
func TLSAName(name, service, network string) (string, error) {
if !IsFqdn(name) {
return "", ErrFqdn
}
p, err := net.LookupPort(network, service)
if err != nil {
return "", err
}
return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
}
// +build tools
// We include our tool dependencies for `go generate` here to ensure they're
// properly tracked by the go tool. See the Go Wiki for the rationale behind this:
// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module.
package dns
import _ "golang.org/x/tools/go/packages"
package dns
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"encoding/hex"
"hash"
"strconv"
"strings"
"time"
)
// HMAC hashing codes. These are transmitted as domain names.
const (
HmacSHA1 = "hmac-sha1."
HmacSHA224 = "hmac-sha224."
HmacSHA256 = "hmac-sha256."
HmacSHA384 = "hmac-sha384."
HmacSHA512 = "hmac-sha512."
HmacMD5 = "hmac-md5.sig-alg.reg.int." // Deprecated: HmacMD5 is no longer supported.
)
// TsigProvider provides the API to plug-in a custom TSIG implementation.
type TsigProvider interface {
// Generate is passed the DNS message to be signed and the partial TSIG RR. It returns the signature and nil, otherwise an error.
Generate(msg []byte, t *TSIG) ([]byte, error)
// Verify is passed the DNS message to be verified and the TSIG RR. If the signature is valid it will return nil, otherwise an error.
Verify(msg []byte, t *TSIG) error
}
type tsigHMACProvider string
func (key tsigHMACProvider) Generate(msg []byte, t *TSIG) ([]byte, error) {
// If we barf here, the caller is to blame
rawsecret, err := fromBase64([]byte(key))
if err != nil {
return nil, err
}
var h hash.Hash
switch CanonicalName(t.Algorithm) {
case HmacSHA1:
h = hmac.New(sha1.New, rawsecret)
case HmacSHA224:
h = hmac.New(sha256.New224, rawsecret)
case HmacSHA256:
h = hmac.New(sha256.New, rawsecret)
case HmacSHA384:
h = hmac.New(sha512.New384, rawsecret)
case HmacSHA512:
h = hmac.New(sha512.New, rawsecret)
default:
return nil, ErrKeyAlg
}
h.Write(msg)
return h.Sum(nil), nil
}
func (key tsigHMACProvider) Verify(msg []byte, t *TSIG) error {
b, err := key.Generate(msg, t)
if err != nil {
return err
}
mac, err := hex.DecodeString(t.MAC)
if err != nil {
return err
}
if !hmac.Equal(b, mac) {
return ErrSig
}
return nil
}
type tsigSecretProvider map[string]string
func (ts tsigSecretProvider) Generate(msg []byte, t *TSIG) ([]byte, error) {
key, ok := ts[t.Hdr.Name]
if !ok {
return nil, ErrSecret
}
return tsigHMACProvider(key).Generate(msg, t)
}
func (ts tsigSecretProvider) Verify(msg []byte, t *TSIG) error {
key, ok := ts[t.Hdr.Name]
if !ok {
return ErrSecret
}
return tsigHMACProvider(key).Verify(msg, t)
}
// TSIG is the RR the holds the transaction signature of a message.
// See RFC 2845 and RFC 4635.
type TSIG struct {
Hdr RR_Header
Algorithm string `dns:"domain-name"`
TimeSigned uint64 `dns:"uint48"`
Fudge uint16
MACSize uint16
MAC string `dns:"size-hex:MACSize"`
OrigId uint16
Error uint16
OtherLen uint16
OtherData string `dns:"size-hex:OtherLen"`
}
// TSIG has no official presentation format, but this will suffice.
func (rr *TSIG) String() string {
s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format
s += rr.Hdr.String() +
" " + rr.Algorithm +
" " + tsigTimeToString(rr.TimeSigned) +
" " + strconv.Itoa(int(rr.Fudge)) +
" " + strconv.Itoa(int(rr.MACSize)) +
" " + strings.ToUpper(rr.MAC) +
" " + strconv.Itoa(int(rr.OrigId)) +
" " + strconv.Itoa(int(rr.Error)) + // BIND prints NOERROR
" " + strconv.Itoa(int(rr.OtherLen)) +
" " + rr.OtherData
return s
}
func (*TSIG) parse(c *zlexer, origin string) *ParseError {
return &ParseError{err: "TSIG records do not have a presentation format"}
}
// The following values must be put in wireformat, so that the MAC can be calculated.
// RFC 2845, section 3.4.2. TSIG Variables.
type tsigWireFmt struct {
// From RR_Header
Name string `dns:"domain-name"`
Class uint16
Ttl uint32
// Rdata of the TSIG
Algorithm string `dns:"domain-name"`
TimeSigned uint64 `dns:"uint48"`
Fudge uint16
// MACSize, MAC and OrigId excluded
Error uint16
OtherLen uint16
OtherData string `dns:"size-hex:OtherLen"`
}
// If we have the MAC use this type to convert it to wiredata. Section 3.4.3. Request MAC
type macWireFmt struct {
MACSize uint16
MAC string `dns:"size-hex:MACSize"`
}
// 3.3. Time values used in TSIG calculations
type timerWireFmt struct {
TimeSigned uint64 `dns:"uint48"`
Fudge uint16
}
// TsigGenerate fills out the TSIG record attached to the message.
// The message should contain a "stub" TSIG RR with the algorithm, key name
// (owner name of the RR), time fudge (defaults to 300 seconds) and the current
// time The TSIG MAC is saved in that Tsig RR. When TsigGenerate is called for
// the first time requestMAC should be set to the empty string and timersOnly to
// false.
func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
return TsigGenerateWithProvider(m, tsigHMACProvider(secret), requestMAC, timersOnly)
}
// TsigGenerateWithProvider is similar to TsigGenerate, but allows for a custom TsigProvider.
func TsigGenerateWithProvider(m *Msg, provider TsigProvider, requestMAC string, timersOnly bool) ([]byte, string, error) {
if m.IsTsig() == nil {
panic("dns: TSIG not last RR in additional")
}
rr := m.Extra[len(m.Extra)-1].(*TSIG)
m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg
mbuf, err := m.Pack()
if err != nil {
return nil, "", err
}
buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
if err != nil {
return nil, "", err
}
t := new(TSIG)
// Copy all TSIG fields except MAC, its size, and time signed which are filled when signing.
*t = *rr
t.TimeSigned = 0
t.MAC = ""
t.MACSize = 0
// Sign unless there is a key or MAC validation error (RFC 8945 5.3.2)
if rr.Error != RcodeBadKey && rr.Error != RcodeBadSig {
mac, err := provider.Generate(buf, rr)
if err != nil {
return nil, "", err
}
t.TimeSigned = rr.TimeSigned
t.MAC = hex.EncodeToString(mac)
t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
}
tbuf := make([]byte, Len(t))
off, err := PackRR(t, tbuf, 0, nil, false)
if err != nil {
return nil, "", err
}
mbuf = append(mbuf, tbuf[:off]...)
// Update the ArCount directly in the buffer.
binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
return mbuf, t.MAC, nil
}
// TsigVerify verifies the TSIG on a message. If the signature does not
// validate the returned error contains the cause. If the signature is OK, the
// error is nil.
func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
return tsigVerify(msg, tsigHMACProvider(secret), requestMAC, timersOnly, uint64(time.Now().Unix()))
}
// TsigVerifyWithProvider is similar to TsigVerify, but allows for a custom TsigProvider.
func TsigVerifyWithProvider(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool) error {
return tsigVerify(msg, provider, requestMAC, timersOnly, uint64(time.Now().Unix()))
}
// actual implementation of TsigVerify, taking the current time ('now') as a parameter for the convenience of tests.
func tsigVerify(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool, now uint64) error {
// Strip the TSIG from the incoming msg
stripped, tsig, err := stripTsig(msg)
if err != nil {
return err
}
buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
if err != nil {
return err
}
if err := provider.Verify(buf, tsig); err != nil {
return err
}
// Fudge factor works both ways. A message can arrive before it was signed because
// of clock skew.
// We check this after verifying the signature, following draft-ietf-dnsop-rfc2845bis
// instead of RFC2845, in order to prevent a security vulnerability as reported in CVE-2017-3142/3143.
ti := now - tsig.TimeSigned
if now < tsig.TimeSigned {
ti = tsig.TimeSigned - now
}
if uint64(tsig.Fudge) < ti {
return ErrTime
}
return nil
}
// Create a wiredata buffer for the MAC calculation.
func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) ([]byte, error) {
var buf []byte
if rr.TimeSigned == 0 {
rr.TimeSigned = uint64(time.Now().Unix())
}
if rr.Fudge == 0 {
rr.Fudge = 300 // Standard (RFC) default.
}
// Replace message ID in header with original ID from TSIG
binary.BigEndian.PutUint16(msgbuf[0:2], rr.OrigId)
if requestMAC != "" {
m := new(macWireFmt)
m.MACSize = uint16(len(requestMAC) / 2)
m.MAC = requestMAC
buf = make([]byte, len(requestMAC)) // long enough
n, err := packMacWire(m, buf)
if err != nil {
return nil, err
}
buf = buf[:n]
}
tsigvar := make([]byte, DefaultMsgSize)
if timersOnly {
tsig := new(timerWireFmt)
tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge
n, err := packTimerWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n]
} else {
tsig := new(tsigWireFmt)
tsig.Name = CanonicalName(rr.Hdr.Name)
tsig.Class = ClassANY
tsig.Ttl = rr.Hdr.Ttl
tsig.Algorithm = CanonicalName(rr.Algorithm)
tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge
tsig.Error = rr.Error
tsig.OtherLen = rr.OtherLen
tsig.OtherData = rr.OtherData
n, err := packTsigWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n]
}
if requestMAC != "" {
x := append(buf, msgbuf...)
buf = append(x, tsigvar...)
} else {
buf = append(msgbuf, tsigvar...)
}
return buf, nil
}
// Strip the TSIG from the raw message.
func stripTsig(msg []byte) ([]byte, *TSIG, error) {
// Copied from msg.go's Unpack() Header, but modified.
var (
dh Header
err error
)
off, tsigoff := 0, 0
if dh, off, err = unpackMsgHdr(msg, off); err != nil {
return nil, nil, err
}
if dh.Arcount == 0 {
return nil, nil, ErrNoSig
}
// Rcode, see msg.go Unpack()
if int(dh.Bits&0xF) == RcodeNotAuth {
return nil, nil, ErrAuth
}
for i := 0; i < int(dh.Qdcount); i++ {
_, off, err = unpackQuestion(msg, off)
if err != nil {
return nil, nil, err
}
}
_, off, err = unpackRRslice(int(dh.Ancount), msg, off)
if err != nil {
return nil, nil, err
}
_, off, err = unpackRRslice(int(dh.Nscount), msg, off)
if err != nil {
return nil, nil, err
}
rr := new(TSIG)
var extra RR
for i := 0; i < int(dh.Arcount); i++ {
tsigoff = off
extra, off, err = UnpackRR(msg, off)
if err != nil {
return nil, nil, err
}
if extra.Header().Rrtype == TypeTSIG {
rr = extra.(*TSIG)
// Adjust Arcount.
arcount := binary.BigEndian.Uint16(msg[10:])
binary.BigEndian.PutUint16(msg[10:], arcount-1)
break
}
}
if rr == nil {
return nil, nil, ErrNoSig
}
return msg[:tsigoff], rr, nil
}
// Translate the TSIG time signed into a date. There is no
// need for RFC1982 calculations as this date is 48 bits.
func tsigTimeToString(t uint64) string {
ti := time.Unix(int64(t), 0).UTC()
return ti.Format("20060102150405")
}
func packTsigWire(tw *tsigWireFmt, msg []byte) (int, error) {
// copied from zmsg.go TSIG packing
// RR_Header
off, err := PackDomainName(tw.Name, msg, 0, nil, false)
if err != nil {
return off, err
}
off, err = packUint16(tw.Class, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(tw.Ttl, msg, off)
if err != nil {
return off, err
}
off, err = PackDomainName(tw.Algorithm, msg, off, nil, false)
if err != nil {
return off, err
}
off, err = packUint48(tw.TimeSigned, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(tw.Fudge, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(tw.Error, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(tw.OtherLen, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(tw.OtherData, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func packMacWire(mw *macWireFmt, msg []byte) (int, error) {
off, err := packUint16(mw.MACSize, msg, 0)
if err != nil {
return off, err
}
off, err = packStringHex(mw.MAC, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func packTimerWire(tw *timerWireFmt, msg []byte) (int, error) {
off, err := packUint48(tw.TimeSigned, msg, 0)
if err != nil {
return off, err
}
off, err = packUint16(tw.Fudge, msg, off)
if err != nil {
return off, err
}
return off, nil
}
package dns
import (
"bytes"
"fmt"
"net"
"strconv"
"strings"
"time"
)
type (
// Type is a DNS type.
Type uint16
// Class is a DNS class.
Class uint16
// Name is a DNS domain name.
Name string
)
// Packet formats
// Wire constants and supported types.
const (
// valid RR_Header.Rrtype and Question.qtype
TypeNone uint16 = 0
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
TypeRP uint16 = 17
TypeAFSDB uint16 = 18
TypeX25 uint16 = 19
TypeISDN uint16 = 20
TypeRT uint16 = 21
TypeNSAPPTR uint16 = 23
TypeSIG uint16 = 24
TypeKEY uint16 = 25
TypePX uint16 = 26
TypeGPOS uint16 = 27
TypeAAAA uint16 = 28
TypeLOC uint16 = 29
TypeNXT uint16 = 30
TypeEID uint16 = 31
TypeNIMLOC uint16 = 32
TypeSRV uint16 = 33
TypeATMA uint16 = 34
TypeNAPTR uint16 = 35
TypeKX uint16 = 36
TypeCERT uint16 = 37
TypeDNAME uint16 = 39
TypeOPT uint16 = 41 // EDNS
TypeAPL uint16 = 42
TypeDS uint16 = 43
TypeSSHFP uint16 = 44
TypeRRSIG uint16 = 46
TypeNSEC uint16 = 47
TypeDNSKEY uint16 = 48
TypeDHCID uint16 = 49
TypeNSEC3 uint16 = 50
TypeNSEC3PARAM uint16 = 51
TypeTLSA uint16 = 52
TypeSMIMEA uint16 = 53
TypeHIP uint16 = 55
TypeNINFO uint16 = 56
TypeRKEY uint16 = 57
TypeTALINK uint16 = 58
TypeCDS uint16 = 59
TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61
TypeCSYNC uint16 = 62
TypeZONEMD uint16 = 63
TypeSVCB uint16 = 64
TypeHTTPS uint16 = 65
TypeSPF uint16 = 99
TypeUINFO uint16 = 100
TypeUID uint16 = 101
TypeGID uint16 = 102
TypeUNSPEC uint16 = 103
TypeNID uint16 = 104
TypeL32 uint16 = 105
TypeL64 uint16 = 106
TypeLP uint16 = 107
TypeEUI48 uint16 = 108
TypeEUI64 uint16 = 109
TypeURI uint16 = 256
TypeCAA uint16 = 257
TypeAVC uint16 = 258
TypeTKEY uint16 = 249
TypeTSIG uint16 = 250
// valid Question.Qtype only
TypeIXFR uint16 = 251
TypeAXFR uint16 = 252
TypeMAILB uint16 = 253
TypeMAILA uint16 = 254
TypeANY uint16 = 255
TypeTA uint16 = 32768
TypeDLV uint16 = 32769
TypeReserved uint16 = 65535
// valid Question.Qclass
ClassINET = 1
ClassCSNET = 2
ClassCHAOS = 3
ClassHESIOD = 4
ClassNONE = 254
ClassANY = 255
// 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]
// Message Opcodes. There is no 3.
OpcodeQuery = 0
OpcodeIQuery = 1
OpcodeStatus = 2
OpcodeNotify = 4
OpcodeUpdate = 5
)
// Used in ZONEMD https://tools.ietf.org/html/rfc8976
const (
ZoneMDSchemeSimple = 1
ZoneMDHashAlgSHA384 = 1
ZoneMDHashAlgSHA512 = 2
)
// Header is the wire format for the DNS packet header.
type Header struct {
Id uint16
Bits uint16
Qdcount, Ancount, Nscount, Arcount uint16
}
const (
headerSize = 12
// 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
_Z = 1 << 6 // Z
_AD = 1 << 5 // authenticated data
_CD = 1 << 4 // checking disabled
)
// Various constants used in the LOC RR. See RFC 1887.
const (
LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
LOC_HOURS = 60 * 1000
LOC_DEGREES = 60 * LOC_HOURS
LOC_ALTITUDEBASE = 100000
)
// Different Certificate Types, see RFC 4398, Section 2.1
const (
CertPKIX = 1 + iota
CertSPKI
CertPGP
CertIPIX
CertISPKI
CertIPGP
CertACPKIX
CertIACPKIX
CertURI = 253
CertOID = 254
)
// CertTypeToString converts the Cert Type to its string representation.
// See RFC 4398 and RFC 6944.
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",
}
//go:generate go run types_generate.go
// 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.
type Question struct {
Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
Qtype uint16
Qclass uint16
}
func (q *Question) len(off int, compression map[string]struct{}) int {
l := domainNameLen(q.Name, off, compression, true)
l += 2 + 2
return l
}
func (q *Question) String() (s string) {
// prefix with ; (as in dig)
s = ";" + sprintName(q.Name) + "\t"
s += Class(q.Qclass).String() + "\t"
s += " " + Type(q.Qtype).String()
return s
}
// ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
// is named "*" there.
type ANY struct {
Hdr RR_Header
// Does not have any rdata
}
func (rr *ANY) String() string { return rr.Hdr.String() }
func (*ANY) parse(c *zlexer, origin string) *ParseError {
return &ParseError{err: "ANY records do not have a presentation format"}
}
// NULL RR. See RFC 1035.
type NULL struct {
Hdr RR_Header
Data string `dns:"any"`
}
func (rr *NULL) String() string {
// There is no presentation format; prefix string with a comment.
return ";" + rr.Hdr.String() + rr.Data
}
func (*NULL) parse(c *zlexer, origin string) *ParseError {
return &ParseError{err: "NULL records do not have a presentation format"}
}
// CNAME RR. See RFC 1034.
type CNAME struct {
Hdr RR_Header
Target string `dns:"cdomain-name"`
}
func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
// HINFO RR. See RFC 1034.
type HINFO struct {
Hdr RR_Header
Cpu string
Os string
}
func (rr *HINFO) String() string {
return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
}
// MB RR. See RFC 1035.
type MB struct {
Hdr RR_Header
Mb string `dns:"cdomain-name"`
}
func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
// MG RR. See RFC 1035.
type MG struct {
Hdr RR_Header
Mg string `dns:"cdomain-name"`
}
func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
// MINFO RR. See RFC 1035.
type MINFO struct {
Hdr RR_Header
Rmail string `dns:"cdomain-name"`
Email string `dns:"cdomain-name"`
}
func (rr *MINFO) String() string {
return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
}
// MR RR. See RFC 1035.
type MR struct {
Hdr RR_Header
Mr string `dns:"cdomain-name"`
}
func (rr *MR) String() string {
return rr.Hdr.String() + sprintName(rr.Mr)
}
// MF RR. See RFC 1035.
type MF struct {
Hdr RR_Header
Mf string `dns:"cdomain-name"`
}
func (rr *MF) String() string {
return rr.Hdr.String() + sprintName(rr.Mf)
}
// MD RR. See RFC 1035.
type MD struct {
Hdr RR_Header
Md string `dns:"cdomain-name"`
}
func (rr *MD) String() string {
return rr.Hdr.String() + sprintName(rr.Md)
}
// MX RR. See RFC 1035.
type MX struct {
Hdr RR_Header
Preference uint16
Mx string `dns:"cdomain-name"`
}
func (rr *MX) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
}
// AFSDB RR. See RFC 1183.
type AFSDB struct {
Hdr RR_Header
Subtype uint16
Hostname string `dns:"domain-name"`
}
func (rr *AFSDB) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
}
// X25 RR. See RFC 1183, Section 3.1.
type X25 struct {
Hdr RR_Header
PSDNAddress string
}
func (rr *X25) String() string {
return rr.Hdr.String() + rr.PSDNAddress
}
// RT RR. See RFC 1183, Section 3.3.
type RT struct {
Hdr RR_Header
Preference uint16
Host string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
}
func (rr *RT) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
}
// NS RR. See RFC 1035.
type NS struct {
Hdr RR_Header
Ns string `dns:"cdomain-name"`
}
func (rr *NS) String() string {
return rr.Hdr.String() + sprintName(rr.Ns)
}
// PTR RR. See RFC 1035.
type PTR struct {
Hdr RR_Header
Ptr string `dns:"cdomain-name"`
}
func (rr *PTR) String() string {
return rr.Hdr.String() + sprintName(rr.Ptr)
}
// RP RR. See RFC 1138, Section 2.2.
type RP struct {
Hdr RR_Header
Mbox string `dns:"domain-name"`
Txt string `dns:"domain-name"`
}
func (rr *RP) String() string {
return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
}
// SOA RR. See RFC 1035.
type SOA struct {
Hdr RR_Header
Ns string `dns:"cdomain-name"`
Mbox string `dns:"cdomain-name"`
Serial uint32
Refresh uint32
Retry uint32
Expire uint32
Minttl uint32
}
func (rr *SOA) String() string {
return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
" " + 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)
}
// TXT RR. See RFC 1035.
type TXT struct {
Hdr RR_Header
Txt []string `dns:"txt"`
}
func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
func sprintName(s string) string {
var dst strings.Builder
for i := 0; i < len(s); {
if s[i] == '.' {
if dst.Len() != 0 {
dst.WriteByte('.')
}
i++
continue
}
b, n := nextByte(s, i)
if n == 0 {
// Drop "dangling" incomplete escapes.
if dst.Len() == 0 {
return s[:i]
}
break
}
if isDomainNameLabelSpecial(b) {
if dst.Len() == 0 {
dst.Grow(len(s) * 2)
dst.WriteString(s[:i])
}
dst.WriteByte('\\')
dst.WriteByte(b)
} 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)
}
}
i += n
}
if dst.Len() == 0 {
return s
}
return dst.String()
}
func sprintTxtOctet(s string) string {
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])
i += 2
continue
}
b, n := nextByte(s, i)
if n == 0 {
i++ // dangling back slash
} else {
writeTXTStringByte(&dst, b)
}
i += n
}
dst.WriteByte('"')
return dst.String()
}
func sprintTxt(txt []string) string {
var out strings.Builder
for i, s := range txt {
out.Grow(3 + len(s))
if i > 0 {
out.WriteString(` "`)
} else {
out.WriteByte('"')
}
for j := 0; j < len(s); {
b, n := nextByte(s, j)
if n == 0 {
break
}
writeTXTStringByte(&out, b)
j += n
}
out.WriteByte('"')
}
return out.String()
}
func writeTXTStringByte(s *strings.Builder, b byte) {
switch {
case b == '"' || b == '\\':
s.WriteByte('\\')
s.WriteByte(b)
case b < ' ' || b > '~':
s.WriteString(escapeByte(b))
default:
s.WriteByte(b)
}
}
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]
}
b -= '~' + 1
// The cast here is needed as b*4 may overflow byte.
return escapedByteLarge[int(b)*4 : int(b)*4+4]
}
// 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
}
func nextByte(s string, offset int) (byte, int) {
if offset >= len(s) {
return 0, 0
}
if s[offset] != '\\' {
// not an escape sequence
return s[offset], 1
}
switch len(s) - offset {
case 1: // dangling escape
return 0, 0
case 2, 3: // too short to be \ddd
default: // maybe \ddd
if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
return dddStringToByte(s[offset+1:]), 4
}
}
// not \ddd, just an RFC 1035 "quoted" character
return s[offset+1], 2
}
// SPF RR. See RFC 4408, Section 3.1.1.
type SPF struct {
Hdr RR_Header
Txt []string `dns:"txt"`
}
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
type AVC struct {
Hdr RR_Header
Txt []string `dns:"txt"`
}
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
// SRV RR. See RFC 2782.
type SRV struct {
Hdr RR_Header
Priority uint16
Weight uint16
Port uint16
Target string `dns:"domain-name"`
}
func (rr *SRV) String() string {
return rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
strconv.Itoa(int(rr.Weight)) + " " +
strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
}
// NAPTR RR. See RFC 2915.
type NAPTR struct {
Hdr RR_Header
Order uint16
Preference uint16
Flags string
Service string
Regexp string
Replacement string `dns:"domain-name"`
}
func (rr *NAPTR) String() string {
return rr.Hdr.String() +
strconv.Itoa(int(rr.Order)) + " " +
strconv.Itoa(int(rr.Preference)) + " " +
"\"" + rr.Flags + "\" " +
"\"" + rr.Service + "\" " +
"\"" + rr.Regexp + "\" " +
rr.Replacement
}
// CERT RR. See RFC 4398.
type CERT struct {
Hdr RR_Header
Type uint16
KeyTag uint16
Algorithm uint8
Certificate string `dns:"base64"`
}
func (rr *CERT) String() string {
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 +
" " + strconv.Itoa(int(rr.KeyTag)) +
" " + algorithm +
" " + rr.Certificate
}
// DNAME RR. See RFC 2672.
type DNAME struct {
Hdr RR_Header
Target string `dns:"domain-name"`
}
func (rr *DNAME) String() string {
return rr.Hdr.String() + sprintName(rr.Target)
}
// A RR. See RFC 1035.
type A struct {
Hdr RR_Header
A net.IP `dns:"a"`
}
func (rr *A) String() string {
if rr.A == nil {
return rr.Hdr.String()
}
return rr.Hdr.String() + rr.A.String()
}
// AAAA RR. See RFC 3596.
type AAAA struct {
Hdr RR_Header
AAAA net.IP `dns:"aaaa"`
}
func (rr *AAAA) String() string {
if rr.AAAA == nil {
return rr.Hdr.String()
}
return rr.Hdr.String() + rr.AAAA.String()
}
// PX RR. See RFC 2163.
type PX struct {
Hdr RR_Header
Preference uint16
Map822 string `dns:"domain-name"`
Mapx400 string `dns:"domain-name"`
}
func (rr *PX) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
}
// GPOS RR. See RFC 1712.
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
}
// LOC RR. See RFC RFC 1876.
type LOC struct {
Hdr RR_Header
Version uint8
Size uint8
HorizPre uint8
VertPre uint8
Latitude uint32
Longitude uint32
Altitude uint32
}
// cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
// format and returns a string in m (two decimals for the cm).
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"
e--
}
return s
}
func (rr *LOC) String() string {
s := rr.Hdr.String()
lat := rr.Latitude
ns := "N"
if lat > LOC_EQUATOR {
lat = lat - LOC_EQUATOR
} else {
ns = "S"
lat = LOC_EQUATOR - lat
}
h := lat / LOC_DEGREES
lat = lat % LOC_DEGREES
m := lat / LOC_HOURS
lat = lat % LOC_HOURS
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns)
lon := rr.Longitude
ew := "E"
if lon > LOC_PRIMEMERIDIAN {
lon = lon - LOC_PRIMEMERIDIAN
} else {
ew = "W"
lon = LOC_PRIMEMERIDIAN - lon
}
h = lon / LOC_DEGREES
lon = lon % LOC_DEGREES
m = lon / LOC_HOURS
lon = lon % LOC_HOURS
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
var alt = float64(rr.Altitude) / 100
alt -= LOC_ALTITUDEBASE
if rr.Altitude%100 != 0 {
s += fmt.Sprintf("%.2fm ", alt)
} else {
s += fmt.Sprintf("%.0fm ", alt)
}
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"
return s
}
// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
type SIG struct {
RRSIG
}
// RRSIG RR. See RFC 4034 and RFC 3755.
type RRSIG struct {
Hdr RR_Header
TypeCovered uint16
Algorithm uint8
Labels uint8
OrigTtl uint32
Expiration uint32
Inception uint32
KeyTag uint16
SignerName string `dns:"domain-name"`
Signature string `dns:"base64"`
}
func (rr *RRSIG) String() string {
s := rr.Hdr.String()
s += Type(rr.TypeCovered).String()
s += " " + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.Labels)) +
" " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
" " + TimeToString(rr.Expiration) +
" " + TimeToString(rr.Inception) +
" " + strconv.Itoa(int(rr.KeyTag)) +
" " + sprintName(rr.SignerName) +
" " + rr.Signature
return s
}
// NSEC RR. See RFC 4034 and RFC 3755.
type NSEC struct {
Hdr RR_Header
NextDomain string `dns:"domain-name"`
TypeBitMap []uint16 `dns:"nsec"`
}
func (rr *NSEC) String() string {
s := rr.Hdr.String() + sprintName(rr.NextDomain)
for _, t := range rr.TypeBitMap {
s += " " + Type(t).String()
}
return s
}
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)
l += typeBitMapLen(rr.TypeBitMap)
return l
}
// DLV RR. See RFC 4431.
type DLV struct{ DS }
// CDS RR. See RFC 7344.
type CDS struct{ DS }
// DS RR. See RFC 4034 and RFC 3658.
type DS struct {
Hdr RR_Header
KeyTag uint16
Algorithm uint8
DigestType uint8
Digest string `dns:"hex"`
}
func (rr *DS) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.DigestType)) +
" " + strings.ToUpper(rr.Digest)
}
// KX RR. See RFC 2230.
type KX struct {
Hdr RR_Header
Preference uint16
Exchanger string `dns:"domain-name"`
}
func (rr *KX) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
" " + sprintName(rr.Exchanger)
}
// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
type TA struct {
Hdr RR_Header
KeyTag uint16
Algorithm uint8
DigestType uint8
Digest string `dns:"hex"`
}
func (rr *TA) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.DigestType)) +
" " + strings.ToUpper(rr.Digest)
}
// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
type TALINK struct {
Hdr RR_Header
PreviousName string `dns:"domain-name"`
NextName string `dns:"domain-name"`
}
func (rr *TALINK) String() string {
return rr.Hdr.String() +
sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
}
// SSHFP RR. See RFC RFC 4255.
type SSHFP struct {
Hdr RR_Header
Algorithm uint8
Type uint8
FingerPrint string `dns:"hex"`
}
func (rr *SSHFP) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.Type)) +
" " + strings.ToUpper(rr.FingerPrint)
}
// KEY RR. See RFC RFC 2535.
type KEY struct {
DNSKEY
}
// CDNSKEY RR. See RFC 7344.
type CDNSKEY struct {
DNSKEY
}
// DNSKEY RR. See RFC 4034 and RFC 3755.
type DNSKEY struct {
Hdr RR_Header
Flags uint16
Protocol uint8
Algorithm uint8
PublicKey string `dns:"base64"`
}
func (rr *DNSKEY) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
" " + strconv.Itoa(int(rr.Protocol)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + rr.PublicKey
}
// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
type RKEY struct {
Hdr RR_Header
Flags uint16
Protocol uint8
Algorithm uint8
PublicKey string `dns:"base64"`
}
func (rr *RKEY) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
" " + strconv.Itoa(int(rr.Protocol)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + rr.PublicKey
}
// NSAPPTR RR. See RFC 1348.
type NSAPPTR struct {
Hdr RR_Header
Ptr string `dns:"domain-name"`
}
func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
// NSEC3 RR. See RFC 5155.
type NSEC3 struct {
Hdr RR_Header
Hash uint8
Flags uint8
Iterations uint16
SaltLength uint8
Salt string `dns:"size-hex:SaltLength"`
HashLength uint8
NextDomain string `dns:"size-base32:HashLength"`
TypeBitMap []uint16 `dns:"nsec"`
}
func (rr *NSEC3) String() string {
s := rr.Hdr.String()
s += strconv.Itoa(int(rr.Hash)) +
" " + strconv.Itoa(int(rr.Flags)) +
" " + strconv.Itoa(int(rr.Iterations)) +
" " + saltToString(rr.Salt) +
" " + rr.NextDomain
for _, t := range rr.TypeBitMap {
s += " " + Type(t).String()
}
return s
}
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
l += typeBitMapLen(rr.TypeBitMap)
return l
}
// NSEC3PARAM RR. See RFC 5155.
type NSEC3PARAM struct {
Hdr RR_Header
Hash uint8
Flags uint8
Iterations uint16
SaltLength uint8
Salt string `dns:"size-hex:SaltLength"`
}
func (rr *NSEC3PARAM) String() string {
s := rr.Hdr.String()
s += strconv.Itoa(int(rr.Hash)) +
" " + strconv.Itoa(int(rr.Flags)) +
" " + strconv.Itoa(int(rr.Iterations)) +
" " + saltToString(rr.Salt)
return s
}
// TKEY RR. See RFC 2930.
type TKEY struct {
Hdr RR_Header
Algorithm string `dns:"domain-name"`
Inception uint32
Expiration uint32
Mode uint16
Error uint16
KeySize uint16
Key string `dns:"size-hex:KeySize"`
OtherLen uint16
OtherData string `dns:"size-hex:OtherLen"`
}
// TKEY has no official presentation format, but this will suffice.
func (rr *TKEY) String() string {
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
return s
}
// RFC3597 represents an unknown/generic RR. See RFC 3597.
type RFC3597 struct {
Hdr RR_Header
Rdata string `dns:"hex"`
}
func (rr *RFC3597) String() string {
// Let's call it a hack
s := rfc3597Header(rr.Hdr)
s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
return s
}
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
}
// URI RR. See RFC 7553.
type URI struct {
Hdr RR_Header
Priority uint16
Weight uint16
Target string `dns:"octet"`
}
// rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
func (rr *URI) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
}
// DHCID RR. See RFC 4701.
type DHCID struct {
Hdr RR_Header
Digest string `dns:"base64"`
}
func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
// TLSA RR. See RFC 6698.
type TLSA struct {
Hdr RR_Header
Usage uint8
Selector uint8
MatchingType uint8
Certificate string `dns:"hex"`
}
func (rr *TLSA) String() string {
return rr.Hdr.String() +
strconv.Itoa(int(rr.Usage)) +
" " + strconv.Itoa(int(rr.Selector)) +
" " + strconv.Itoa(int(rr.MatchingType)) +
" " + rr.Certificate
}
// SMIMEA RR. See RFC 8162.
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
}
// HIP RR. See RFC 8005.
type HIP struct {
Hdr RR_Header
HitLength uint8
PublicKeyAlgorithm uint8
PublicKeyLength uint16
Hit string `dns:"size-hex:HitLength"`
PublicKey string `dns:"size-base64:PublicKeyLength"`
RendezvousServers []string `dns:"domain-name"`
}
func (rr *HIP) String() string {
s := rr.Hdr.String() +
strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
" " + rr.Hit +
" " + rr.PublicKey
for _, d := range rr.RendezvousServers {
s += " " + sprintName(d)
}
return s
}
// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
type NINFO struct {
Hdr RR_Header
ZSData []string `dns:"txt"`
}
func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
// NID RR. See RFC RFC 6742.
type NID struct {
Hdr RR_Header
Preference uint16
NodeID uint64
}
func (rr *NID) String() string {
s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
node := fmt.Sprintf("%0.16x", rr.NodeID)
s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
return s
}
// L32 RR, See RFC 6742.
type L32 struct {
Hdr RR_Header
Preference uint16
Locator32 net.IP `dns:"a"`
}
func (rr *L32) String() string {
if rr.Locator32 == nil {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
}
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
" " + rr.Locator32.String()
}
// L64 RR, See RFC 6742.
type L64 struct {
Hdr RR_Header
Preference uint16
Locator64 uint64
}
func (rr *L64) String() string {
s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
node := fmt.Sprintf("%0.16X", rr.Locator64)
s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
return s
}
// LP RR. See RFC 6742.
type LP struct {
Hdr RR_Header
Preference uint16
Fqdn string `dns:"domain-name"`
}
func (rr *LP) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
}
// EUI48 RR. See RFC 7043.
type EUI48 struct {
Hdr RR_Header
Address uint64 `dns:"uint48"`
}
func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
// EUI64 RR. See RFC 7043.
type EUI64 struct {
Hdr RR_Header
Address uint64
}
func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
// CAA RR. See RFC 6844.
type CAA struct {
Hdr RR_Header
Flag uint8
Tag string
Value string `dns:"octet"`
}
// rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
func (rr *CAA) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
}
// UID RR. Deprecated, IANA-Reserved.
type UID struct {
Hdr RR_Header
Uid uint32
}
func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
// GID RR. Deprecated, IANA-Reserved.
type GID struct {
Hdr RR_Header
Gid uint32
}
func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
// UINFO RR. Deprecated, IANA-Reserved.
type UINFO struct {
Hdr RR_Header
Uinfo string
}
func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
type EID struct {
Hdr RR_Header
Endpoint string `dns:"hex"`
}
func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
type NIMLOC struct {
Hdr RR_Header
Locator string `dns:"hex"`
}
func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
// OPENPGPKEY RR. See RFC 7929.
type OPENPGPKEY struct {
Hdr RR_Header
PublicKey string `dns:"base64"`
}
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
// 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))
for _, t := range rr.TypeBitMap {
s += " " + Type(t).String()
}
return s
}
func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 4 + 2
l += typeBitMapLen(rr.TypeBitMap)
return l
}
// 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
}
// 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.
func (a *APLPrefix) str() string {
var sb strings.Builder
if a.Negation {
sb.WriteByte('!')
}
switch len(a.Network.IP) {
case net.IPv4len:
sb.WriteByte('1')
case net.IPv6len:
sb.WriteByte('2')
}
sb.WriteByte(':')
switch len(a.Network.IP) {
case net.IPv4len:
sb.WriteString(a.Network.IP.String())
case net.IPv6len:
// add prefix for IPv4-mapped IPv6
if v4 := a.Network.IP.To4(); v4 != nil {
sb.WriteString("::ffff:")
}
sb.WriteString(a.Network.IP.String())
}
sb.WriteByte('/')
prefix, _ := a.Network.Mask.Size()
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.
func (a *APLPrefix) copy() APLPrefix {
return APLPrefix{
Negation: a.Negation,
Network: copyNet(a.Network),
}
}
// len returns size of the prefix in wire format.
func (a *APLPrefix) len() int {
// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
prefix, _ := a.Network.Mask.Size()
return 4 + (prefix+7)/8
}
// TimeToString translates the RRSIG's incep. and expir. times to the
// string representation used when printing the record.
// It takes serial arithmetic (RFC 1982) into account.
func TimeToString(t uint32) string {
mod := (int64(t)-time.Now().Unix())/year68 - 1
if mod < 0 {
mod = 0
}
ti := time.Unix(int64(t)-mod*year68, 0).UTC()
return ti.Format("20060102150405")
}
// StringToTime translates the RRSIG's incep. and expir. times from
// string values like "20110403154150" to an 32 bit integer.
// It takes serial arithmetic (RFC 1982) into account.
func StringToTime(s string) (uint32, error) {
t, err := time.Parse("20060102150405", s)
if err != nil {
return 0, err
}
mod := t.Unix()/year68 - 1
if mod < 0 {
mod = 0
}
return uint32(t.Unix() - mod*year68), nil
}
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
func saltToString(s string) string {
if s == "" {
return "-"
}
return strings.ToUpper(s)
}
func euiToString(eui uint64, bits int) (hex string) {
switch bits {
case 64:
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]
case 48:
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]
}
return
}
// copyIP returns a copy of ip.
func copyIP(ip net.IP) net.IP {
p := make(net.IP, len(ip))
copy(p, ip)
return p
}
// 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,
}
}
// 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
}
// +build !windows
package dns
import (
"net"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
// This is the required size of the OOB buffer to pass to ReadMsgUDP.
var udpOOBSize = func() int {
// We can't know whether we'll get an IPv4 control message or an
// IPv6 control message ahead of time. To get around this, we size
// the buffer equal to the largest of the two.
oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface)
oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface)
if len(oob4) > len(oob6) {
return len(oob4)
}
return len(oob6)
}()
// SessionUDP holds the remote address and the associated
// out-of-band data.
type SessionUDP struct {
raddr *net.UDPAddr
context []byte
}
// RemoteAddr returns the remote network address.
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
oob := make([]byte, udpOOBSize)
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
if err != nil {
return n, nil, err
}
return n, &SessionUDP{raddr, oob[:oobn]}, err
}
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
oob := correctSource(session.context)
n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
return n, err
}
func setUDPSocketOptions(conn *net.UDPConn) error {
// Try setting the flags for both families and ignore the errors unless they
// both error.
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
if err6 != nil && err4 != nil {
return err4
}
return nil
}
// parseDstFromOOB takes oob data and returns the destination IP.
func parseDstFromOOB(oob []byte) net.IP {
// Start with IPv6 and then fallback to IPv4
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
// the lvl of the header for a 0 or 41 isn't cross-platform.
cm6 := new(ipv6.ControlMessage)
if cm6.Parse(oob) == nil && cm6.Dst != nil {
return cm6.Dst
}
cm4 := new(ipv4.ControlMessage)
if cm4.Parse(oob) == nil && cm4.Dst != nil {
return cm4.Dst
}
return nil
}
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
func correctSource(oob []byte) []byte {
dst := parseDstFromOOB(oob)
if dst == nil {
return nil
}
// If the dst is definitely an IPv6, then use ipv6's ControlMessage to
// respond otherwise use ipv4's because ipv6's marshal ignores ipv4
// addresses.
if dst.To4() == nil {
cm := new(ipv6.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
} else {
cm := new(ipv4.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
}
return oob
}
// +build windows
package dns
import "net"
// SessionUDP holds the remote address
type SessionUDP struct {
raddr *net.UDPAddr
}
// RemoteAddr returns the remote network address.
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
n, raddr, err := conn.ReadFrom(b)
if err != nil {
return n, nil, err
}
return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
}
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
return conn.WriteTo(b, session.raddr)
}
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
// use the standard method in udp.go for these.
func setUDPSocketOptions(*net.UDPConn) error { return nil }
func parseDstFromOOB([]byte, net.IP) net.IP { return nil }
package dns
// NameUsed sets the RRs in the prereq section to
// "Name is in use" RRs. RFC 2136 section 2.4.4.
func (u *Msg) NameUsed(rr []RR) {
if u.Answer == nil {
u.Answer = make([]RR, 0, len(rr))
}
for _, r := range rr {
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
}
}
// NameNotUsed sets the RRs in the prereq section to
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
func (u *Msg) NameNotUsed(rr []RR) {
if u.Answer == nil {
u.Answer = make([]RR, 0, len(rr))
}
for _, r := range rr {
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
}
}
// Used sets the RRs in the prereq section to
// "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.
func (u *Msg) Used(rr []RR) {
if len(u.Question) == 0 {
panic("dns: empty question section")
}
if u.Answer == nil {
u.Answer = make([]RR, 0, len(rr))
}
for _, r := range rr {
hdr := r.Header()
hdr.Class = u.Question[0].Qclass
hdr.Ttl = 0
u.Answer = append(u.Answer, r)
}
}
// RRsetUsed sets the RRs in the prereq section to
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
func (u *Msg) RRsetUsed(rr []RR) {
if u.Answer == nil {
u.Answer = make([]RR, 0, len(rr))
}
for _, r := range rr {
h := r.Header()
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
}
}
// RRsetNotUsed sets the RRs in the prereq section to
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
func (u *Msg) RRsetNotUsed(rr []RR) {
if u.Answer == nil {
u.Answer = make([]RR, 0, len(rr))
}
for _, r := range rr {
h := r.Header()
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassNONE}})
}
}
// Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.
func (u *Msg) Insert(rr []RR) {
if len(u.Question) == 0 {
panic("dns: empty question section")
}
if u.Ns == nil {
u.Ns = make([]RR, 0, len(rr))
}
for _, r := range rr {
r.Header().Class = u.Question[0].Qclass
u.Ns = append(u.Ns, r)
}
}
// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
func (u *Msg) RemoveRRset(rr []RR) {
if u.Ns == nil {
u.Ns = make([]RR, 0, len(rr))
}
for _, r := range rr {
h := r.Header()
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
}
}
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
func (u *Msg) RemoveName(rr []RR) {
if u.Ns == nil {
u.Ns = make([]RR, 0, len(rr))
}
for _, r := range rr {
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
}
}
// Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
func (u *Msg) Remove(rr []RR) {
if u.Ns == nil {
u.Ns = make([]RR, 0, len(rr))
}
for _, r := range rr {
h := r.Header()
h.Class = ClassNONE
h.Ttl = 0
u.Ns = append(u.Ns, r)
}
}
package dns
import "fmt"
// Version is current version of this library.
var Version = v{1, 1, 50}
// v holds the version of this library.
type v struct {
Major, Minor, Patch int
}
func (v v) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
package dns
import (
"fmt"
"time"
)
// Envelope is used when doing a zone transfer with a remote server.
type Envelope struct {
RR []RR // The set of RRs in the answer section of the xfr reply message.
Error error // If something went wrong, this contains the error.
}
// A Transfer defines parameters that are used during a zone transfer.
type Transfer struct {
*Conn
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
tsigTimersOnly bool
}
func (t *Transfer) tsigProvider() TsigProvider {
if t.TsigProvider != nil {
return t.TsigProvider
}
if t.TsigSecret != nil {
return tsigSecretProvider(t.TsigSecret)
}
return nil
}
// TODO: Think we need to away to stop the transfer
// In performs an incoming transfer with the server in a.
// If you would like to set the source IP, or some other attribute
// of a Dialer for a Transfer, you can do so by specifying the attributes
// in the Transfer.Conn:
//
// d := net.Dialer{LocalAddr: transfer_source}
// con, err := d.Dial("tcp", master)
// dnscon := &dns.Conn{Conn:con}
// transfer = &dns.Transfer{Conn: dnscon}
// channel, err := transfer.In(message, master)
//
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
switch q.Question[0].Qtype {
case TypeAXFR, TypeIXFR:
default:
return nil, &Error{"unsupported question type"}
}
timeout := dnsTimeout
if t.DialTimeout != 0 {
timeout = t.DialTimeout
}
if t.Conn == nil {
t.Conn, err = DialTimeout("tcp", a, timeout)
if err != nil {
return nil, err
}
}
if err := t.WriteMsg(q); err != nil {
return nil, err
}
env = make(chan *Envelope)
switch q.Question[0].Qtype {
case TypeAXFR:
go t.inAxfr(q, env)
case TypeIXFR:
go t.inIxfr(q, env)
}
return env, nil
}
func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
first := true
defer t.Close()
defer close(c)
timeout := dnsTimeout
if t.ReadTimeout != 0 {
timeout = t.ReadTimeout
}
for {
t.Conn.SetReadDeadline(time.Now().Add(timeout))
in, err := t.ReadMsg()
if err != nil {
c <- &Envelope{nil, err}
return
}
if q.Id != in.Id {
c <- &Envelope{in.Answer, ErrId}
return
}
if first {
if in.Rcode != RcodeSuccess {
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
return
}
if !isSOAFirst(in) {
c <- &Envelope{in.Answer, ErrSoa}
return
}
first = !first
// only one answer that is SOA, receive more
if len(in.Answer) == 1 {
t.tsigTimersOnly = true
c <- &Envelope{in.Answer, nil}
continue
}
}
if !first {
t.tsigTimersOnly = true // Subsequent envelopes use this.
if isSOALast(in) {
c <- &Envelope{in.Answer, nil}
return
}
c <- &Envelope{in.Answer, nil}
}
}
}
func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
var serial uint32 // The first serial seen is the current server serial
axfr := true
n := 0
qser := q.Ns[0].(*SOA).Serial
defer t.Close()
defer close(c)
timeout := dnsTimeout
if t.ReadTimeout != 0 {
timeout = t.ReadTimeout
}
for {
t.SetReadDeadline(time.Now().Add(timeout))
in, err := t.ReadMsg()
if err != nil {
c <- &Envelope{nil, err}
return
}
if q.Id != in.Id {
c <- &Envelope{in.Answer, ErrId}
return
}
if in.Rcode != RcodeSuccess {
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
return
}
if n == 0 {
// Check if the returned answer is ok
if !isSOAFirst(in) {
c <- &Envelope{in.Answer, ErrSoa}
return
}
// This serial is important
serial = in.Answer[0].(*SOA).Serial
// Check if there are no changes in zone
if qser >= serial {
c <- &Envelope{in.Answer, nil}
return
}
}
// Now we need to check each message for SOA records, to see what we need to do
t.tsigTimersOnly = true
for _, rr := range in.Answer {
if v, ok := rr.(*SOA); ok {
if v.Serial == serial {
n++
// quit if it's a full axfr or the the servers' SOA is repeated the third time
if axfr && n == 2 || n == 3 {
c <- &Envelope{in.Answer, nil}
return
}
} else if axfr {
// it's an ixfr
axfr = false
}
}
}
c <- &Envelope{in.Answer, nil}
}
}
// Out performs an outgoing transfer with the client connecting in w.
// Basic use pattern:
//
// ch := make(chan *dns.Envelope)
// tr := new(dns.Transfer)
// var wg sync.WaitGroup
// go func() {
// tr.Out(w, r, ch)
// wg.Done()
// }()
// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
// close(ch)
// wg.Wait() // wait until everything is written out
// w.Close() // close connection
//
// The server is responsible for sending the correct sequence of RRs through the channel ch.
func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
for x := range ch {
r := new(Msg)
// Compress?
r.SetReply(q)
r.Authoritative = true
// assume it fits TODO(miek): fix
r.Answer = append(r.Answer, x.RR...)
if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
}
if err := w.WriteMsg(r); err != nil {
return err
}
w.TsigTimersOnly(true)
}
return nil
}
// ReadMsg reads a message from the transfer connection t.
func (t *Transfer) ReadMsg() (*Msg, error) {
m := new(Msg)
p := make([]byte, MaxMsgSize)
n, err := t.Read(p)
if err != nil && n == 0 {
return nil, err
}
p = p[:n]
if err := m.Unpack(p); err != nil {
return nil, err
}
if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
// Need to work on the original message p, as that was used to calculate the tsig.
err = TsigVerifyWithProvider(p, tp, t.tsigRequestMAC, t.tsigTimersOnly)
t.tsigRequestMAC = ts.MAC
}
return m, err
}
// WriteMsg writes a message through the transfer connection t.
func (t *Transfer) WriteMsg(m *Msg) (err error) {
var out []byte
if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
out, t.tsigRequestMAC, err = TsigGenerateWithProvider(m, tp, t.tsigRequestMAC, t.tsigTimersOnly)
} else {
out, err = m.Pack()
}
if err != nil {
return err
}
_, err = t.Write(out)
return err
}
func isSOAFirst(in *Msg) bool {
return len(in.Answer) > 0 &&
in.Answer[0].Header().Rrtype == TypeSOA
}
func isSOALast(in *Msg) bool {
return len(in.Answer) > 0 &&
in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
}
const errXFR = "bad xfr rcode: %d"
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
package dns
// isDuplicate() functions
func (r1 *A) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*A)
if !ok {
return false
}
_ = r2
if !r1.A.Equal(r2.A) {
return false
}
return true
}
func (r1 *AAAA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*AAAA)
if !ok {
return false
}
_ = r2
if !r1.AAAA.Equal(r2.AAAA) {
return false
}
return true
}
func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*AFSDB)
if !ok {
return false
}
_ = r2
if r1.Subtype != r2.Subtype {
return false
}
if !isDuplicateName(r1.Hostname, r2.Hostname) {
return false
}
return true
}
func (r1 *ANY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*ANY)
if !ok {
return false
}
_ = r2
return true
}
func (r1 *APL) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*APL)
if !ok {
return false
}
_ = r2
if len(r1.Prefixes) != len(r2.Prefixes) {
return false
}
for i := 0; i < len(r1.Prefixes); i++ {
if !r1.Prefixes[i].equals(&r2.Prefixes[i]) {
return false
}
}
return true
}
func (r1 *AVC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*AVC)
if !ok {
return false
}
_ = r2
if len(r1.Txt) != len(r2.Txt) {
return false
}
for i := 0; i < len(r1.Txt); i++ {
if r1.Txt[i] != r2.Txt[i] {
return false
}
}
return true
}
func (r1 *CAA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CAA)
if !ok {
return false
}
_ = r2
if r1.Flag != r2.Flag {
return false
}
if r1.Tag != r2.Tag {
return false
}
if r1.Value != r2.Value {
return false
}
return true
}
func (r1 *CDNSKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDNSKEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *CDS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDS)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *CERT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CERT)
if !ok {
return false
}
_ = r2
if r1.Type != r2.Type {
return false
}
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Certificate != r2.Certificate {
return false
}
return true
}
func (r1 *CNAME) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CNAME)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
return true
}
func (r1 *CSYNC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CSYNC)
if !ok {
return false
}
_ = r2
if r1.Serial != r2.Serial {
return false
}
if r1.Flags != r2.Flags {
return false
}
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
return false
}
for i := 0; i < len(r1.TypeBitMap); i++ {
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
return false
}
}
return true
}
func (r1 *DHCID) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DHCID)
if !ok {
return false
}
_ = r2
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *DLV) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DLV)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *DNAME) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DNAME)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
return true
}
func (r1 *DNSKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DNSKEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *DS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DS)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *EID) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*EID)
if !ok {
return false
}
_ = r2
if r1.Endpoint != r2.Endpoint {
return false
}
return true
}
func (r1 *EUI48) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*EUI48)
if !ok {
return false
}
_ = r2
if r1.Address != r2.Address {
return false
}
return true
}
func (r1 *EUI64) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*EUI64)
if !ok {
return false
}
_ = r2
if r1.Address != r2.Address {
return false
}
return true
}
func (r1 *GID) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*GID)
if !ok {
return false
}
_ = r2
if r1.Gid != r2.Gid {
return false
}
return true
}
func (r1 *GPOS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*GPOS)
if !ok {
return false
}
_ = r2
if r1.Longitude != r2.Longitude {
return false
}
if r1.Latitude != r2.Latitude {
return false
}
if r1.Altitude != r2.Altitude {
return false
}
return true
}
func (r1 *HINFO) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HINFO)
if !ok {
return false
}
_ = r2
if r1.Cpu != r2.Cpu {
return false
}
if r1.Os != r2.Os {
return false
}
return true
}
func (r1 *HIP) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HIP)
if !ok {
return false
}
_ = r2
if r1.HitLength != r2.HitLength {
return false
}
if r1.PublicKeyAlgorithm != r2.PublicKeyAlgorithm {
return false
}
if r1.PublicKeyLength != r2.PublicKeyLength {
return false
}
if r1.Hit != r2.Hit {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
if len(r1.RendezvousServers) != len(r2.RendezvousServers) {
return false
}
for i := 0; i < len(r1.RendezvousServers); i++ {
if !isDuplicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
return false
}
}
return true
}
func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HTTPS)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *KEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *KX) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KX)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !isDuplicateName(r1.Exchanger, r2.Exchanger) {
return false
}
return true
}
func (r1 *L32) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*L32)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !r1.Locator32.Equal(r2.Locator32) {
return false
}
return true
}
func (r1 *L64) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*L64)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if r1.Locator64 != r2.Locator64 {
return false
}
return true
}
func (r1 *LOC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*LOC)
if !ok {
return false
}
_ = r2
if r1.Version != r2.Version {
return false
}
if r1.Size != r2.Size {
return false
}
if r1.HorizPre != r2.HorizPre {
return false
}
if r1.VertPre != r2.VertPre {
return false
}
if r1.Latitude != r2.Latitude {
return false
}
if r1.Longitude != r2.Longitude {
return false
}
if r1.Altitude != r2.Altitude {
return false
}
return true
}
func (r1 *LP) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*LP)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !isDuplicateName(r1.Fqdn, r2.Fqdn) {
return false
}
return true
}
func (r1 *MB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MB)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Mb, r2.Mb) {
return false
}
return true
}
func (r1 *MD) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MD)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Md, r2.Md) {
return false
}
return true
}
func (r1 *MF) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MF)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Mf, r2.Mf) {
return false
}
return true
}
func (r1 *MG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MG)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Mg, r2.Mg) {
return false
}
return true
}
func (r1 *MINFO) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MINFO)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Rmail, r2.Rmail) {
return false
}
if !isDuplicateName(r1.Email, r2.Email) {
return false
}
return true
}
func (r1 *MR) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MR)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Mr, r2.Mr) {
return false
}
return true
}
func (r1 *MX) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*MX)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !isDuplicateName(r1.Mx, r2.Mx) {
return false
}
return true
}
func (r1 *NAPTR) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NAPTR)
if !ok {
return false
}
_ = r2
if r1.Order != r2.Order {
return false
}
if r1.Preference != r2.Preference {
return false
}
if r1.Flags != r2.Flags {
return false
}
if r1.Service != r2.Service {
return false
}
if r1.Regexp != r2.Regexp {
return false
}
if !isDuplicateName(r1.Replacement, r2.Replacement) {
return false
}
return true
}
func (r1 *NID) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NID)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if r1.NodeID != r2.NodeID {
return false
}
return true
}
func (r1 *NIMLOC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NIMLOC)
if !ok {
return false
}
_ = r2
if r1.Locator != r2.Locator {
return false
}
return true
}
func (r1 *NINFO) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NINFO)
if !ok {
return false
}
_ = r2
if len(r1.ZSData) != len(r2.ZSData) {
return false
}
for i := 0; i < len(r1.ZSData); i++ {
if r1.ZSData[i] != r2.ZSData[i] {
return false
}
}
return true
}
func (r1 *NS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NS)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Ns, r2.Ns) {
return false
}
return true
}
func (r1 *NSAPPTR) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NSAPPTR)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Ptr, r2.Ptr) {
return false
}
return true
}
func (r1 *NSEC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NSEC)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
return false
}
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
return false
}
for i := 0; i < len(r1.TypeBitMap); i++ {
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
return false
}
}
return true
}
func (r1 *NSEC3) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NSEC3)
if !ok {
return false
}
_ = r2
if r1.Hash != r2.Hash {
return false
}
if r1.Flags != r2.Flags {
return false
}
if r1.Iterations != r2.Iterations {
return false
}
if r1.SaltLength != r2.SaltLength {
return false
}
if r1.Salt != r2.Salt {
return false
}
if r1.HashLength != r2.HashLength {
return false
}
if r1.NextDomain != r2.NextDomain {
return false
}
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
return false
}
for i := 0; i < len(r1.TypeBitMap); i++ {
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
return false
}
}
return true
}
func (r1 *NSEC3PARAM) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NSEC3PARAM)
if !ok {
return false
}
_ = r2
if r1.Hash != r2.Hash {
return false
}
if r1.Flags != r2.Flags {
return false
}
if r1.Iterations != r2.Iterations {
return false
}
if r1.SaltLength != r2.SaltLength {
return false
}
if r1.Salt != r2.Salt {
return false
}
return true
}
func (r1 *NULL) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NULL)
if !ok {
return false
}
_ = r2
if r1.Data != r2.Data {
return false
}
return true
}
func (r1 *OPENPGPKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*OPENPGPKEY)
if !ok {
return false
}
_ = r2
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *PTR) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*PTR)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Ptr, r2.Ptr) {
return false
}
return true
}
func (r1 *PX) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*PX)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !isDuplicateName(r1.Map822, r2.Map822) {
return false
}
if !isDuplicateName(r1.Mapx400, r2.Mapx400) {
return false
}
return true
}
func (r1 *RFC3597) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RFC3597)
if !ok {
return false
}
_ = r2
if r1.Rdata != r2.Rdata {
return false
}
return true
}
func (r1 *RKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RKEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *RP) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RP)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Mbox, r2.Mbox) {
return false
}
if !isDuplicateName(r1.Txt, r2.Txt) {
return false
}
return true
}
func (r1 *RRSIG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RRSIG)
if !ok {
return false
}
_ = r2
if r1.TypeCovered != r2.TypeCovered {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Labels != r2.Labels {
return false
}
if r1.OrigTtl != r2.OrigTtl {
return false
}
if r1.Expiration != r2.Expiration {
return false
}
if r1.Inception != r2.Inception {
return false
}
if r1.KeyTag != r2.KeyTag {
return false
}
if !isDuplicateName(r1.SignerName, r2.SignerName) {
return false
}
if r1.Signature != r2.Signature {
return false
}
return true
}
func (r1 *RT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RT)
if !ok {
return false
}
_ = r2
if r1.Preference != r2.Preference {
return false
}
if !isDuplicateName(r1.Host, r2.Host) {
return false
}
return true
}
func (r1 *SIG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SIG)
if !ok {
return false
}
_ = r2
if r1.TypeCovered != r2.TypeCovered {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Labels != r2.Labels {
return false
}
if r1.OrigTtl != r2.OrigTtl {
return false
}
if r1.Expiration != r2.Expiration {
return false
}
if r1.Inception != r2.Inception {
return false
}
if r1.KeyTag != r2.KeyTag {
return false
}
if !isDuplicateName(r1.SignerName, r2.SignerName) {
return false
}
if r1.Signature != r2.Signature {
return false
}
return true
}
func (r1 *SMIMEA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SMIMEA)
if !ok {
return false
}
_ = r2
if r1.Usage != r2.Usage {
return false
}
if r1.Selector != r2.Selector {
return false
}
if r1.MatchingType != r2.MatchingType {
return false
}
if r1.Certificate != r2.Certificate {
return false
}
return true
}
func (r1 *SOA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SOA)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Ns, r2.Ns) {
return false
}
if !isDuplicateName(r1.Mbox, r2.Mbox) {
return false
}
if r1.Serial != r2.Serial {
return false
}
if r1.Refresh != r2.Refresh {
return false
}
if r1.Retry != r2.Retry {
return false
}
if r1.Expire != r2.Expire {
return false
}
if r1.Minttl != r2.Minttl {
return false
}
return true
}
func (r1 *SPF) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SPF)
if !ok {
return false
}
_ = r2
if len(r1.Txt) != len(r2.Txt) {
return false
}
for i := 0; i < len(r1.Txt); i++ {
if r1.Txt[i] != r2.Txt[i] {
return false
}
}
return true
}
func (r1 *SRV) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SRV)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if r1.Weight != r2.Weight {
return false
}
if r1.Port != r2.Port {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
return true
}
func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SSHFP)
if !ok {
return false
}
_ = r2
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Type != r2.Type {
return false
}
if r1.FingerPrint != r2.FingerPrint {
return false
}
return true
}
func (r1 *SVCB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SVCB)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *TA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TA)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *TALINK) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TALINK)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.PreviousName, r2.PreviousName) {
return false
}
if !isDuplicateName(r1.NextName, r2.NextName) {
return false
}
return true
}
func (r1 *TKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TKEY)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
return false
}
if r1.Inception != r2.Inception {
return false
}
if r1.Expiration != r2.Expiration {
return false
}
if r1.Mode != r2.Mode {
return false
}
if r1.Error != r2.Error {
return false
}
if r1.KeySize != r2.KeySize {
return false
}
if r1.Key != r2.Key {
return false
}
if r1.OtherLen != r2.OtherLen {
return false
}
if r1.OtherData != r2.OtherData {
return false
}
return true
}
func (r1 *TLSA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TLSA)
if !ok {
return false
}
_ = r2
if r1.Usage != r2.Usage {
return false
}
if r1.Selector != r2.Selector {
return false
}
if r1.MatchingType != r2.MatchingType {
return false
}
if r1.Certificate != r2.Certificate {
return false
}
return true
}
func (r1 *TSIG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TSIG)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
return false
}
if r1.TimeSigned != r2.TimeSigned {
return false
}
if r1.Fudge != r2.Fudge {
return false
}
if r1.MACSize != r2.MACSize {
return false
}
if r1.MAC != r2.MAC {
return false
}
if r1.OrigId != r2.OrigId {
return false
}
if r1.Error != r2.Error {
return false
}
if r1.OtherLen != r2.OtherLen {
return false
}
if r1.OtherData != r2.OtherData {
return false
}
return true
}
func (r1 *TXT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TXT)
if !ok {
return false
}
_ = r2
if len(r1.Txt) != len(r2.Txt) {
return false
}
for i := 0; i < len(r1.Txt); i++ {
if r1.Txt[i] != r2.Txt[i] {
return false
}
}
return true
}
func (r1 *UID) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*UID)
if !ok {
return false
}
_ = r2
if r1.Uid != r2.Uid {
return false
}
return true
}
func (r1 *UINFO) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*UINFO)
if !ok {
return false
}
_ = r2
if r1.Uinfo != r2.Uinfo {
return false
}
return true
}
func (r1 *URI) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*URI)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if r1.Weight != r2.Weight {
return false
}
if r1.Target != r2.Target {
return false
}
return true
}
func (r1 *X25) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*X25)
if !ok {
return false
}
_ = r2
if r1.PSDNAddress != r2.PSDNAddress {
return false
}
return true
}
func (r1 *ZONEMD) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*ZONEMD)
if !ok {
return false
}
_ = r2
if r1.Serial != r2.Serial {
return false
}
if r1.Scheme != r2.Scheme {
return false
}
if r1.Hash != r2.Hash {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
package dns
// pack*() functions
func (rr *A) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDataA(rr.A, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AAAA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDataAAAA(rr.AAAA, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AFSDB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Subtype, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Hostname, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
return off, nil
}
func (rr *APL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDataApl(rr.Prefixes, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringTxt(rr.Txt, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CAA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Flag, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Tag, msg, off)
if err != nil {
return off, err
}
off, err = packStringOctet(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CDNSKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Protocol, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CDS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.DigestType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CERT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Type, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.Certificate, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Target, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CSYNC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint32(rr.Serial, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packDataNsec(rr.TypeBitMap, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DHCID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringBase64(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DLV) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.DigestType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DNSKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Protocol, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.DigestType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *EID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringHex(rr.Endpoint, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *EUI48) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint48(rr.Address, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *EUI64) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint64(rr.Address, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *GID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint32(rr.Gid, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *GPOS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packString(rr.Longitude, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Latitude, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Altitude, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *HINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packString(rr.Cpu, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Os, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.HitLength, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.PublicKeyAlgorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.PublicKeyLength, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Hit, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
off, err = packDataDomainNames(rr.RendezvousServers, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Protocol, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Exchanger, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *L32) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDataA(rr.Locator32, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *L64) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packUint64(rr.Locator64, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *LOC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Version, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Size, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.HorizPre, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.VertPre, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Latitude, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Longitude, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Altitude, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *LP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Fqdn, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Mb, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MD) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Md, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MF) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Mf, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Mg, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Rmail, msg, off, compression, compress)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Email, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Mr, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Mx, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NAPTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Order, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Service, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.Regexp, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Replacement, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packUint64(rr.NodeID, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NIMLOC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringHex(rr.Locator, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringTxt(rr.ZSData, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Ns, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSAPPTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Ptr, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.NextDomain, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataNsec(rr.TypeBitMap, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC3) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Hash, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Iterations, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.SaltLength, msg, off)
if err != nil {
return off, err
}
// Only pack salt if value is not "-", i.e. empty
if rr.Salt != "-" {
off, err = packStringHex(rr.Salt, msg, off)
if err != nil {
return off, err
}
}
off, err = packUint8(rr.HashLength, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase32(rr.NextDomain, msg, off)
if err != nil {
return off, err
}
off, err = packDataNsec(rr.TypeBitMap, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC3PARAM) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Hash, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Iterations, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.SaltLength, msg, off)
if err != nil {
return off, err
}
// Only pack salt if value is not "-", i.e. empty
if rr.Salt != "-" {
off, err = packStringHex(rr.Salt, msg, off)
if err != nil {
return off, err
}
}
return off, nil
}
func (rr *NULL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringAny(rr.Data, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPENPGPKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDataOpt(rr.Option, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *PTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Ptr, msg, off, compression, compress)
if err != nil {
return off, err
}
return off, nil
}
func (rr *PX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Map822, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Mapx400, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RFC3597) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringHex(rr.Rdata, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Protocol, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Mbox, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Txt, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RRSIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.TypeCovered, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Labels, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.OrigTtl, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Expiration, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Inception, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.SignerName, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.Signature, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Preference, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Host, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.TypeCovered, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Labels, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.OrigTtl, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Expiration, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Inception, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.SignerName, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packStringBase64(rr.Signature, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SMIMEA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Usage, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Selector, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.MatchingType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Certificate, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SOA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Ns, msg, off, compression, compress)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Mbox, msg, off, compression, compress)
if err != nil {
return off, err
}
off, err = packUint32(rr.Serial, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Refresh, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Retry, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Expire, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Minttl, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SPF) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringTxt(rr.Txt, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SRV) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Weight, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Port, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Type, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.FingerPrint, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SVCB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.DigestType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TALINK) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.PreviousName, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDomainName(rr.NextName, msg, off, compression, false)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packUint32(rr.Inception, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(rr.Expiration, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Mode, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Error, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.KeySize, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Key, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.OtherLen, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.OtherData, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TLSA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint8(rr.Usage, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Selector, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.MatchingType, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Certificate, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TSIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packUint48(rr.TimeSigned, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Fudge, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.MACSize, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.MAC, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.OrigId, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Error, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.OtherLen, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.OtherData, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TXT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringTxt(rr.Txt, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *UID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint32(rr.Uid, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *UINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packString(rr.Uinfo, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *URI) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(rr.Weight, msg, off)
if err != nil {
return off, err
}
off, err = packStringOctet(rr.Target, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *X25) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packString(rr.PSDNAddress, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *ZONEMD) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint32(rr.Serial, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Scheme, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Hash, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
// unpack*() functions
func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.A, off, err = unpackDataA(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AAAA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.AAAA, off, err = unpackDataAAAA(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AFSDB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Subtype, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Hostname, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
return off, nil
}
func (rr *APL) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Prefixes, off, err = unpackDataApl(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Txt, off, err = unpackStringTxt(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CAA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Flag, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Tag, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackStringOctet(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CDNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Flags, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Protocol, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *CDS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.DigestType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *CERT) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Type, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Certificate, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *CNAME) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *CSYNC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Serial, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Flags, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DHCID) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Digest, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *DLV) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.DigestType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *DNAME) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *DNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Flags, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Protocol, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *DS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.DigestType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *EID) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Endpoint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *EUI48) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Address, off, err = unpackUint48(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *EUI64) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Address, off, err = unpackUint64(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *GID) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Gid, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *GPOS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Longitude, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Latitude, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Altitude, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *HINFO) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Cpu, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Os, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.HitLength, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKeyAlgorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKeyLength, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Hit, off, err = unpackStringHex(msg, off, off+int(rr.HitLength))
if err != nil {
return off, err
}
rr.PublicKey, off, err = unpackStringBase64(msg, off, off+int(rr.PublicKeyLength))
if err != nil {
return off, err
}
rr.RendezvousServers, off, err = unpackDataDomainNames(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Flags, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Protocol, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *KX) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Exchanger, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *L32) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Locator32, off, err = unpackDataA(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *L64) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Locator64, off, err = unpackUint64(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *LOC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Version, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Size, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.HorizPre, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.VertPre, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Latitude, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Longitude, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Altitude, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *LP) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Fqdn, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Mb, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MD) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Md, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MF) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Mf, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MG) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Mg, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MINFO) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Rmail, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Email, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MR) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Mr, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *MX) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Mx, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NAPTR) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Order, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Flags, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Service, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Regexp, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Replacement, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NID) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.NodeID, off, err = unpackUint64(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NIMLOC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Locator, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *NINFO) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.ZSData, off, err = unpackStringTxt(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Ns, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSAPPTR) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Ptr, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.NextDomain, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC3) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Hash, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Flags, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Iterations, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.SaltLength, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
if err != nil {
return off, err
}
rr.HashLength, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.NextDomain, off, err = unpackStringBase32(msg, off, off+int(rr.HashLength))
if err != nil {
return off, err
}
rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *NSEC3PARAM) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Hash, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Flags, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Iterations, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.SaltLength, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Data, off, err = unpackStringAny(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPENPGPKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPT) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Option, off, err = unpackDataOpt(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *PTR) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Ptr, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *PX) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Map822, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Mapx400, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RFC3597) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Rdata, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *RKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Flags, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Protocol, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *RP) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Mbox, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Txt, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *RRSIG) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.TypeCovered, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Labels, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.OrigTtl, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Expiration, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Inception, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.SignerName, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *RT) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Preference, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Host, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SIG) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.TypeCovered, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Labels, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.OrigTtl, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Expiration, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Inception, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.SignerName, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *SMIMEA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Usage, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Selector, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.MatchingType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *SOA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Ns, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Mbox, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Serial, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Refresh, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Retry, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Expire, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Minttl, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SPF) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Txt, off, err = unpackStringTxt(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SRV) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Weight, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Port, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Type, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.FingerPrint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.KeyTag, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Algorithm, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.DigestType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *TALINK) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.PreviousName, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.NextName, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Algorithm, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Inception, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Expiration, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Mode, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Error, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.KeySize, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Key, off, err = unpackStringHex(msg, off, off+int(rr.KeySize))
if err != nil {
return off, err
}
rr.OtherLen, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
if err != nil {
return off, err
}
return off, nil
}
func (rr *TLSA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Usage, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Selector, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.MatchingType, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
func (rr *TSIG) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Algorithm, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.TimeSigned, off, err = unpackUint48(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Fudge, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.MACSize, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.MAC, off, err = unpackStringHex(msg, off, off+int(rr.MACSize))
if err != nil {
return off, err
}
rr.OrigId, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Error, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.OtherLen, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
if err != nil {
return off, err
}
return off, nil
}
func (rr *TXT) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Txt, off, err = unpackStringTxt(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *UID) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Uid, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *UINFO) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Uinfo, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *URI) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Weight, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = unpackStringOctet(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *X25) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.PSDNAddress, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *ZONEMD) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Serial, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Scheme, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Hash, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}
// Code generated by "go run types_generate.go"; DO NOT EDIT.
package dns
import (
"encoding/base64"
"net"
)
// TypeToRR is a map of constructors for each RR type.
var TypeToRR = map[uint16]func() RR{
TypeA: func() RR { return new(A) },
TypeAAAA: func() RR { return new(AAAA) },
TypeAFSDB: func() RR { return new(AFSDB) },
TypeANY: func() RR { return new(ANY) },
TypeAPL: func() RR { return new(APL) },
TypeAVC: func() RR { return new(AVC) },
TypeCAA: func() RR { return new(CAA) },
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
TypeCDS: func() RR { return new(CDS) },
TypeCERT: func() RR { return new(CERT) },
TypeCNAME: func() RR { return new(CNAME) },
TypeCSYNC: func() RR { return new(CSYNC) },
TypeDHCID: func() RR { return new(DHCID) },
TypeDLV: func() RR { return new(DLV) },
TypeDNAME: func() RR { return new(DNAME) },
TypeDNSKEY: func() RR { return new(DNSKEY) },
TypeDS: func() RR { return new(DS) },
TypeEID: func() RR { return new(EID) },
TypeEUI48: func() RR { return new(EUI48) },
TypeEUI64: func() RR { return new(EUI64) },
TypeGID: func() RR { return new(GID) },
TypeGPOS: func() RR { return new(GPOS) },
TypeHINFO: func() RR { return new(HINFO) },
TypeHIP: func() RR { return new(HIP) },
TypeHTTPS: func() RR { return new(HTTPS) },
TypeKEY: func() RR { return new(KEY) },
TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) },
TypeL64: func() RR { return new(L64) },
TypeLOC: func() RR { return new(LOC) },
TypeLP: func() RR { return new(LP) },
TypeMB: func() RR { return new(MB) },
TypeMD: func() RR { return new(MD) },
TypeMF: func() RR { return new(MF) },
TypeMG: func() RR { return new(MG) },
TypeMINFO: func() RR { return new(MINFO) },
TypeMR: func() RR { return new(MR) },
TypeMX: func() RR { return new(MX) },
TypeNAPTR: func() RR { return new(NAPTR) },
TypeNID: func() RR { return new(NID) },
TypeNIMLOC: func() RR { return new(NIMLOC) },
TypeNINFO: func() RR { return new(NINFO) },
TypeNS: func() RR { return new(NS) },
TypeNSAPPTR: func() RR { return new(NSAPPTR) },
TypeNSEC: func() RR { return new(NSEC) },
TypeNSEC3: func() RR { return new(NSEC3) },
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
TypeNULL: func() RR { return new(NULL) },
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
TypeOPT: func() RR { return new(OPT) },
TypePTR: func() RR { return new(PTR) },
TypePX: func() RR { return new(PX) },
TypeRKEY: func() RR { return new(RKEY) },
TypeRP: func() RR { return new(RP) },
TypeRRSIG: func() RR { return new(RRSIG) },
TypeRT: func() RR { return new(RT) },
TypeSIG: func() RR { return new(SIG) },
TypeSMIMEA: func() RR { return new(SMIMEA) },
TypeSOA: func() RR { return new(SOA) },
TypeSPF: func() RR { return new(SPF) },
TypeSRV: func() RR { return new(SRV) },
TypeSSHFP: func() RR { return new(SSHFP) },
TypeSVCB: func() RR { return new(SVCB) },
TypeTA: func() RR { return new(TA) },
TypeTALINK: func() RR { return new(TALINK) },
TypeTKEY: func() RR { return new(TKEY) },
TypeTLSA: func() RR { return new(TLSA) },
TypeTSIG: func() RR { return new(TSIG) },
TypeTXT: func() RR { return new(TXT) },
TypeUID: func() RR { return new(UID) },
TypeUINFO: func() RR { return new(UINFO) },
TypeURI: func() RR { return new(URI) },
TypeX25: func() RR { return new(X25) },
TypeZONEMD: func() RR { return new(ZONEMD) },
}
// TypeToString is a map of strings for each RR type.
var TypeToString = map[uint16]string{
TypeA: "A",
TypeAAAA: "AAAA",
TypeAFSDB: "AFSDB",
TypeANY: "ANY",
TypeAPL: "APL",
TypeATMA: "ATMA",
TypeAVC: "AVC",
TypeAXFR: "AXFR",
TypeCAA: "CAA",
TypeCDNSKEY: "CDNSKEY",
TypeCDS: "CDS",
TypeCERT: "CERT",
TypeCNAME: "CNAME",
TypeCSYNC: "CSYNC",
TypeDHCID: "DHCID",
TypeDLV: "DLV",
TypeDNAME: "DNAME",
TypeDNSKEY: "DNSKEY",
TypeDS: "DS",
TypeEID: "EID",
TypeEUI48: "EUI48",
TypeEUI64: "EUI64",
TypeGID: "GID",
TypeGPOS: "GPOS",
TypeHINFO: "HINFO",
TypeHIP: "HIP",
TypeHTTPS: "HTTPS",
TypeISDN: "ISDN",
TypeIXFR: "IXFR",
TypeKEY: "KEY",
TypeKX: "KX",
TypeL32: "L32",
TypeL64: "L64",
TypeLOC: "LOC",
TypeLP: "LP",
TypeMAILA: "MAILA",
TypeMAILB: "MAILB",
TypeMB: "MB",
TypeMD: "MD",
TypeMF: "MF",
TypeMG: "MG",
TypeMINFO: "MINFO",
TypeMR: "MR",
TypeMX: "MX",
TypeNAPTR: "NAPTR",
TypeNID: "NID",
TypeNIMLOC: "NIMLOC",
TypeNINFO: "NINFO",
TypeNS: "NS",
TypeNSEC: "NSEC",
TypeNSEC3: "NSEC3",
TypeNSEC3PARAM: "NSEC3PARAM",
TypeNULL: "NULL",
TypeNXT: "NXT",
TypeNone: "None",
TypeOPENPGPKEY: "OPENPGPKEY",
TypeOPT: "OPT",
TypePTR: "PTR",
TypePX: "PX",
TypeRKEY: "RKEY",
TypeRP: "RP",
TypeRRSIG: "RRSIG",
TypeRT: "RT",
TypeReserved: "Reserved",
TypeSIG: "SIG",
TypeSMIMEA: "SMIMEA",
TypeSOA: "SOA",
TypeSPF: "SPF",
TypeSRV: "SRV",
TypeSSHFP: "SSHFP",
TypeSVCB: "SVCB",
TypeTA: "TA",
TypeTALINK: "TALINK",
TypeTKEY: "TKEY",
TypeTLSA: "TLSA",
TypeTSIG: "TSIG",
TypeTXT: "TXT",
TypeUID: "UID",
TypeUINFO: "UINFO",
TypeUNSPEC: "UNSPEC",
TypeURI: "URI",
TypeX25: "X25",
TypeZONEMD: "ZONEMD",
TypeNSAPPTR: "NSAP-PTR",
}
func (rr *A) Header() *RR_Header { return &rr.Hdr }
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
func (rr *APL) Header() *RR_Header { return &rr.Hdr }
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
func (rr *CSYNC) Header() *RR_Header { return &rr.Hdr }
func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
func (rr *DNSKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *DS) Header() *RR_Header { return &rr.Hdr }
func (rr *EID) Header() *RR_Header { return &rr.Hdr }
func (rr *EUI48) Header() *RR_Header { return &rr.Hdr }
func (rr *EUI64) Header() *RR_Header { return &rr.Hdr }
func (rr *GID) Header() *RR_Header { return &rr.Hdr }
func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr }
func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
func (rr *KX) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) Header() *RR_Header { return &rr.Hdr }
func (rr *L64) Header() *RR_Header { return &rr.Hdr }
func (rr *LOC) Header() *RR_Header { return &rr.Hdr }
func (rr *LP) Header() *RR_Header { return &rr.Hdr }
func (rr *MB) Header() *RR_Header { return &rr.Hdr }
func (rr *MD) Header() *RR_Header { return &rr.Hdr }
func (rr *MF) Header() *RR_Header { return &rr.Hdr }
func (rr *MG) Header() *RR_Header { return &rr.Hdr }
func (rr *MINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *MR) Header() *RR_Header { return &rr.Hdr }
func (rr *MX) Header() *RR_Header { return &rr.Hdr }
func (rr *NAPTR) Header() *RR_Header { return &rr.Hdr }
func (rr *NID) Header() *RR_Header { return &rr.Hdr }
func (rr *NIMLOC) Header() *RR_Header { return &rr.Hdr }
func (rr *NINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *NS) Header() *RR_Header { return &rr.Hdr }
func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
func (rr *NULL) Header() *RR_Header { return &rr.Hdr }
func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
func (rr *PX) Header() *RR_Header { return &rr.Hdr }
func (rr *RFC3597) Header() *RR_Header { return &rr.Hdr }
func (rr *RKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *RP) Header() *RR_Header { return &rr.Hdr }
func (rr *RRSIG) Header() *RR_Header { return &rr.Hdr }
func (rr *RT) Header() *RR_Header { return &rr.Hdr }
func (rr *SIG) Header() *RR_Header { return &rr.Hdr }
func (rr *SMIMEA) Header() *RR_Header { return &rr.Hdr }
func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
func (rr *SVCB) Header() *RR_Header { return &rr.Hdr }
func (rr *TA) Header() *RR_Header { return &rr.Hdr }
func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *TLSA) Header() *RR_Header { return &rr.Hdr }
func (rr *TSIG) Header() *RR_Header { return &rr.Hdr }
func (rr *TXT) Header() *RR_Header { return &rr.Hdr }
func (rr *UID) Header() *RR_Header { return &rr.Hdr }
func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *URI) Header() *RR_Header { return &rr.Hdr }
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
func (rr *ZONEMD) Header() *RR_Header { return &rr.Hdr }
// len() functions
func (rr *A) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
if len(rr.A) != 0 {
l += net.IPv4len
}
return l
}
func (rr *AAAA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
if len(rr.AAAA) != 0 {
l += net.IPv6len
}
return l
}
func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Subtype
l += domainNameLen(rr.Hostname, off+l, compression, false)
return l
}
func (rr *ANY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
return l
}
func (rr *APL) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.Prefixes {
l += x.len()
}
return l
}
func (rr *AVC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *CAA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Flag
l += len(rr.Tag) + 1
l += len(rr.Value)
return l
}
func (rr *CERT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Type
l += 2 // KeyTag
l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
return l
}
func (rr *CNAME) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Target, off+l, compression, true)
return l
}
func (rr *DHCID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += base64.StdEncoding.DecodedLen(len(rr.Digest))
return l
}
func (rr *DNAME) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Target, off+l, compression, false)
return l
}
func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Flags
l++ // Protocol
l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *DS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // KeyTag
l++ // Algorithm
l++ // DigestType
l += len(rr.Digest) / 2
return l
}
func (rr *EID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Endpoint) / 2
return l
}
func (rr *EUI48) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 6 // Address
return l
}
func (rr *EUI64) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 8 // Address
return l
}
func (rr *GID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 4 // Gid
return l
}
func (rr *GPOS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Longitude) + 1
l += len(rr.Latitude) + 1
l += len(rr.Altitude) + 1
return l
}
func (rr *HINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Cpu) + 1
l += len(rr.Os) + 1
return l
}
func (rr *HIP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // HitLength
l++ // PublicKeyAlgorithm
l += 2 // PublicKeyLength
l += len(rr.Hit) / 2
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
for _, x := range rr.RendezvousServers {
l += domainNameLen(x, off+l, compression, false)
}
return l
}
func (rr *KX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += domainNameLen(rr.Exchanger, off+l, compression, false)
return l
}
func (rr *L32) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
if len(rr.Locator32) != 0 {
l += net.IPv4len
}
return l
}
func (rr *L64) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += 8 // Locator64
return l
}
func (rr *LOC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Version
l++ // Size
l++ // HorizPre
l++ // VertPre
l += 4 // Latitude
l += 4 // Longitude
l += 4 // Altitude
return l
}
func (rr *LP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += domainNameLen(rr.Fqdn, off+l, compression, false)
return l
}
func (rr *MB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Mb, off+l, compression, true)
return l
}
func (rr *MD) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Md, off+l, compression, true)
return l
}
func (rr *MF) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Mf, off+l, compression, true)
return l
}
func (rr *MG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Mg, off+l, compression, true)
return l
}
func (rr *MINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Rmail, off+l, compression, true)
l += domainNameLen(rr.Email, off+l, compression, true)
return l
}
func (rr *MR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Mr, off+l, compression, true)
return l
}
func (rr *MX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += domainNameLen(rr.Mx, off+l, compression, true)
return l
}
func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Order
l += 2 // Preference
l += len(rr.Flags) + 1
l += len(rr.Service) + 1
l += len(rr.Regexp) + 1
l += domainNameLen(rr.Replacement, off+l, compression, false)
return l
}
func (rr *NID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += 8 // NodeID
return l
}
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Locator) / 2
return l
}
func (rr *NINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.ZSData {
l += len(x) + 1
}
return l
}
func (rr *NS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Ns, off+l, compression, true)
return l
}
func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Ptr, off+l, compression, false)
return l
}
func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Hash
l++ // Flags
l += 2 // Iterations
l++ // SaltLength
l += len(rr.Salt) / 2
return l
}
func (rr *NULL) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Data)
return l
}
func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *PTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Ptr, off+l, compression, true)
return l
}
func (rr *PX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += domainNameLen(rr.Map822, off+l, compression, false)
l += domainNameLen(rr.Mapx400, off+l, compression, false)
return l
}
func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Rdata) / 2
return l
}
func (rr *RKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Flags
l++ // Protocol
l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *RP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Mbox, off+l, compression, false)
l += domainNameLen(rr.Txt, off+l, compression, false)
return l
}
func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // TypeCovered
l++ // Algorithm
l++ // Labels
l += 4 // OrigTtl
l += 4 // Expiration
l += 4 // Inception
l += 2 // KeyTag
l += domainNameLen(rr.SignerName, off+l, compression, false)
l += base64.StdEncoding.DecodedLen(len(rr.Signature))
return l
}
func (rr *RT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Preference
l += domainNameLen(rr.Host, off+l, compression, false)
return l
}
func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Usage
l++ // Selector
l++ // MatchingType
l += len(rr.Certificate) / 2
return l
}
func (rr *SOA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Ns, off+l, compression, true)
l += domainNameLen(rr.Mbox, off+l, compression, true)
l += 4 // Serial
l += 4 // Refresh
l += 4 // Retry
l += 4 // Expire
l += 4 // Minttl
return l
}
func (rr *SPF) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *SRV) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += 2 // Weight
l += 2 // Port
l += domainNameLen(rr.Target, off+l, compression, false)
return l
}
func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Algorithm
l++ // Type
l += len(rr.FingerPrint) / 2
return l
}
func (rr *SVCB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += domainNameLen(rr.Target, off+l, compression, false)
for _, x := range rr.Value {
l += 4 + int(x.len())
}
return l
}
func (rr *TA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // KeyTag
l++ // Algorithm
l++ // DigestType
l += len(rr.Digest) / 2
return l
}
func (rr *TALINK) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.PreviousName, off+l, compression, false)
l += domainNameLen(rr.NextName, off+l, compression, false)
return l
}
func (rr *TKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Algorithm, off+l, compression, false)
l += 4 // Inception
l += 4 // Expiration
l += 2 // Mode
l += 2 // Error
l += 2 // KeySize
l += len(rr.Key) / 2
l += 2 // OtherLen
l += len(rr.OtherData) / 2
return l
}
func (rr *TLSA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l++ // Usage
l++ // Selector
l++ // MatchingType
l += len(rr.Certificate) / 2
return l
}
func (rr *TSIG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.Algorithm, off+l, compression, false)
l += 6 // TimeSigned
l += 2 // Fudge
l += 2 // MACSize
l += len(rr.MAC) / 2
l += 2 // OrigId
l += 2 // Error
l += 2 // OtherLen
l += len(rr.OtherData) / 2
return l
}
func (rr *TXT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *UID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 4 // Uid
return l
}
func (rr *UINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Uinfo) + 1
return l
}
func (rr *URI) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += 2 // Weight
l += len(rr.Target)
return l
}
func (rr *X25) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.PSDNAddress) + 1
return l
}
func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 4 // Serial
l++ // Scheme
l++ // Hash
l += len(rr.Digest) / 2
return l
}
// copy() functions
func (rr *A) copy() RR {
return &A{rr.Hdr, copyIP(rr.A)}
}
func (rr *AAAA) copy() RR {
return &AAAA{rr.Hdr, copyIP(rr.AAAA)}
}
func (rr *AFSDB) copy() RR {
return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname}
}
func (rr *ANY) copy() RR {
return &ANY{rr.Hdr}
}
func (rr *APL) copy() RR {
Prefixes := make([]APLPrefix, len(rr.Prefixes))
for i, e := range rr.Prefixes {
Prefixes[i] = e.copy()
}
return &APL{rr.Hdr, Prefixes}
}
func (rr *AVC) copy() RR {
Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt)
return &AVC{rr.Hdr, Txt}
}
func (rr *CAA) copy() RR {
return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
}
func (rr *CDNSKEY) copy() RR {
return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *CDS) copy() RR {
return &CDS{*rr.DS.copy().(*DS)}
}
func (rr *CERT) copy() RR {
return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
}
func (rr *CNAME) copy() RR {
return &CNAME{rr.Hdr, rr.Target}
}
func (rr *CSYNC) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap)
return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap}
}
func (rr *DHCID) copy() RR {
return &DHCID{rr.Hdr, rr.Digest}
}
func (rr *DLV) copy() RR {
return &DLV{*rr.DS.copy().(*DS)}
}
func (rr *DNAME) copy() RR {
return &DNAME{rr.Hdr, rr.Target}
}
func (rr *DNSKEY) copy() RR {
return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
}
func (rr *DS) copy() RR {
return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
}
func (rr *EID) copy() RR {
return &EID{rr.Hdr, rr.Endpoint}
}
func (rr *EUI48) copy() RR {
return &EUI48{rr.Hdr, rr.Address}
}
func (rr *EUI64) copy() RR {
return &EUI64{rr.Hdr, rr.Address}
}
func (rr *GID) copy() RR {
return &GID{rr.Hdr, rr.Gid}
}
func (rr *GPOS) copy() RR {
return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude}
}
func (rr *HINFO) copy() RR {
return &HINFO{rr.Hdr, rr.Cpu, rr.Os}
}
func (rr *HIP) copy() RR {
RendezvousServers := make([]string, len(rr.RendezvousServers))
copy(RendezvousServers, rr.RendezvousServers)
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
}
func (rr *HTTPS) copy() RR {
return &HTTPS{*rr.SVCB.copy().(*SVCB)}
}
func (rr *KEY) copy() RR {
return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *KX) copy() RR {
return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
}
func (rr *L32) copy() RR {
return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)}
}
func (rr *L64) copy() RR {
return &L64{rr.Hdr, rr.Preference, rr.Locator64}
}
func (rr *LOC) copy() RR {
return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
}
func (rr *LP) copy() RR {
return &LP{rr.Hdr, rr.Preference, rr.Fqdn}
}
func (rr *MB) copy() RR {
return &MB{rr.Hdr, rr.Mb}
}
func (rr *MD) copy() RR {
return &MD{rr.Hdr, rr.Md}
}
func (rr *MF) copy() RR {
return &MF{rr.Hdr, rr.Mf}
}
func (rr *MG) copy() RR {
return &MG{rr.Hdr, rr.Mg}
}
func (rr *MINFO) copy() RR {
return &MINFO{rr.Hdr, rr.Rmail, rr.Email}
}
func (rr *MR) copy() RR {
return &MR{rr.Hdr, rr.Mr}
}
func (rr *MX) copy() RR {
return &MX{rr.Hdr, rr.Preference, rr.Mx}
}
func (rr *NAPTR) copy() RR {
return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
}
func (rr *NID) copy() RR {
return &NID{rr.Hdr, rr.Preference, rr.NodeID}
}
func (rr *NIMLOC) copy() RR {
return &NIMLOC{rr.Hdr, rr.Locator}
}
func (rr *NINFO) copy() RR {
ZSData := make([]string, len(rr.ZSData))
copy(ZSData, rr.ZSData)
return &NINFO{rr.Hdr, ZSData}
}
func (rr *NS) copy() RR {
return &NS{rr.Hdr, rr.Ns}
}
func (rr *NSAPPTR) copy() RR {
return &NSAPPTR{rr.Hdr, rr.Ptr}
}
func (rr *NSEC) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap)
return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap}
}
func (rr *NSEC3) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap)
return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
}
func (rr *NSEC3PARAM) copy() RR {
return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
}
func (rr *NULL) copy() RR {
return &NULL{rr.Hdr, rr.Data}
}
func (rr *OPENPGPKEY) copy() RR {
return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
}
func (rr *OPT) copy() RR {
Option := make([]EDNS0, len(rr.Option))
for i, e := range rr.Option {
Option[i] = e.copy()
}
return &OPT{rr.Hdr, Option}
}
func (rr *PTR) copy() RR {
return &PTR{rr.Hdr, rr.Ptr}
}
func (rr *PX) copy() RR {
return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400}
}
func (rr *RFC3597) copy() RR {
return &RFC3597{rr.Hdr, rr.Rdata}
}
func (rr *RKEY) copy() RR {
return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
}
func (rr *RP) copy() RR {
return &RP{rr.Hdr, rr.Mbox, rr.Txt}
}
func (rr *RRSIG) copy() RR {
return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
}
func (rr *RT) copy() RR {
return &RT{rr.Hdr, rr.Preference, rr.Host}
}
func (rr *SIG) copy() RR {
return &SIG{*rr.RRSIG.copy().(*RRSIG)}
}
func (rr *SMIMEA) copy() RR {
return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
}
func (rr *SOA) copy() RR {
return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
}
func (rr *SPF) copy() RR {
Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt)
return &SPF{rr.Hdr, Txt}
}
func (rr *SRV) copy() RR {
return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target}
}
func (rr *SSHFP) copy() RR {
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
}
func (rr *SVCB) copy() RR {
Value := make([]SVCBKeyValue, len(rr.Value))
for i, e := range rr.Value {
Value[i] = e.copy()
}
return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
}
func (rr *TA) copy() RR {
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
}
func (rr *TALINK) copy() RR {
return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName}
}
func (rr *TKEY) copy() RR {
return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
}
func (rr *TLSA) copy() RR {
return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
}
func (rr *TSIG) copy() RR {
return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
}
func (rr *TXT) copy() RR {
Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt)
return &TXT{rr.Hdr, Txt}
}
func (rr *UID) copy() RR {
return &UID{rr.Hdr, rr.Uid}
}
func (rr *UINFO) copy() RR {
return &UINFO{rr.Hdr, rr.Uinfo}
}
func (rr *URI) copy() RR {
return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target}
}
func (rr *X25) copy() RR {
return &X25{rr.Hdr, rr.PSDNAddress}
}
func (rr *ZONEMD) copy() RR {
return &ZONEMD{rr.Hdr, rr.Serial, rr.Scheme, rr.Hash, rr.Digest}
}
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 The OpenZipkin Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"errors"
"time"
)
// ErrValidTimestampRequired error
var ErrValidTimestampRequired = errors.New("valid annotation timestamp required")
// Annotation associates an event that explains latency with a timestamp.
type Annotation struct {
Timestamp time.Time
Value string
}
// MarshalJSON implements custom JSON encoding
func (a *Annotation) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Timestamp int64 `json:"timestamp"`
Value string `json:"value"`
}{
Timestamp: a.Timestamp.Round(time.Microsecond).UnixNano() / 1e3,
Value: a.Value,
})
}
// UnmarshalJSON implements custom JSON decoding
func (a *Annotation) UnmarshalJSON(b []byte) error {
type Alias Annotation
annotation := &struct {
TimeStamp uint64 `json:"timestamp"`
*Alias
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(b, &annotation); err != nil {
return err
}
if annotation.TimeStamp < 1 {
return ErrValidTimestampRequired
}
a.Timestamp = time.Unix(0, int64(annotation.TimeStamp)*1e3)
return nil
}
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package model contains the Zipkin V2 model which is used by the Zipkin Go
tracer implementation.
Third party instrumentation libraries can use the model and transport packages
found in this Zipkin Go library to directly interface with the Zipkin Server or
Zipkin Collectors without the need to use the tracer implementation itself.
*/
package model
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"net"
"strings"
)
// Endpoint holds the network context of a node in the service graph.
type Endpoint struct {
ServiceName string
IPv4 net.IP
IPv6 net.IP
Port uint16
}
// MarshalJSON exports our Endpoint into the correct format for the Zipkin V2 API.
func (e Endpoint) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
ServiceName string `json:"serviceName,omitempty"`
IPv4 net.IP `json:"ipv4,omitempty"`
IPv6 net.IP `json:"ipv6,omitempty"`
Port uint16 `json:"port,omitempty"`
}{
strings.ToLower(e.ServiceName),
e.IPv4,
e.IPv6,
e.Port,
})
}
// Empty returns if all Endpoint properties are empty / unspecified.
func (e *Endpoint) Empty() bool {
return e == nil ||
(e.ServiceName == "" && e.Port == 0 && len(e.IPv4) == 0 && len(e.IPv6) == 0)
}
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
// Kind clarifies context of timestamp, duration and remoteEndpoint in a span.
type Kind string
// Available Kind values
const (
Undetermined Kind = ""
Client Kind = "CLIENT"
Server Kind = "SERVER"
Producer Kind = "PRODUCER"
Consumer Kind = "CONSUMER"
)
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"errors"
"strings"
"time"
)
// unmarshal errors
var (
ErrValidTraceIDRequired = errors.New("valid traceId required")
ErrValidIDRequired = errors.New("valid span id required")
ErrValidDurationRequired = errors.New("valid duration required")
)
// BaggageFields holds the interface for consumers needing to interact with
// the fields in application logic.
type BaggageFields interface {
// Get returns the values for a field identified by its key.
Get(key string) []string
// Add adds the provided values to a header designated by key. If not
// accepted by the baggage implementation, it will return false.
Add(key string, value ...string) bool
// Set sets the provided values to a header designated by key. If not
// accepted by the baggage implementation, it will return false.
Set(key string, value ...string) bool
// Delete removes the field data designated by key. If not accepted by the
// baggage implementation, it will return false.
Delete(key string) bool
// Iterate will iterate over the available fields and for each one it will
// trigger the callback function.
Iterate(f func(key string, values []string))
}
// SpanContext holds the context of a Span.
type SpanContext struct {
TraceID TraceID `json:"traceId"`
ID ID `json:"id"`
ParentID *ID `json:"parentId,omitempty"`
Debug bool `json:"debug,omitempty"`
Sampled *bool `json:"-"`
Err error `json:"-"`
Baggage BaggageFields `json:"-"`
}
// SpanModel structure.
//
// If using this library to instrument your application you will not need to
// directly access or modify this representation. The SpanModel is exported for
// use cases involving 3rd party Go instrumentation libraries desiring to
// export data to a Zipkin server using the Zipkin V2 Span model.
type SpanModel struct {
SpanContext
Name string `json:"name,omitempty"`
Kind Kind `json:"kind,omitempty"`
Timestamp time.Time `json:"-"`
Duration time.Duration `json:"-"`
Shared bool `json:"shared,omitempty"`
LocalEndpoint *Endpoint `json:"localEndpoint,omitempty"`
RemoteEndpoint *Endpoint `json:"remoteEndpoint,omitempty"`
Annotations []Annotation `json:"annotations,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
}
// MarshalJSON exports our Model into the correct format for the Zipkin V2 API.
func (s SpanModel) MarshalJSON() ([]byte, error) {
type Alias SpanModel
var timestamp int64
if !s.Timestamp.IsZero() {
if s.Timestamp.Unix() < 1 {
// Zipkin does not allow Timestamps before Unix epoch
return nil, ErrValidTimestampRequired
}
timestamp = s.Timestamp.Round(time.Microsecond).UnixNano() / 1e3
}
if s.Duration < time.Microsecond {
if s.Duration < 0 {
// negative duration is not allowed and signals a timing logic error
return nil, ErrValidDurationRequired
} else if s.Duration > 0 {
// sub microsecond durations are reported as 1 microsecond
s.Duration = 1 * time.Microsecond
}
} else {
// Duration will be rounded to nearest microsecond representation.
//
// NOTE: Duration.Round() is not available in Go 1.8 which we still support.
// To handle microsecond resolution rounding we'll add 500 nanoseconds to
// the duration. When truncated to microseconds in the call to marshal, it
// will be naturally rounded. See TestSpanDurationRounding in span_test.go
s.Duration += 500 * time.Nanosecond
}
s.Name = strings.ToLower(s.Name)
if s.LocalEndpoint.Empty() {
s.LocalEndpoint = nil
}
if s.RemoteEndpoint.Empty() {
s.RemoteEndpoint = nil
}
return json.Marshal(&struct {
T int64 `json:"timestamp,omitempty"`
D int64 `json:"duration,omitempty"`
Alias
}{
T: timestamp,
D: s.Duration.Nanoseconds() / 1e3,
Alias: (Alias)(s),
})
}
// UnmarshalJSON imports our Model from a Zipkin V2 API compatible span
// representation.
func (s *SpanModel) UnmarshalJSON(b []byte) error {
type Alias SpanModel
span := &struct {
T uint64 `json:"timestamp,omitempty"`
D uint64 `json:"duration,omitempty"`
*Alias
}{
Alias: (*Alias)(s),
}
if err := json.Unmarshal(b, &span); err != nil {
return err
}
if s.ID < 1 {
return ErrValidIDRequired
}
if span.T > 0 {
s.Timestamp = time.Unix(0, int64(span.T)*1e3)
}
s.Duration = time.Duration(span.D*1e3) * time.Nanosecond
if s.LocalEndpoint.Empty() {
s.LocalEndpoint = nil
}
if s.RemoteEndpoint.Empty() {
s.RemoteEndpoint = nil
}
return nil
}
// Copyright 2022 The OpenZipkin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"fmt"
"strconv"
)
// ID type
type ID uint64
// String outputs the 64-bit ID as hex string.
func (i ID) String() string {
return fmt.Sprintf("%016x", uint64(i))
}
// MarshalJSON serializes an ID type (SpanID, ParentSpanID) to HEX.
func (i ID) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%q", i.String())), nil
}
// UnmarshalJSON deserializes an ID type (SpanID, ParentSpanID) from HEX.
func (i *ID) UnmarshalJSON(b []byte) (err error) {
var id uint64
if len(b) < 3 {
return nil
}
id, err = strconv.ParseUint(string(b[1:len(b)-1]), 16, 64)
*i = ID(id)
return err
}