Update github.com/miekg/dns to pull in bug fixes.

Most notable a race condition.
This commit is contained in:
beorn7 2016-10-28 14:42:36 +02:00
parent 98e6e4fbee
commit 590446434f
37 changed files with 6989 additions and 2286 deletions

View file

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns) [![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns) [![](https://godoc.org/github.com/miekg/dns?status.svg)](https://godoc.org/github.com/miekg/dns)
# Alternative (more granular) approach to a DNS library # Alternative (more granular) approach to a DNS library
@ -10,9 +10,9 @@ If there is stuff you should know as a DNS programmer there isn't a convenience
function for it. Server side and client side programming is supported, i.e. you function for it. Server side and client side programming is supported, i.e. you
can build servers and resolvers with it. can build servers and resolvers with it.
If you like this, you may also be interested in: We try to keep the "master" branch as sane as possible and at the bleeding edge
of standards, avoiding breaking changes wherever reasonable. We support the last
* https://github.com/miekg/unbound -- Go wrapper for the Unbound resolver. two versions of Go, currently: 1.5 and 1.6.
# Goals # Goals
@ -33,6 +33,7 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/fcambus/rrda * https://github.com/fcambus/rrda
* https://github.com/kenshinx/godns * https://github.com/kenshinx/godns
* https://github.com/skynetservices/skydns * https://github.com/skynetservices/skydns
* https://github.com/hashicorp/consul
* https://github.com/DevelopersPL/godnsagent * https://github.com/DevelopersPL/godnsagent
* https://github.com/duedil-ltd/discodns * https://github.com/duedil-ltd/discodns
* https://github.com/StalkR/dns-reverse-proxy * https://github.com/StalkR/dns-reverse-proxy
@ -42,6 +43,16 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://play.google.com/store/apps/details?id=com.turbobytes.dig * https://play.google.com/store/apps/details?id=com.turbobytes.dig
* https://github.com/fcambus/statzone * https://github.com/fcambus/statzone
* https://github.com/benschw/dns-clb-go * https://github.com/benschw/dns-clb-go
* https://github.com/corny/dnscheck for http://public-dns.info/
* https://namesmith.io
* https://github.com/miekg/unbound
* https://github.com/miekg/exdns
* https://dnslookup.org
* https://github.com/looterz/grimd
* https://github.com/phamhongviet/serf-dns
* https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
@ -55,9 +66,10 @@ Send pull request if you want to be listed here.
* Server side programming (mimicking the net/http package); * Server side programming (mimicking the net/http package);
* Client side programming; * Client side programming;
* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA; * DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
* EDNS0, NSID; * EDNS0, NSID, Cookies;
* AXFR/IXFR; * AXFR/IXFR;
* TSIG, SIG(0); * TSIG, SIG(0);
* DNS over TLS: optional encrypted connection between client and server;
* DNS name compression; * DNS name compression;
* Depends only on the standard library. * Depends only on the standard library.
@ -104,7 +116,6 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 340{1,2,3} - NAPTR record * 340{1,2,3} - NAPTR record
* 3445 - Limiting the scope of (DNS)KEY * 3445 - Limiting the scope of (DNS)KEY
* 3597 - Unknown RRs * 3597 - Unknown RRs
* 4025 - IPSECKEY
* 403{3,4,5} - DNSSEC + validation functions * 403{3,4,5} - DNSSEC + validation functions
* 4255 - SSHFP record * 4255 - SSHFP record
* 4343 - Case insensitivity * 4343 - Case insensitivity
@ -123,6 +134,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6605 - ECDSA * 6605 - ECDSA
* 6725 - IANA Registry Update * 6725 - IANA Registry Update
* 6742 - ILNP DNS * 6742 - ILNP DNS
* 6840 - Clarifications and Implementation Notes for DNS Security
* 6844 - CAA record * 6844 - CAA record
* 6891 - EDNS0 update * 6891 - EDNS0 update
* 6895 - DNS IANA considerations * 6895 - DNS IANA considerations
@ -130,6 +142,8 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 7043 - EUI48/EUI64 records * 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option * 7314 - DNS (EDNS) EXPIRE Option
* 7553 - URI record * 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations (draft)
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
* xxxx - EDNS0 DNS Update Lease (draft) * xxxx - EDNS0 DNS Update Lease (draft)
## Loosely based upon ## Loosely based upon
@ -138,11 +152,3 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* `NSD` * `NSD`
* `Net::DNS` * `Net::DNS`
* `GRONG` * `GRONG`
## TODO
* privatekey.Precompute() when signing?
* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
* NSEC(3) cover/match/closest enclose.
* Replies with TC bit are not parsed to the end.

161
vendor/github.com/miekg/dns/client.go generated vendored
View file

@ -4,6 +4,8 @@ package dns
import ( import (
"bytes" "bytes"
"crypto/tls"
"encoding/binary"
"io" "io"
"net" "net"
"time" "time"
@ -24,27 +26,22 @@ type Conn struct {
// A Client defines parameters for a DNS client. // A Client defines parameters for a DNS client.
type Client struct { type Client struct {
Net string // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
UDPSize uint16 // minimum receive buffer for UDP messages UDPSize uint16 // minimum receive buffer for UDP messages
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds TLSConfig *tls.Config // TLS connection configuration
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds Timeout time.Duration // a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout and WriteTimeout when non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
group singleflight group singleflight
} }
// Exchange performs a synchronous UDP query. It sends the message m to the address // Exchange performs a synchronous UDP query. It sends the message m to the address
// contained in a and waits for an reply. Exchange does not retry a failed query, nor // contained in a and waits for a reply. Exchange does not retry a failed query, nor
// will it fall back to TCP in case of truncation. // will it fall back to TCP in case of truncation.
// If you need to send a DNS message on an already existing connection, you can use the // See client.Exchange for more information on setting larger buffer sizes.
// following:
//
// co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m)
// in, err := co.ReadMsg()
// co.Close()
//
func Exchange(m *Msg, a string) (r *Msg, err error) { func Exchange(m *Msg, a string) (r *Msg, err error) {
var co *Conn var co *Conn
co, err = DialTimeout("udp", a, dnsTimeout) co, err = DialTimeout("udp", a, dnsTimeout)
@ -53,8 +50,6 @@ func Exchange(m *Msg, a string) (r *Msg, err error) {
} }
defer co.Close() defer co.Close()
co.SetReadDeadline(time.Now().Add(dnsTimeout))
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
opt := m.IsEdns0() opt := m.IsEdns0()
// If EDNS0 is used use that for size. // If EDNS0 is used use that for size.
@ -62,9 +57,12 @@ func Exchange(m *Msg, a string) (r *Msg, err error) {
co.UDPSize = opt.UDPSize() co.UDPSize = opt.UDPSize()
} }
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
if err = co.WriteMsg(m); err != nil { if err = co.WriteMsg(m); err != nil {
return nil, err return nil, err
} }
co.SetReadDeadline(time.Now().Add(dnsTimeout))
r, err = co.ReadMsg() r, err = co.ReadMsg()
if err == nil && r.Id != m.Id { if err == nil && r.Id != m.Id {
err = ErrId err = ErrId
@ -95,14 +93,18 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
return r, err return r, err
} }
// Exchange performs an synchronous query. It sends the message m to the address // Exchange performs a synchronous query. It sends the message m to the address
// contained in a and waits for an reply. Basic use pattern with a *dns.Client: // contained in a and waits for a reply. Basic use pattern with a *dns.Client:
// //
// c := new(dns.Client) // c := new(dns.Client)
// in, rtt, err := c.Exchange(message, "127.0.0.1:53") // in, rtt, err := c.Exchange(message, "127.0.0.1:53")
// //
// Exchange does not retry a failed query, nor will it fall back to TCP in // Exchange does not retry a failed query, nor will it fall back to TCP in
// case of truncation. // case of truncation.
// It is up to the caller to create a message that allows for larger responses to be
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
// buffer, see SetEdns0. Messsages without an OPT RR will fallback to the historic limit
// of 512 bytes.
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) { func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight { if !c.SingleInflight {
return c.exchange(m, a) return c.exchange(m, a)
@ -129,6 +131,9 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
} }
func (c *Client) dialTimeout() time.Duration { func (c *Client) dialTimeout() time.Duration {
if c.Timeout != 0 {
return c.Timeout
}
if c.DialTimeout != 0 { if c.DialTimeout != 0 {
return c.DialTimeout return c.DialTimeout
} }
@ -151,11 +156,36 @@ func (c *Client) writeTimeout() time.Duration {
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) { func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
var co *Conn var co *Conn
if c.Net == "" { network := "udp"
co, err = DialTimeout("udp", a, c.dialTimeout()) tls := false
} else {
co, err = DialTimeout(c.Net, a, c.dialTimeout()) switch c.Net {
case "tcp-tls":
network = "tcp"
tls = true
case "tcp4-tls":
network = "tcp4"
tls = true
case "tcp6-tls":
network = "tcp6"
tls = true
default:
if c.Net != "" {
network = c.Net
} }
}
var deadline time.Time
if c.Timeout != 0 {
deadline = time.Now().Add(c.Timeout)
}
if tls {
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, c.dialTimeout())
} else {
co, err = DialTimeout(network, a, c.dialTimeout())
}
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
@ -171,13 +201,13 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
co.UDPSize = c.UDPSize co.UDPSize = c.UDPSize
} }
co.SetReadDeadline(time.Now().Add(c.readTimeout()))
co.SetWriteDeadline(time.Now().Add(c.writeTimeout()))
co.TsigSecret = c.TsigSecret co.TsigSecret = c.TsigSecret
co.SetWriteDeadline(deadlineOrTimeout(deadline, c.writeTimeout()))
if err = co.WriteMsg(m); err != nil { if err = co.WriteMsg(m); err != nil {
return nil, 0, err return nil, 0, err
} }
co.SetReadDeadline(deadlineOrTimeout(deadline, c.readTimeout()))
r, err = co.ReadMsg() r, err = co.ReadMsg()
if err == nil && r.Id != m.Id { if err == nil && r.Id != m.Id {
err = ErrId err = ErrId
@ -196,6 +226,12 @@ func (co *Conn) ReadMsg() (*Msg, error) {
m := new(Msg) m := new(Msg)
if err := m.Unpack(p); err != nil { if err := m.Unpack(p); err != nil {
// If ErrTruncated was returned, we still want to allow the user to use
// the message, but naively they can just check err if they don't want
// to use a truncated message
if err == ErrTruncated {
return m, err
}
return nil, err return nil, err
} }
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
@ -218,21 +254,26 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
err error err error
) )
if t, ok := co.Conn.(*net.TCPConn); ok { switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
// First two bytes specify the length of the entire message. // First two bytes specify the length of the entire message.
l, err := tcpMsgLen(t) l, err := tcpMsgLen(r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p = make([]byte, l) p = make([]byte, l)
n, err = tcpRead(t, p) n, err = tcpRead(r, p)
} else { co.rtt = time.Since(co.t)
default:
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
} else { } else {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
co.rtt = time.Since(co.t)
} }
if err != nil { if err != nil {
@ -243,15 +284,17 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
p = p[:n] p = p[:n]
if hdr != nil { if hdr != nil {
if _, err = UnpackStruct(hdr, p, 0); err != nil { dh, _, err := unpackMsgHdr(p, 0)
if err != nil {
return nil, err return nil, err
} }
*hdr = dh
} }
return p, err return p, err
} }
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length. // tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
func tcpMsgLen(t *net.TCPConn) (int, error) { func tcpMsgLen(t io.Reader) (int, error) {
p := []byte{0, 0} p := []byte{0, 0}
n, err := t.Read(p) n, err := t.Read(p)
if err != nil { if err != nil {
@ -260,7 +303,7 @@ func tcpMsgLen(t *net.TCPConn) (int, error) {
if n != 2 { if n != 2 {
return 0, ErrShortRead return 0, ErrShortRead
} }
l, _ := unpackUint16(p, 0) l := binary.BigEndian.Uint16(p)
if l == 0 { if l == 0 {
return 0, ErrShortRead return 0, ErrShortRead
} }
@ -268,7 +311,7 @@ func tcpMsgLen(t *net.TCPConn) (int, error) {
} }
// tcpRead calls TCPConn.Read enough times to fill allocated buffer. // tcpRead calls TCPConn.Read enough times to fill allocated buffer.
func tcpRead(t *net.TCPConn, p []byte) (int, error) { func tcpRead(t io.Reader, p []byte) (int, error) {
n, err := t.Read(p) n, err := t.Read(p)
if err != nil { if err != nil {
return n, err return n, err
@ -291,27 +334,28 @@ func (co *Conn) Read(p []byte) (n int, err error) {
if len(p) < 2 { if len(p) < 2 {
return 0, io.ErrShortBuffer return 0, io.ErrShortBuffer
} }
if t, ok := co.Conn.(*net.TCPConn); ok { switch t := co.Conn.(type) {
l, err := tcpMsgLen(t) case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
l, err := tcpMsgLen(r)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if l > len(p) { if l > len(p) {
return int(l), io.ErrShortBuffer return int(l), io.ErrShortBuffer
} }
return tcpRead(t, p[:l]) return tcpRead(r, p[:l])
} }
// UDP connection // UDP connection
n, err = co.Conn.Read(p) n, err = co.Conn.Read(p)
if err != nil { if err != nil {
return n, err return n, err
} }
co.rtt = time.Since(co.t)
return n, err return n, err
} }
// WriteMsg sends a message throught the connection co. // WriteMsg sends a message through the connection co.
// If the message m contains a TSIG record the transaction // If the message m contains a TSIG record the transaction
// signature is calculated. // signature is calculated.
func (co *Conn) WriteMsg(m *Msg) (err error) { func (co *Conn) WriteMsg(m *Msg) (err error) {
@ -322,7 +366,7 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
return ErrSecret return ErrSecret
} }
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false) out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
// Set for the next read, allthough only used in zone transfers // Set for the next read, although only used in zone transfers
co.tsigRequestMAC = mac co.tsigRequestMAC = mac
} else { } else {
out, err = m.Pack() out, err = m.Pack()
@ -339,7 +383,10 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
// Write implements the net.Conn Write method. // Write implements the net.Conn Write method.
func (co *Conn) Write(p []byte) (n int, err error) { func (co *Conn) Write(p []byte) (n int, err error) {
if t, ok := co.Conn.(*net.TCPConn); ok { switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn:
w := t.(io.Writer)
lp := len(p) lp := len(p)
if lp < 2 { if lp < 2 {
return 0, io.ErrShortBuffer return 0, io.ErrShortBuffer
@ -348,9 +395,9 @@ func (co *Conn) Write(p []byte) (n int, err error) {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, lp+2) l := make([]byte, 2, lp+2)
l[0], l[1] = packUint16(uint16(lp)) binary.BigEndian.PutUint16(l, uint16(lp))
p = append(l, p...) p = append(l, p...)
n, err := io.Copy(t, bytes.NewReader(p)) n, err := io.Copy(w, bytes.NewReader(p))
return int(n), err return int(n), err
} }
n, err = co.Conn.(*net.UDPConn).Write(p) n, err = co.Conn.(*net.UDPConn).Write(p)
@ -376,3 +423,33 @@ func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, er
} }
return conn, nil return conn, nil
} }
// DialWithTLS connects to the address on the named network with TLS.
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
conn = new(Conn)
conn.Conn, err = tls.Dial(network, address, tlsConfig)
if err != nil {
return nil, err
}
return conn, nil
}
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
var dialer net.Dialer
dialer.Timeout = timeout
conn = new(Conn)
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
if err != nil {
return nil, err
}
return conn, nil
}
func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
if deadline.IsZero() {
return time.Now().Add(timeout)
}
return deadline
}

44
vendor/github.com/miekg/dns/dane.go generated vendored Normal file
View file

@ -0,0 +1,44 @@
package dns
import (
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/hex"
"errors"
"io"
)
// CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records.
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
switch matchingType {
case 0:
switch selector {
case 0:
return hex.EncodeToString(cert.Raw), nil
case 1:
return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
}
case 1:
h := sha256.New()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
return hex.EncodeToString(h.Sum(nil)), nil
}
case 2:
h := sha512.New()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
return hex.EncodeToString(h.Sum(nil)), nil
}
}
return "", errors.New("dns: bad MatchingType or Selector")
}

View file

@ -142,26 +142,33 @@ func (dns *Msg) IsTsig() *TSIG {
// record in the additional section will do. It returns the OPT record // record in the additional section will do. It returns the OPT record
// found or nil. // found or nil.
func (dns *Msg) IsEdns0() *OPT { func (dns *Msg) IsEdns0() *OPT {
for _, r := range dns.Extra { // EDNS0 is at the end of the additional section, start there.
if r.Header().Rrtype == TypeOPT { // We might want to change this to *only* look at the last two
return r.(*OPT) // records. So we see TSIG and/or OPT - this a slightly bigger
// change though.
for i := len(dns.Extra) - 1; i >= 0; i-- {
if dns.Extra[i].Header().Rrtype == TypeOPT {
return dns.Extra[i].(*OPT)
} }
} }
return nil return nil
} }
// IsDomainName checks if s is a valid domainname, it returns // IsDomainName checks if s is a valid domain name, it returns the number of
// the number of labels and true, when a domain name is valid. // labels and true, when a domain name is valid. Note that non fully qualified
// Note that non fully qualified domain name is considered valid, in this case the // domain name is considered valid, in this case the last label is counted in
// last label is counted in the number of labels. // the number of labels. When false is returned the number of labels is not
// When false is returned the number of labels is not defined. // defined. Also note that this function is extremely liberal; almost any
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
// label fits in 63 characters, but there is no length check for the entire
// string s. I.e. a domain name longer than 255 characters is considered valid.
func IsDomainName(s string) (labels int, ok bool) { func IsDomainName(s string) (labels int, ok bool) {
_, labels, err := packDomainName(s, nil, 0, nil, false) _, labels, err := packDomainName(s, nil, 0, nil, false)
return labels, err == nil return labels, err == nil
} }
// IsSubDomain checks if child is indeed a child of the parent. Both child and // IsSubDomain checks if child is indeed a child of the parent. If child and parent
// parent are *not* downcased before doing the comparison. // are the same domain true is returned as well.
func IsSubDomain(parent, child string) bool { func IsSubDomain(parent, child string) bool {
// Entire child is contained in parent // Entire child is contained in parent
return CompareDomainName(parent, child) == CountLabel(parent) return CompareDomainName(parent, child) == CountLabel(parent)

34
vendor/github.com/miekg/dns/dns.go generated vendored
View file

@ -4,16 +4,14 @@ import "strconv"
const ( const (
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
// DefaultMsgSize is the standard default for messages larger than 512 bytes.
DefaultMsgSize = 4096
// MinMsgSize is the minimal size of a DNS packet.
MinMsgSize = 512
// MaxMsgSize is the largest possible DNS packet.
MaxMsgSize = 65535
defaultTtl = 3600 // Default internal TTL. defaultTtl = 3600 // Default internal TTL.
DefaultMsgSize = 4096 // DefaultMsgSize is the standard default for messages larger than 512 bytes.
MinMsgSize = 512 // MinMsgSize is the minimal size of a DNS packet.
MaxMsgSize = 65535 // MaxMsgSize is the largest possible DNS packet.
) )
// Error represents a DNS error // Error represents a DNS error.
type Error struct{ err string } type Error struct{ err string }
func (e *Error) Error() string { func (e *Error) Error() string {
@ -30,10 +28,13 @@ type RR interface {
Header() *RR_Header Header() *RR_Header
// String returns the text representation of the resource record. // String returns the text representation of the resource record.
String() string String() string
// copy returns a copy of the RR // copy returns a copy of the RR
copy() RR copy() RR
// len returns the length (in octets) of the uncompressed RR in wire format. // len returns the length (in octets) of the uncompressed RR in wire format.
len() int len() int
// pack packs an RR into wire format.
pack([]byte, int, map[string]int, bool) (int, error)
} }
// RR_Header is the header all DNS resource records share. // RR_Header is the header all DNS resource records share.
@ -42,13 +43,13 @@ type RR_Header struct {
Rrtype uint16 Rrtype uint16
Class uint16 Class uint16
Ttl uint32 Ttl uint32
Rdlength uint16 // length of data after header Rdlength uint16 // Length of data after header.
} }
// Header returns itself. This is here to make RR_Header implement the RR interface. // Header returns itself. This is here to make RR_Header implements the RR interface.
func (h *RR_Header) Header() *RR_Header { return h } func (h *RR_Header) Header() *RR_Header { return h }
// Just to imlement the RR interface. // Just to implement the RR interface.
func (h *RR_Header) copy() RR { return nil } func (h *RR_Header) copy() RR { return nil }
func (h *RR_Header) copyHeader() *RR_Header { func (h *RR_Header) copyHeader() *RR_Header {
@ -82,19 +83,22 @@ func (h *RR_Header) len() int {
return l return l
} }
// ToRFC3597 converts a known RR to the unknown RR representation // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
// from RFC 3597.
func (rr *RFC3597) ToRFC3597(r RR) error { func (rr *RFC3597) ToRFC3597(r RR) error {
buf := make([]byte, r.len()*2) buf := make([]byte, r.len()*2)
off, err := PackStruct(r, buf, 0) off, err := PackRR(r, buf, 0, nil, false)
if err != nil { if err != nil {
return err return err
} }
buf = buf[:off] buf = buf[:off]
rawSetRdlength(buf, 0, off) if int(r.Header().Rdlength) > off {
_, err = UnpackStruct(rr, buf, 0) return ErrBuf
}
rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength))
if err != nil { if err != nil {
return err return err
} }
*rr = *rfc3597.(*RFC3597)
return nil return nil
} }

View file

@ -13,6 +13,7 @@ import (
_ "crypto/sha256" _ "crypto/sha256"
_ "crypto/sha512" _ "crypto/sha512"
"encoding/asn1" "encoding/asn1"
"encoding/binary"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"sort" "sort"
@ -103,9 +104,7 @@ const (
ZONE = 1 << 8 ZONE = 1 << 8
) )
// The RRSIG needs to be converted to wireformat with some of // The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing.
// the rdata (the signature) missing. Use this struct to easy
// the conversion (and re-use the pack/unpack functions).
type rrsigWireFmt struct { type rrsigWireFmt struct {
TypeCovered uint16 TypeCovered uint16
Algorithm uint8 Algorithm uint8
@ -144,7 +143,7 @@ func (k *DNSKEY) KeyTag() uint16 {
// at the base64 values. But I'm lazy. // at the base64 values. But I'm lazy.
modulus, _ := fromBase64([]byte(k.PublicKey)) modulus, _ := fromBase64([]byte(k.PublicKey))
if len(modulus) > 1 { if len(modulus) > 1 {
x, _ := unpackUint16(modulus, len(modulus)-2) x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
keytag = int(x) keytag = int(x)
} }
default: default:
@ -154,7 +153,7 @@ func (k *DNSKEY) KeyTag() uint16 {
keywire.Algorithm = k.Algorithm keywire.Algorithm = k.Algorithm
keywire.PublicKey = k.PublicKey keywire.PublicKey = k.PublicKey
wire := make([]byte, DefaultMsgSize) wire := make([]byte, DefaultMsgSize)
n, err := PackStruct(keywire, wire, 0) n, err := packKeyWire(keywire, wire)
if err != nil { if err != nil {
return 0 return 0
} }
@ -192,7 +191,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
keywire.Algorithm = k.Algorithm keywire.Algorithm = k.Algorithm
keywire.PublicKey = k.PublicKey keywire.PublicKey = k.PublicKey
wire := make([]byte, DefaultMsgSize) wire := make([]byte, DefaultMsgSize)
n, err := PackStruct(keywire, wire, 0) n, err := packKeyWire(keywire, wire)
if err != nil { if err != nil {
return nil return nil
} }
@ -248,13 +247,12 @@ func (d *DS) ToCDS() *CDS {
return c return c
} }
// Sign signs an RRSet. The signature needs to be filled in with // Sign signs an RRSet. The signature needs to be filled in with the values:
// the values: Inception, Expiration, KeyTag, SignerName and Algorithm. // Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied
// The rest is copied from the RRset. Sign returns true when the signing went OK, // from the RRset. Sign returns a non-nill error when the signing went OK.
// otherwise false. // There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non
// There is no check if RRSet is a proper (RFC 2181) RRSet. // zero, it is used as-is, otherwise the TTL of the RRset is used as the
// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset // OrigTTL.
// is used as the OrigTTL.
func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error { func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
if k == nil { if k == nil {
return ErrPrivKey return ErrPrivKey
@ -290,7 +288,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
// Create the desired binary blob // Create the desired binary blob
signdata := make([]byte, DefaultMsgSize) signdata := make([]byte, DefaultMsgSize)
n, err := PackStruct(sigwire, signdata, 0) n, err := packSigWire(sigwire, signdata)
if err != nil { if err != nil {
return err return err
} }
@ -408,7 +406,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
sigwire.SignerName = strings.ToLower(rr.SignerName) sigwire.SignerName = strings.ToLower(rr.SignerName)
// Create the desired binary blob // Create the desired binary blob
signeddata := make([]byte, DefaultMsgSize) signeddata := make([]byte, DefaultMsgSize)
n, err := PackStruct(sigwire, signeddata, 0) n, err := packSigWire(sigwire, signeddata)
if err != nil { if err != nil {
return err return err
} }
@ -421,8 +419,8 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
sigbuf := rr.sigBuf() // Get the binary signature data sigbuf := rr.sigBuf() // Get the binary signature data
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
// TODO(mg) // TODO(miek)
// remove the domain name and assume its our // remove the domain name and assume its ours?
} }
hash, ok := AlgorithmToHash[rr.Algorithm] hash, ok := AlgorithmToHash[rr.Algorithm]
@ -609,6 +607,12 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
// SRV, DNAME, A6 // SRV, DNAME, A6
//
// RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC):
// Section 6.2 of [RFC4034] also erroneously lists HINFO as a record
// that needs conversion to lowercase, and twice at that. Since HINFO
// records contain no domain names, they are not subject to case
// conversion.
switch x := r1.(type) { switch x := r1.(type) {
case *NS: case *NS:
x.Ns = strings.ToLower(x.Ns) x.Ns = strings.ToLower(x.Ns)
@ -657,3 +661,61 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
} }
return buf, nil return buf, nil
} }
func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) {
// copied from zmsg.go RRSIG packing
off, err := packUint16(sw.TypeCovered, msg, 0)
if err != nil {
return off, err
}
off, err = packUint8(sw.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(sw.Labels, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(sw.OrigTtl, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(sw.Expiration, msg, off)
if err != nil {
return off, err
}
off, err = packUint32(sw.Inception, msg, off)
if err != nil {
return off, err
}
off, err = packUint16(sw.KeyTag, msg, off)
if err != nil {
return off, err
}
off, err = PackDomainName(sw.SignerName, msg, off, nil, false)
if err != nil {
return off, err
}
return off, nil
}
func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) {
// copied from zmsg.go DNSKEY packing
off, err := packUint16(dw.Flags, msg, 0)
if err != nil {
return off, err
}
off, err = packUint8(dw.Protocol, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(dw.Algorithm, msg, off)
if err != nil {
return off, err
}
off, err = packStringBase64(dw.PublicKey, msg, off)
if err != nil {
return off, err
}
return off, nil
}

View file

@ -14,7 +14,7 @@ import (
// NewPrivateKey returns a PrivateKey by parsing the string s. // NewPrivateKey returns a PrivateKey by parsing the string s.
// s should be in the same form of the BIND private key files. // s should be in the same form of the BIND private key files.
func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) { func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
if s[len(s)-1] != '\n' { // We need a closing newline if s == "" || s[len(s)-1] != '\n' { // We need a closing newline
return k.ReadPrivateKey(strings.NewReader(s+"\n"), "") return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
} }
return k.ReadPrivateKey(strings.NewReader(s), "") return k.ReadPrivateKey(strings.NewReader(s), "")
@ -25,9 +25,9 @@ func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
// The public key must be known, because some cryptographic algorithms embed // The public key must be known, because some cryptographic algorithms embed
// the public inside the privatekey. // the public inside the privatekey.
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) { func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
m, e := parseKey(q, file) m, err := parseKey(q, file)
if m == nil { if m == nil {
return nil, e return nil, err
} }
if _, ok := m["private-key-format"]; !ok { if _, ok := m["private-key-format"]; !ok {
return nil, ErrPrivKey return nil, ErrPrivKey
@ -42,16 +42,16 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
} }
switch uint8(algo) { switch uint8(algo) {
case DSA: case DSA:
priv, e := readPrivateKeyDSA(m) priv, err := readPrivateKeyDSA(m)
if e != nil { if err != nil {
return nil, e return nil, err
} }
pub := k.publicKeyDSA() pub := k.publicKeyDSA()
if pub == nil { if pub == nil {
return nil, ErrKey return nil, ErrKey
} }
priv.PublicKey = *pub priv.PublicKey = *pub
return priv, e return priv, nil
case RSAMD5: case RSAMD5:
fallthrough fallthrough
case RSASHA1: case RSASHA1:
@ -61,31 +61,31 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
case RSASHA256: case RSASHA256:
fallthrough fallthrough
case RSASHA512: case RSASHA512:
priv, e := readPrivateKeyRSA(m) priv, err := readPrivateKeyRSA(m)
if e != nil { if err != nil {
return nil, e return nil, err
} }
pub := k.publicKeyRSA() pub := k.publicKeyRSA()
if pub == nil { if pub == nil {
return nil, ErrKey return nil, ErrKey
} }
priv.PublicKey = *pub priv.PublicKey = *pub
return priv, e return priv, nil
case ECCGOST: case ECCGOST:
return nil, ErrPrivKey return nil, ErrPrivKey
case ECDSAP256SHA256: case ECDSAP256SHA256:
fallthrough fallthrough
case ECDSAP384SHA384: case ECDSAP384SHA384:
priv, e := readPrivateKeyECDSA(m) priv, err := readPrivateKeyECDSA(m)
if e != nil { if err != nil {
return nil, e return nil, err
} }
pub := k.publicKeyECDSA() pub := k.publicKeyECDSA()
if pub == nil { if pub == nil {
return nil, ErrKey return nil, ErrKey
} }
priv.PublicKey = *pub priv.PublicKey = *pub
return priv, e return priv, nil
default: default:
return nil, ErrPrivKey return nil, ErrPrivKey
} }

8
vendor/github.com/miekg/dns/doc.go generated vendored
View file

@ -101,7 +101,7 @@ uses public key cryptography to sign resource records. The
public keys are stored in DNSKEY records and the signatures in RRSIG records. public keys are stored in DNSKEY records and the signatures in RRSIG records.
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
to an request. to a request.
m := new(dns.Msg) m := new(dns.Msg)
m.SetEdns0(4096, true) m.SetEdns0(4096, true)
@ -184,9 +184,9 @@ Basic use pattern validating and replying to a message that has TSIG set.
dns.HandleFunc(".", handleRequest) dns.HandleFunc(".", handleRequest)
func handleRequest(w dns.ResponseWriter, r *dns.Msg) { func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
m := new(Msg) m := new(dns.Msg)
m.SetReply(r) m.SetReply(r)
if r.IsTsig() { if r.IsTsig() != nil {
if w.TsigStatus() == nil { if w.TsigStatus() == nil {
// *Msg r has an TSIG record and it was validated // *Msg r has an TSIG record and it was validated
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
@ -203,7 +203,7 @@ RFC 6895 sets aside a range of type codes for private use. This range
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
can be used, before requesting an official type code from IANA. can be used, before requesting an official type code from IANA.
see http://miek.nl/posts/2014/Sep/21/Private%20RRs%20and%20IDN%20in%20Go%20DNS/ for more see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
information. information.
EDNS0 EDNS0

116
vendor/github.com/miekg/dns/edns.go generated vendored
View file

@ -1,6 +1,7 @@
package dns package dns
import ( import (
"encoding/binary"
"encoding/hex" "encoding/hex"
"errors" "errors"
"net" "net"
@ -17,6 +18,7 @@ const (
EDNS0N3U = 0x7 // NSEC3 Hash Understood EDNS0N3U = 0x7 // NSEC3 Hash Understood
EDNS0SUBNET = 0x8 // client-subnet (RFC6891) EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
EDNS0EXPIRE = 0x9 // EDNS0 expire EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891) EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891) EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
@ -30,11 +32,6 @@ type OPT struct {
Option []EDNS0 `dns:"opt"` Option []EDNS0 `dns:"opt"`
} }
// Header implements the RR interface.
func (rr *OPT) Header() *RR_Header {
return &rr.Hdr
}
func (rr *OPT) String() string { func (rr *OPT) String() string {
s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; " s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
if rr.Do() { if rr.Do() {
@ -61,6 +58,8 @@ func (rr *OPT) String() string {
if o.(*EDNS0_SUBNET).DraftOption { if o.(*EDNS0_SUBNET).DraftOption {
s += " (draft)" s += " (draft)"
} }
case *EDNS0_COOKIE:
s += "\n; COOKIE: " + o.String()
case *EDNS0_UL: case *EDNS0_UL:
s += "\n; UPDATE LEASE: " + o.String() s += "\n; UPDATE LEASE: " + o.String()
case *EDNS0_LLQ: case *EDNS0_LLQ:
@ -88,10 +87,6 @@ func (rr *OPT) len() int {
return l return l
} }
func (rr *OPT) copy() RR {
return &OPT{*rr.Hdr.copyHeader(), rr.Option}
}
// return the old value -> delete SetVersion? // return the old value -> delete SetVersion?
// Version returns the EDNS version used. Only zero is defined. // Version returns the EDNS version used. Only zero is defined.
@ -105,13 +100,16 @@ func (rr *OPT) SetVersion(v uint8) {
} }
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL). // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
func (rr *OPT) ExtendedRcode() uint8 { func (rr *OPT) ExtendedRcode() int {
return uint8((rr.Hdr.Ttl & 0xFF000000) >> 24) return int((rr.Hdr.Ttl&0xFF000000)>>24) + 15
} }
// SetExtendedRcode sets the EDNS extended RCODE field. // SetExtendedRcode sets the EDNS extended RCODE field.
func (rr *OPT) SetExtendedRcode(v uint8) { func (rr *OPT) SetExtendedRcode(v uint8) {
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24) if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
return
}
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v-15) << 24)
} }
// UDPSize returns the UDP buffer size. // UDPSize returns the UDP buffer size.
@ -130,12 +128,21 @@ func (rr *OPT) Do() bool {
} }
// SetDo sets the DO (DNSSEC OK) bit. // SetDo sets the DO (DNSSEC OK) bit.
func (rr *OPT) SetDo() { // If we pass an argument, set the DO bit to that value.
// It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored.
func (rr *OPT) SetDo(do ...bool) {
if len(do) == 1 {
if do[0] {
rr.Hdr.Ttl |= _DO
} else {
rr.Hdr.Ttl &^= _DO
}
} else {
rr.Hdr.Ttl |= _DO rr.Hdr.Ttl |= _DO
} }
}
// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
// it.
type EDNS0 interface { type EDNS0 interface {
// Option returns the option code for the option. // Option returns the option code for the option.
Option() uint16 Option() uint16
@ -216,7 +223,7 @@ func (e *EDNS0_SUBNET) Option() uint16 {
func (e *EDNS0_SUBNET) pack() ([]byte, error) { func (e *EDNS0_SUBNET) pack() ([]byte, error) {
b := make([]byte, 4) b := make([]byte, 4)
b[0], b[1] = packUint16(e.Family) binary.BigEndian.PutUint16(b[0:], e.Family)
b[2] = e.SourceNetmask b[2] = e.SourceNetmask
b[3] = e.SourceScope b[3] = e.SourceScope
switch e.Family { switch e.Family {
@ -250,7 +257,7 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
if len(b) < 4 { if len(b) < 4 {
return ErrBuf return ErrBuf
} }
e.Family, _ = unpackUint16(b, 0) e.Family = binary.BigEndian.Uint16(b)
e.SourceNetmask = b[2] e.SourceNetmask = b[2]
e.SourceScope = b[3] e.SourceScope = b[3]
switch e.Family { switch e.Family {
@ -292,6 +299,41 @@ func (e *EDNS0_SUBNET) String() (s string) {
return return
} }
// The Cookie EDNS0 option
//
// o := new(dns.OPT)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeOPT
// e := new(dns.EDNS0_COOKIE)
// e.Code = dns.EDNS0COOKIE
// e.Cookie = "24a5ac.."
// o.Option = append(o.Option, e)
//
// The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is
// always 8 bytes. It may then optionally be followed by the server cookie. The server
// cookie is of variable length, 8 to a maximum of 32 bytes. In other words:
//
// cCookie := o.Cookie[:16]
// sCookie := o.Cookie[16:]
//
// There is no guarantee that the Cookie string has a specific length.
type EDNS0_COOKIE struct {
Code uint16 // Always EDNS0COOKIE
Cookie string // Hex-encoded cookie data
}
func (e *EDNS0_COOKIE) pack() ([]byte, error) {
h, err := hex.DecodeString(e.Cookie)
if err != nil {
return nil, err
}
return h, nil
}
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
func (e *EDNS0_COOKIE) String() string { return e.Cookie }
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
// an expiration on an update RR. This is helpful for clients that cannot clean // an expiration on an update RR. This is helpful for clients that cannot clean
// up after themselves. This is a draft RFC and more information can be found at // up after themselves. This is a draft RFC and more information can be found at
@ -315,10 +357,7 @@ func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease),
// Copied: http://golang.org/src/pkg/net/dnsmsg.go // Copied: http://golang.org/src/pkg/net/dnsmsg.go
func (e *EDNS0_UL) pack() ([]byte, error) { func (e *EDNS0_UL) pack() ([]byte, error) {
b := make([]byte, 4) b := make([]byte, 4)
b[0] = byte(e.Lease >> 24) binary.BigEndian.PutUint32(b, e.Lease)
b[1] = byte(e.Lease >> 16)
b[2] = byte(e.Lease >> 8)
b[3] = byte(e.Lease)
return b, nil return b, nil
} }
@ -326,7 +365,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
if len(b) < 4 { if len(b) < 4 {
return ErrBuf return ErrBuf
} }
e.Lease = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) e.Lease = binary.BigEndian.Uint32(b)
return nil return nil
} }
@ -345,21 +384,11 @@ func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
func (e *EDNS0_LLQ) pack() ([]byte, error) { func (e *EDNS0_LLQ) pack() ([]byte, error) {
b := make([]byte, 18) b := make([]byte, 18)
b[0], b[1] = packUint16(e.Version) binary.BigEndian.PutUint16(b[0:], e.Version)
b[2], b[3] = packUint16(e.Opcode) binary.BigEndian.PutUint16(b[2:], e.Opcode)
b[4], b[5] = packUint16(e.Error) binary.BigEndian.PutUint16(b[4:], e.Error)
b[6] = byte(e.Id >> 56) binary.BigEndian.PutUint64(b[6:], e.Id)
b[7] = byte(e.Id >> 48) binary.BigEndian.PutUint32(b[14:], e.LeaseLife)
b[8] = byte(e.Id >> 40)
b[9] = byte(e.Id >> 32)
b[10] = byte(e.Id >> 24)
b[11] = byte(e.Id >> 16)
b[12] = byte(e.Id >> 8)
b[13] = byte(e.Id)
b[14] = byte(e.LeaseLife >> 24)
b[15] = byte(e.LeaseLife >> 16)
b[16] = byte(e.LeaseLife >> 8)
b[17] = byte(e.LeaseLife)
return b, nil return b, nil
} }
@ -367,12 +396,11 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
if len(b) < 18 { if len(b) < 18 {
return ErrBuf return ErrBuf
} }
e.Version, _ = unpackUint16(b, 0) e.Version = binary.BigEndian.Uint16(b[0:])
e.Opcode, _ = unpackUint16(b, 2) e.Opcode = binary.BigEndian.Uint16(b[2:])
e.Error, _ = unpackUint16(b, 4) e.Error = binary.BigEndian.Uint16(b[4:])
e.Id = uint64(b[6])<<56 | uint64(b[6+1])<<48 | uint64(b[6+2])<<40 | e.Id = binary.BigEndian.Uint64(b[6:])
uint64(b[6+3])<<32 | uint64(b[6+4])<<24 | uint64(b[6+5])<<16 | uint64(b[6+6])<<8 | uint64(b[6+7]) e.LeaseLife = binary.BigEndian.Uint32(b[14:])
e.LeaseLife = uint32(b[14])<<24 | uint32(b[14+1])<<16 | uint32(b[14+2])<<8 | uint32(b[14+3])
return nil return nil
} }
@ -468,7 +496,7 @@ func (e *EDNS0_EXPIRE) unpack(b []byte) error {
if len(b) < 4 { if len(b) < 4 {
return ErrBuf return ErrBuf
} }
e.Expire = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) e.Expire = binary.BigEndian.Uint32(b)
return nil return nil
} }

View file

@ -69,15 +69,6 @@ func Field(r RR, i int) string {
s += " " + Type(d.Index(i).Uint()).String() s += " " + Type(d.Index(i).Uint()).String()
} }
return s return s
case `dns:"wks"`:
if d.Len() == 0 {
return ""
}
s := strconv.Itoa(int(d.Index(0).Uint()))
for i := 0; i < d.Len(); i++ {
s += " " + strconv.Itoa(int(d.Index(i).Uint()))
}
return s
default: default:
// if it does not have a tag its a string slice // if it does not have a tag its a string slice
fallthrough fallthrough

View file

@ -2,6 +2,7 @@ package dns
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -15,7 +16,7 @@ import (
// * [[ttl][class]] // * [[ttl][class]]
// * type // * type
// * rhs (rdata) // * rhs (rdata)
// But we are lazy here, only the range is parsed *all* occurences // But we are lazy here, only the range is parsed *all* occurrences
// of $ after that are interpreted. // of $ after that are interpreted.
// Any error are returned as a string value, the empty string signals // Any error are returned as a string value, the empty string signals
// "no error". // "no error".
@ -25,7 +26,7 @@ func generate(l lex, c chan lex, t chan *Token, o string) string {
if i+1 == len(l.token) { if i+1 == len(l.token) {
return "bad step in $GENERATE range" return "bad step in $GENERATE range"
} }
if s, e := strconv.Atoi(l.token[i+1:]); e == nil { if s, err := strconv.Atoi(l.token[i+1:]); err == nil {
if s < 0 { if s < 0 {
return "bad step in $GENERATE range" return "bad step in $GENERATE range"
} }
@ -65,7 +66,7 @@ BuildRR:
escape bool escape bool
dom bytes.Buffer dom bytes.Buffer
mod string mod string
err string err error
offset int offset int
) )
@ -104,8 +105,8 @@ BuildRR:
return "bad modifier in $GENERATE" return "bad modifier in $GENERATE"
} }
mod, offset, err = modToPrintf(s[j+2 : j+2+sep]) mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
if err != "" { if err != nil {
return err return err.Error()
} }
j += 2 + sep // Jump to it j += 2 + sep // Jump to it
} }
@ -119,9 +120,9 @@ BuildRR:
} }
} }
// Re-parse the RR and send it on the current channel t // Re-parse the RR and send it on the current channel t
rx, e := NewRR("$ORIGIN " + o + "\n" + dom.String()) rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String())
if e != nil { if err != nil {
return e.(*ParseError).err return err.Error()
} }
t <- &Token{RR: rx} t <- &Token{RR: rx}
// Its more efficient to first built the rrlist and then parse it in // Its more efficient to first built the rrlist and then parse it in
@ -131,28 +132,28 @@ BuildRR:
} }
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with. // Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
func modToPrintf(s string) (string, int, string) { func modToPrintf(s string) (string, int, error) {
xs := strings.SplitN(s, ",", 3) xs := strings.SplitN(s, ",", 3)
if len(xs) != 3 { if len(xs) != 3 {
return "", 0, "bad modifier in $GENERATE" return "", 0, errors.New("bad modifier in $GENERATE")
} }
// xs[0] is offset, xs[1] is width, xs[2] is base // xs[0] is offset, xs[1] is width, xs[2] is base
if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" { if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
return "", 0, "bad base in $GENERATE" return "", 0, errors.New("bad base in $GENERATE")
} }
offset, err := strconv.Atoi(xs[0]) offset, err := strconv.Atoi(xs[0])
if err != nil || offset > 255 { if err != nil || offset > 255 {
return "", 0, "bad offset in $GENERATE" return "", 0, errors.New("bad offset in $GENERATE")
} }
width, err := strconv.Atoi(xs[1]) width, err := strconv.Atoi(xs[1])
if err != nil || width > 255 { if err != nil || width > 255 {
return "", offset, "bad width in $GENERATE" return "", offset, errors.New("bad width in $GENERATE")
} }
switch { switch {
case width < 0: case width < 0:
return "", offset, "bad width in $GENERATE" return "", offset, errors.New("bad width in $GENERATE")
case width == 0: case width == 0:
return "%" + xs[1] + xs[2], offset, "" return "%" + xs[1] + xs[2], offset, nil
} }
return "%0" + xs[1] + xs[2], offset, "" return "%0" + xs[1] + xs[2], offset, nil
} }

View file

@ -4,9 +4,11 @@ package dns
// SplitDomainName splits a name string into it's labels. // SplitDomainName splits a name string into it's labels.
// www.miek.nl. returns []string{"www", "miek", "nl"} // www.miek.nl. returns []string{"www", "miek", "nl"}
// .www.miek.nl. returns []string{"", "www", "miek", "nl"},
// The root label (.) returns nil. Note that using // The root label (.) returns nil. Note that using
// strings.Split(s) will work in most cases, but does not handle // strings.Split(s) will work in most cases, but does not handle
// escaped dots (\.) for instance. // escaped dots (\.) for instance.
// s must be a syntactically valid domain name, see IsDomainName.
func SplitDomainName(s string) (labels []string) { func SplitDomainName(s string) (labels []string) {
if len(s) == 0 { if len(s) == 0 {
return nil return nil
@ -45,6 +47,8 @@ func SplitDomainName(s string) (labels []string) {
// //
// www.miek.nl. and miek.nl. have two labels in common: miek and nl // www.miek.nl. and miek.nl. have two labels in common: miek and nl
// www.miek.nl. and www.bla.nl. have one label in common: nl // www.miek.nl. and www.bla.nl. have one label in common: nl
//
// s1 and s2 must be syntactically valid domain names.
func CompareDomainName(s1, s2 string) (n int) { func CompareDomainName(s1, s2 string) (n int) {
s1 = Fqdn(s1) s1 = Fqdn(s1)
s2 = Fqdn(s2) s2 = Fqdn(s2)
@ -85,6 +89,7 @@ func CompareDomainName(s1, s2 string) (n int) {
} }
// CountLabel counts the the number of labels in the string s. // CountLabel counts the the number of labels in the string s.
// s must be a syntactically valid domain name.
func CountLabel(s string) (labels int) { func CountLabel(s string) (labels int) {
if s == "." { if s == "." {
return return
@ -103,6 +108,7 @@ func CountLabel(s string) (labels int) {
// Split splits a name s into its label indexes. // Split splits a name s into its label indexes.
// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}. // www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
// The root name (.) returns nil. Also see SplitDomainName. // The root name (.) returns nil. Also see SplitDomainName.
// s must be a syntactically valid domain name.
func Split(s string) []int { func Split(s string) []int {
if s == "." { if s == "." {
return nil return nil

1281
vendor/github.com/miekg/dns/msg.go generated vendored

File diff suppressed because it is too large Load diff

340
vendor/github.com/miekg/dns/msg_generate.go generated vendored Normal file
View file

@ -0,0 +1,340 @@
//+build ignore
// msg_generate.go is meant to run with go generate. It will use
// go/{importer,types} to track down all the RR struct types. Then for each type
// it will generate pack/unpack methods based on the struct tags. The generated source is
// written to zmsg.go, and is meant to be checked into git.
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/types"
"log"
"os"
"strings"
)
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from msg_generate.go
package dns
`
// getTypeStruct will take a type and the package scope, and return the
// (innermost) struct if the type is considered a RR type (currently defined as
// those structs beginning with a RR_Header, could be redefined as implementing
// the RR interface). The bool return value indicates if embedded structs were
// resolved.
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
st, ok := t.Underlying().(*types.Struct)
if !ok {
return nil, false
}
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
return st, false
}
if st.Field(0).Anonymous() {
st, _ := getTypeStruct(st.Field(0).Type(), scope)
return st, true
}
return nil, false
}
func main() {
// Import and type-check the package
pkg, err := importer.Default().Import("github.com/miekg/dns")
fatalIfErr(err)
scope := pkg.Scope()
// Collect actual types (*X)
var namedTypes []string
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
continue
}
if name == "PrivateRR" {
continue
}
// Check if corresponding TypeX exists
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
log.Fatalf("Constant Type%s does not exist.", o.Name())
}
namedTypes = append(namedTypes, o.Name())
}
b := &bytes.Buffer{}
b.WriteString(packageHdr)
fmt.Fprint(b, "// pack*() functions\n\n")
for _, name := range namedTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil {
return off, err
}
headerEnd := off
`)
for i := 1; i < st.NumFields(); i++ {
o := func(s string) {
fmt.Fprintf(b, s, st.Field(i).Name())
fmt.Fprint(b, `if err != nil {
return off, err
}
`)
}
if _, ok := st.Field(i).Type().(*types.Slice); ok {
switch st.Tag(i) {
case `dns:"-"`: // ignored
case `dns:"txt"`:
o("off, err = packStringTxt(rr.%s, msg, off)\n")
case `dns:"opt"`:
o("off, err = packDataOpt(rr.%s, msg, off)\n")
case `dns:"nsec"`:
o("off, err = packDataNsec(rr.%s, msg, off)\n")
case `dns:"domain-name"`:
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
continue
}
switch {
case st.Tag(i) == `dns:"-"`: // ignored
case st.Tag(i) == `dns:"cdomain-name"`:
fallthrough
case st.Tag(i) == `dns:"domain-name"`:
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
case st.Tag(i) == `dns:"a"`:
o("off, err = packDataA(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"aaaa"`:
o("off, err = packDataAAAA(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"uint48"`:
o("off, err = packUint48(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"txt"`:
o("off, err = packString(rr.%s, msg, off)\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
fallthrough
case st.Tag(i) == `dns:"base32"`:
o("off, err = packStringBase32(rr.%s, msg, off)\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
fallthrough
case st.Tag(i) == `dns:"base64"`:
o("off, err = packStringBase64(rr.%s, msg, off)\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`): // Hack to fix empty salt length for NSEC3
o("if rr.%s == \"-\" { /* do nothing, empty salt */ }\n")
continue
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
fallthrough
case st.Tag(i) == `dns:"hex"`:
o("off, err = packStringHex(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"octet"`:
o("off, err = packStringOctet(rr.%s, msg, off)\n")
case st.Tag(i) == "":
switch st.Field(i).Type().(*types.Basic).Kind() {
case types.Uint8:
o("off, err = packUint8(rr.%s, msg, off)\n")
case types.Uint16:
o("off, err = packUint16(rr.%s, msg, off)\n")
case types.Uint32:
o("off, err = packUint32(rr.%s, msg, off)\n")
case types.Uint64:
o("off, err = packUint64(rr.%s, msg, off)\n")
case types.String:
o("off, err = packString(rr.%s, msg, off)\n")
default:
log.Fatalln(name, st.Field(i).Name())
}
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
}
// We have packed everything, only now we know the rdlength of this RR
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
fmt.Fprintln(b, "return off, nil }\n")
}
fmt.Fprint(b, "// unpack*() functions\n\n")
for _, name := range namedTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
fmt.Fprintf(b, "rr := new(%s)\n", name)
fmt.Fprint(b, "rr.Hdr = h\n")
fmt.Fprint(b, `if noRdata(h) {
return rr, off, nil
}
var err error
rdStart := off
_ = rdStart
`)
for i := 1; i < st.NumFields(); i++ {
o := func(s string) {
fmt.Fprintf(b, s, st.Field(i).Name())
fmt.Fprint(b, `if err != nil {
return rr, off, err
}
`)
}
// size-* are special, because they reference a struct member we should use for the length.
if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
structMember := structMember(st.Tag(i))
structTag := structTag(st.Tag(i))
switch structTag {
case "hex":
fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
case "base32":
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
case "base64":
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
fmt.Fprint(b, `if err != nil {
return rr, off, err
}
`)
continue
}
if _, ok := st.Field(i).Type().(*types.Slice); ok {
switch st.Tag(i) {
case `dns:"-"`: // ignored
case `dns:"txt"`:
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
case `dns:"opt"`:
o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
case `dns:"nsec"`:
o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
case `dns:"domain-name"`:
o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
continue
}
switch st.Tag(i) {
case `dns:"-"`: // ignored
case `dns:"cdomain-name"`:
fallthrough
case `dns:"domain-name"`:
o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
case `dns:"a"`:
o("rr.%s, off, err = unpackDataA(msg, off)\n")
case `dns:"aaaa"`:
o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
case `dns:"uint48"`:
o("rr.%s, off, err = unpackUint48(msg, off)\n")
case `dns:"txt"`:
o("rr.%s, off, err = unpackString(msg, off)\n")
case `dns:"base32"`:
o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"base64"`:
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"hex"`:
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"octet"`:
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
case "":
switch st.Field(i).Type().(*types.Basic).Kind() {
case types.Uint8:
o("rr.%s, off, err = unpackUint8(msg, off)\n")
case types.Uint16:
o("rr.%s, off, err = unpackUint16(msg, off)\n")
case types.Uint32:
o("rr.%s, off, err = unpackUint32(msg, off)\n")
case types.Uint64:
o("rr.%s, off, err = unpackUint64(msg, off)\n")
case types.String:
o("rr.%s, off, err = unpackString(msg, off)\n")
default:
log.Fatalln(name, st.Field(i).Name())
}
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
// If we've hit len(msg) we return without error.
if i < st.NumFields()-1 {
fmt.Fprintf(b, `if off == len(msg) {
return rr, off, nil
}
`)
}
}
fmt.Fprintf(b, "return rr, off, err }\n\n")
}
// Generate typeToUnpack map
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
for _, name := range namedTypes {
if name == "RFC3597" {
continue
}
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
}
fmt.Fprintln(b, "}\n")
// gofmt
res, err := format.Source(b.Bytes())
if err != nil {
b.WriteTo(os.Stderr)
log.Fatal(err)
}
// write result
f, err := os.Create("zmsg.go")
fatalIfErr(err)
defer f.Close()
f.Write(res)
}
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
func structMember(s string) string {
fields := strings.Split(s, ":")
if len(fields) == 0 {
return ""
}
f := fields[len(fields)-1]
// f should have a closing "
if len(f) > 1 {
return f[:len(f)-1]
}
return f
}
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
func structTag(s string) string {
fields := strings.Split(s, ":")
if len(fields) < 2 {
return ""
}
return fields[1][len("\"size-"):]
}
func fatalIfErr(err error) {
if err != nil {
log.Fatal(err)
}
}

630
vendor/github.com/miekg/dns/msg_helpers.go generated vendored Normal file
View file

@ -0,0 +1,630 @@
package dns
import (
"encoding/base32"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"net"
"strconv"
)
// helper functions called from the generated zmsg.go
// These function are named after the tag to help pack/unpack, if there is no tag it is the name
// of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or
// packDataDomainName.
func unpackDataA(msg []byte, off int) (net.IP, int, error) {
if off+net.IPv4len > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking a"}
}
a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...)
off += net.IPv4len
return a, off, nil
}
func packDataA(a net.IP, msg []byte, off int) (int, error) {
// It must be a slice of 4, even if it is 16, we encode only the first 4
if off+net.IPv4len > len(msg) {
return len(msg), &Error{err: "overflow packing a"}
}
switch len(a) {
case net.IPv4len, net.IPv6len:
copy(msg[off:], a.To4())
off += net.IPv4len
case 0:
// Allowed, for dynamic updates.
default:
return len(msg), &Error{err: "overflow packing a"}
}
return off, nil
}
func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
if off+net.IPv6len > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
}
aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...)
off += net.IPv6len
return aaaa, off, nil
}
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
if off+net.IPv6len > len(msg) {
return len(msg), &Error{err: "overflow packing aaaa"}
}
switch len(aaaa) {
case net.IPv6len:
copy(msg[off:], aaaa)
off += net.IPv6len
case 0:
// Allowed, dynamic updates.
default:
return len(msg), &Error{err: "overflow packing aaaa"}
}
return off, nil
}
// unpackHeader unpacks an RR header, returning the offset to the end of the header and a
// re-sliced msg according to the expected length of the RR.
func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte, err error) {
hdr := RR_Header{}
if off == len(msg) {
return hdr, off, msg, nil
}
hdr.Name, off, err = UnpackDomainName(msg, off)
if err != nil {
return hdr, len(msg), msg, err
}
hdr.Rrtype, off, err = unpackUint16(msg, off)
if err != nil {
return hdr, len(msg), msg, err
}
hdr.Class, off, err = unpackUint16(msg, off)
if err != nil {
return hdr, len(msg), msg, err
}
hdr.Ttl, off, err = unpackUint32(msg, off)
if err != nil {
return hdr, len(msg), msg, err
}
hdr.Rdlength, off, err = unpackUint16(msg, off)
if err != nil {
return hdr, len(msg), msg, err
}
msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
return hdr, off, msg, nil
}
// pack packs an RR header, returning the offset to the end of the header.
// See PackDomainName for documentation about the compression.
func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
if off == len(msg) {
return off, nil
}
off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
if err != nil {
return len(msg), err
}
off, err = packUint16(hdr.Rrtype, msg, off)
if err != nil {
return len(msg), err
}
off, err = packUint16(hdr.Class, msg, off)
if err != nil {
return len(msg), err
}
off, err = packUint32(hdr.Ttl, msg, off)
if err != nil {
return len(msg), err
}
off, err = packUint16(hdr.Rdlength, msg, off)
if err != nil {
return len(msg), err
}
return off, nil
}
// helper helper functions.
// truncateMsgFromRdLength truncates msg to match the expected length of the RR.
// Returns an error if msg is smaller than the expected size.
func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []byte, err error) {
lenrd := off + int(rdlength)
if lenrd > len(msg) {
return msg, &Error{err: "overflowing header size"}
}
return msg[:lenrd], nil
}
func fromBase32(s []byte) (buf []byte, err error) {
buflen := base32.HexEncoding.DecodedLen(len(s))
buf = make([]byte, buflen)
n, err := base32.HexEncoding.Decode(buf, s)
buf = buf[:n]
return
}
func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) }
func fromBase64(s []byte) (buf []byte, err error) {
buflen := base64.StdEncoding.DecodedLen(len(s))
buf = make([]byte, buflen)
n, err := base64.StdEncoding.Decode(buf, s)
buf = buf[:n]
return
}
func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
// dynamicUpdate returns true if the Rdlength is zero.
func noRdata(h RR_Header) bool { return h.Rdlength == 0 }
func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
if off+1 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint8"}
}
return uint8(msg[off]), off + 1, nil
}
func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
if off+1 > len(msg) {
return len(msg), &Error{err: "overflow packing uint8"}
}
msg[off] = byte(i)
return off + 1, nil
}
func unpackUint16(msg []byte, off int) (i uint16, off1 int, err error) {
if off+2 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint16"}
}
return binary.BigEndian.Uint16(msg[off:]), off + 2, nil
}
func packUint16(i uint16, msg []byte, off int) (off1 int, err error) {
if off+2 > len(msg) {
return len(msg), &Error{err: "overflow packing uint16"}
}
binary.BigEndian.PutUint16(msg[off:], i)
return off + 2, nil
}
func unpackUint32(msg []byte, off int) (i uint32, off1 int, err error) {
if off+4 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint32"}
}
return binary.BigEndian.Uint32(msg[off:]), off + 4, nil
}
func packUint32(i uint32, msg []byte, off int) (off1 int, err error) {
if off+4 > len(msg) {
return len(msg), &Error{err: "overflow packing uint32"}
}
binary.BigEndian.PutUint32(msg[off:], i)
return off + 4, nil
}
func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
if off+6 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
}
// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
i = (uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
uint64(msg[off+4])<<8 | uint64(msg[off+5])))
off += 6
return i, off, nil
}
func packUint48(i uint64, msg []byte, off int) (off1 int, err error) {
if off+6 > len(msg) {
return len(msg), &Error{err: "overflow packing uint64 as uint48"}
}
msg[off] = byte(i >> 40)
msg[off+1] = byte(i >> 32)
msg[off+2] = byte(i >> 24)
msg[off+3] = byte(i >> 16)
msg[off+4] = byte(i >> 8)
msg[off+5] = byte(i)
off += 6
return off, nil
}
func unpackUint64(msg []byte, off int) (i uint64, off1 int, err error) {
if off+8 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint64"}
}
return binary.BigEndian.Uint64(msg[off:]), off + 8, nil
}
func packUint64(i uint64, msg []byte, off int) (off1 int, err error) {
if off+8 > len(msg) {
return len(msg), &Error{err: "overflow packing uint64"}
}
binary.BigEndian.PutUint64(msg[off:], i)
off += 8
return off, nil
}
func unpackString(msg []byte, off int) (string, int, error) {
if off+1 > len(msg) {
return "", off, &Error{err: "overflow unpacking txt"}
}
l := int(msg[off])
if off+l+1 > len(msg) {
return "", off, &Error{err: "overflow unpacking txt"}
}
s := make([]byte, 0, l)
for _, b := range msg[off+1 : off+1+l] {
switch b {
case '"', '\\':
s = append(s, '\\', b)
case '\t', '\r', '\n':
s = append(s, b)
default:
if b < 32 || b > 127 { // unprintable
var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\')
for i := 0; i < 3-len(bufs); i++ {
s = append(s, '0')
}
for _, r := range bufs {
s = append(s, r)
}
} else {
s = append(s, b)
}
}
}
off += 1 + l
return string(s), off, nil
}
func packString(s string, msg []byte, off int) (int, error) {
txtTmp := make([]byte, 256*4+1)
off, err := packTxtString(s, msg, off, txtTmp)
if err != nil {
return len(msg), err
}
return off, nil
}
func unpackStringBase32(msg []byte, off, end int) (string, int, error) {
if end > len(msg) {
return "", len(msg), &Error{err: "overflow unpacking base32"}
}
s := toBase32(msg[off:end])
return s, end, nil
}
func packStringBase32(s string, msg []byte, off int) (int, error) {
b32, err := fromBase32([]byte(s))
if err != nil {
return len(msg), err
}
if off+len(b32) > len(msg) {
return len(msg), &Error{err: "overflow packing base32"}
}
copy(msg[off:off+len(b32)], b32)
off += len(b32)
return off, nil
}
func unpackStringBase64(msg []byte, off, end int) (string, int, error) {
// Rest of the RR is base64 encoded value, so we don't need an explicit length
// to be set. Thus far all RR's that have base64 encoded fields have those as their
// last one. What we do need is the end of the RR!
if end > len(msg) {
return "", len(msg), &Error{err: "overflow unpacking base64"}
}
s := toBase64(msg[off:end])
return s, end, nil
}
func packStringBase64(s string, msg []byte, off int) (int, error) {
b64, err := fromBase64([]byte(s))
if err != nil {
return len(msg), err
}
if off+len(b64) > len(msg) {
return len(msg), &Error{err: "overflow packing base64"}
}
copy(msg[off:off+len(b64)], b64)
off += len(b64)
return off, nil
}
func unpackStringHex(msg []byte, off, end int) (string, int, error) {
// Rest of the RR is hex encoded value, so we don't need an explicit length
// to be set. NSEC and TSIG have hex fields with a length field.
// What we do need is the end of the RR!
if end > len(msg) {
return "", len(msg), &Error{err: "overflow unpacking hex"}
}
s := hex.EncodeToString(msg[off:end])
return s, end, nil
}
func packStringHex(s string, msg []byte, off int) (int, error) {
h, err := hex.DecodeString(s)
if err != nil {
return len(msg), err
}
if off+(len(h)) > len(msg) {
return len(msg), &Error{err: "overflow packing hex"}
}
copy(msg[off:off+len(h)], h)
off += len(h)
return off, nil
}
func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
txt, off, err := unpackTxt(msg, off)
if err != nil {
return nil, len(msg), err
}
return txt, off, nil
}
func packStringTxt(s []string, msg []byte, off int) (int, error) {
txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
off, err := packTxt(s, msg, off, txtTmp)
if err != nil {
return len(msg), err
}
return off, nil
}
func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
var edns []EDNS0
Option:
code := uint16(0)
if off+4 > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking opt"}
}
code = binary.BigEndian.Uint16(msg[off:])
off += 2
optlen := binary.BigEndian.Uint16(msg[off:])
off += 2
if off+int(optlen) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking opt"}
}
switch code {
case EDNS0NSID:
e := new(EDNS0_NSID)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0SUBNET, EDNS0SUBNETDRAFT:
e := new(EDNS0_SUBNET)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
if code == EDNS0SUBNETDRAFT {
e.DraftOption = true
}
case EDNS0COOKIE:
e := new(EDNS0_COOKIE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0UL:
e := new(EDNS0_UL)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0LLQ:
e := new(EDNS0_LLQ)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DAU:
e := new(EDNS0_DAU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DHU:
e := new(EDNS0_DHU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0N3U:
e := new(EDNS0_N3U)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
default:
e := new(EDNS0_LOCAL)
e.Code = code
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
}
if off < len(msg) {
goto Option
}
return edns, off, nil
}
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
for _, el := range options {
b, err := el.pack()
if err != nil || off+3 > len(msg) {
return len(msg), &Error{err: "overflow packing opt"}
}
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
off += 4
if off+len(b) > len(msg) {
copy(msg[off:], b)
off = len(msg)
continue
}
// Actual data
copy(msg[off:off+len(b)], b)
off += len(b)
}
return off, nil
}
func unpackStringOctet(msg []byte, off int) (string, int, error) {
s := string(msg[off:])
return s, len(msg), nil
}
func packStringOctet(s string, msg []byte, off int) (int, error) {
txtTmp := make([]byte, 256*4+1)
off, err := packOctetString(s, msg, off, txtTmp)
if err != nil {
return len(msg), err
}
return off, nil
}
func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
var nsec []uint16
length, window, lastwindow := 0, 0, -1
for off < len(msg) {
if off+2 > len(msg) {
return nsec, len(msg), &Error{err: "overflow unpacking nsecx"}
}
window = int(msg[off])
length = int(msg[off+1])
off += 2
if window <= lastwindow {
// RFC 4034: Blocks are present in the NSEC RR RDATA in
// increasing numerical order.
return nsec, len(msg), &Error{err: "out of order NSEC block"}
}
if length == 0 {
// RFC 4034: Blocks with no types present MUST NOT be included.
return nsec, len(msg), &Error{err: "empty NSEC block"}
}
if length > 32 {
return nsec, len(msg), &Error{err: "NSEC block too long"}
}
if off+length > len(msg) {
return nsec, len(msg), &Error{err: "overflowing NSEC block"}
}
// Walk the bytes in the window and extract the type bits
for j := 0; j < length; j++ {
b := msg[off+j]
// Check the bits one by one, and set the type
if b&0x80 == 0x80 {
nsec = append(nsec, uint16(window*256+j*8+0))
}
if b&0x40 == 0x40 {
nsec = append(nsec, uint16(window*256+j*8+1))
}
if b&0x20 == 0x20 {
nsec = append(nsec, uint16(window*256+j*8+2))
}
if b&0x10 == 0x10 {
nsec = append(nsec, uint16(window*256+j*8+3))
}
if b&0x8 == 0x8 {
nsec = append(nsec, uint16(window*256+j*8+4))
}
if b&0x4 == 0x4 {
nsec = append(nsec, uint16(window*256+j*8+5))
}
if b&0x2 == 0x2 {
nsec = append(nsec, uint16(window*256+j*8+6))
}
if b&0x1 == 0x1 {
nsec = append(nsec, uint16(window*256+j*8+7))
}
}
off += length
lastwindow = window
}
return nsec, off, nil
}
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
if len(bitmap) == 0 {
return off, nil
}
var lastwindow, lastlength uint16
for j := 0; j < len(bitmap); j++ {
t := bitmap[j]
window := t / 256
length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
off += int(lastlength) + 2
lastlength = 0
}
if window < lastwindow || length < lastlength {
return len(msg), &Error{err: "nsec bits out of order"}
}
if off+2+int(length) > len(msg) {
return len(msg), &Error{err: "overflow packing nsec"}
}
// Setting the window #
msg[off] = byte(window)
// Setting the octets length
msg[off+1] = byte(length)
// Setting the bit value for the type in the right octet
msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
lastwindow, lastlength = window, length
}
off += int(lastlength) + 2
return off, nil
}
func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
var (
servers []string
s string
err error
)
if end > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking domain names"}
}
for off < end {
s, off, err = UnpackDomainName(msg, off)
if err != nil {
return servers, len(msg), err
}
servers = append(servers, s)
}
return servers, off, nil
}
func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
var err error
for j := 0; j < len(names); j++ {
off, err = PackDomainName(names[j], msg, off, compression, false && compress)
if err != nil {
return len(msg), err
}
}
return off, nil
}

13
vendor/github.com/miekg/dns/nsecx.go generated vendored
View file

@ -11,13 +11,12 @@ type saltWireFmt struct {
Salt string `dns:"size-hex"` Salt string `dns:"size-hex"`
} }
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in // HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
// uppercase.
func HashName(label string, ha uint8, iter uint16, salt string) string { func HashName(label string, ha uint8, iter uint16, salt string) string {
saltwire := new(saltWireFmt) saltwire := new(saltWireFmt)
saltwire.Salt = salt saltwire.Salt = salt
wire := make([]byte, DefaultMsgSize) wire := make([]byte, DefaultMsgSize)
n, err := PackStruct(saltwire, wire, 0) n, err := packSaltWire(saltwire, wire)
if err != nil { if err != nil {
return "" return ""
} }
@ -110,3 +109,11 @@ func (rr *NSEC3) Match(name string) bool {
} }
return false return false
} }
func packSaltWire(sw *saltWireFmt, msg []byte) (int, error) {
off, err := packStringHex(sw.Salt, msg, 0)
if err != nil {
return off, err
}
return off, nil
}

View file

@ -33,7 +33,7 @@ type PrivateRR struct {
func mkPrivateRR(rrtype uint16) *PrivateRR { func mkPrivateRR(rrtype uint16) *PrivateRR {
// Panics if RR is not an instance of PrivateRR. // Panics if RR is not an instance of PrivateRR.
rrfunc, ok := typeToRR[rrtype] rrfunc, ok := TypeToRR[rrtype]
if !ok { if !ok {
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype)) panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
} }
@ -43,7 +43,7 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
case *PrivateRR: case *PrivateRR:
return rr return rr
} }
panic(fmt.Sprintf("dns: RR is not a PrivateRR, typeToRR[%d] generator returned %T", rrtype, anyrr)) panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
} }
// Header return the RR header of r. // Header return the RR header of r.
@ -65,29 +65,60 @@ func (r *PrivateRR) copy() RR {
} }
return rr return rr
} }
func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
off, err := r.Hdr.pack(msg, off, compression, compress)
if err != nil {
return off, err
}
headerEnd := off
n, err := r.Data.Pack(msg[off:])
if err != nil {
return len(msg), err
}
off += n
r.Header().Rdlength = uint16(off - headerEnd)
return off, nil
}
// PrivateHandle registers a private resource record type. It requires // PrivateHandle registers a private resource record type. It requires
// string and numeric representation of private RR type and generator function as argument. // string and numeric representation of private RR type and generator function as argument.
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) { func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
rtypestr = strings.ToUpper(rtypestr) rtypestr = strings.ToUpper(rtypestr)
typeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} } TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
TypeToString[rtype] = rtypestr TypeToString[rtype] = rtypestr
StringToType[rtypestr] = rtype StringToType[rtypestr] = rtype
typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
if noRdata(h) {
return &h, off, nil
}
var err error
rr := mkPrivateRR(h.Rrtype)
rr.Hdr = h
off1, err := rr.Data.Unpack(msg[off:])
off += off1
if err != nil {
return rr, off, err
}
return rr, off, err
}
setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := mkPrivateRR(h.Rrtype) rr := mkPrivateRR(h.Rrtype)
rr.Hdr = h rr.Hdr = h
var l lex var l lex
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1 text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
FETCH: Fetch:
for { for {
// TODO(miek): we could also be returning _QUOTE, this might or might not // TODO(miek): we could also be returning _QUOTE, this might or might not
// be an issue (basically parsing TXT becomes hard) // be an issue (basically parsing TXT becomes hard)
switch l = <-c; l.value { switch l = <-c; l.value {
case zNewline, zEOF: case zNewline, zEOF:
break FETCH break Fetch
case zString: case zString:
text = append(text, l.token) text = append(text, l.token)
} }
@ -108,10 +139,11 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
func PrivateHandleRemove(rtype uint16) { func PrivateHandleRemove(rtype uint16) {
rtypestr, ok := TypeToString[rtype] rtypestr, ok := TypeToString[rtype]
if ok { if ok {
delete(typeToRR, rtype) delete(TypeToRR, rtype)
delete(TypeToString, rtype) delete(TypeToString, rtype)
delete(typeToparserFunc, rtype) delete(typeToparserFunc, rtype)
delete(StringToType, rtypestr) delete(StringToType, rtypestr)
delete(typeToUnpack, rtype)
} }
return return
} }

View file

@ -1,52 +1,6 @@
package dns package dns
// These raw* functions do not use reflection, they directly set the values import "encoding/binary"
// in the buffer. There are faster than their reflection counterparts.
// RawSetId sets the message id in buf.
func rawSetId(msg []byte, i uint16) bool {
if len(msg) < 2 {
return false
}
msg[0], msg[1] = packUint16(i)
return true
}
// rawSetQuestionLen sets the length of the question section.
func rawSetQuestionLen(msg []byte, i uint16) bool {
if len(msg) < 6 {
return false
}
msg[4], msg[5] = packUint16(i)
return true
}
// rawSetAnswerLen sets the lenght of the answer section.
func rawSetAnswerLen(msg []byte, i uint16) bool {
if len(msg) < 8 {
return false
}
msg[6], msg[7] = packUint16(i)
return true
}
// rawSetsNsLen sets the lenght of the authority section.
func rawSetNsLen(msg []byte, i uint16) bool {
if len(msg) < 10 {
return false
}
msg[8], msg[9] = packUint16(i)
return true
}
// rawSetExtraLen sets the lenght of the additional section.
func rawSetExtraLen(msg []byte, i uint16) bool {
if len(msg) < 12 {
return false
}
msg[10], msg[11] = packUint16(i)
return true
}
// rawSetRdlength sets the rdlength in the header of // rawSetRdlength sets the rdlength in the header of
// the RR. The offset 'off' must be positioned at the // the RR. The offset 'off' must be positioned at the
@ -90,6 +44,6 @@ Loop:
if rdatalen > 0xFFFF { if rdatalen > 0xFFFF {
return false return false
} }
msg[off], msg[off+1] = packUint16(uint16(rdatalen)) binary.BigEndian.PutUint16(msg[off:], uint16(rdatalen))
return true return true
} }

38
vendor/github.com/miekg/dns/reverse.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
package dns
// StringToType is the reverse of TypeToString, needed for string parsing.
var StringToType = reverseInt16(TypeToString)
// StringToClass is the reverse of ClassToString, needed for string parsing.
var StringToClass = reverseInt16(ClassToString)
// Map of opcodes strings.
var StringToOpcode = reverseInt(OpcodeToString)
// Map of rcodes strings.
var StringToRcode = reverseInt(RcodeToString)
// Reverse a map
func reverseInt8(m map[uint8]string) map[string]uint8 {
n := make(map[string]uint8, len(m))
for u, s := range m {
n[s] = u
}
return n
}
func reverseInt16(m map[uint16]string) map[string]uint16 {
n := make(map[string]uint16, len(m))
for u, s := range m {
n[s] = u
}
return n
}
func reverseInt(m map[int]string) map[string]int {
n := make(map[string]int, len(m))
for u, s := range m {
n[s] = u
}
return n
}

View file

@ -67,7 +67,7 @@ const (
) )
// ParseError is a parsing error. It contains the parse error and the location in the io.Reader // ParseError is a parsing error. It contains the parse error and the location in the io.Reader
// where the error occured. // where the error occurred.
type ParseError struct { type ParseError struct {
file string file string
err string err string
@ -86,7 +86,7 @@ func (e *ParseError) Error() (s string) {
type lex struct { type lex struct {
token string // text of the token token string // text of the token
tokenUpper string // uppercase text of the token tokenUpper string // uppercase text of the token
length int // lenght of the token length int // length of the token
err bool // when true, token text has lexer error err bool // when true, token text has lexer error
value uint8 // value: zString, _BLANK, etc. value uint8 // value: zString, _BLANK, etc.
line int // line in the file line int // line in the file
@ -99,7 +99,7 @@ type lex struct {
type Token struct { type Token struct {
// The scanned resource record when error is not nil. // The scanned resource record when error is not nil.
RR RR
// When an error occured, this has the error specifics. // When an error occurred, this has the error specifics.
Error *ParseError Error *ParseError
// A potential comment positioned after the RR and on the same line. // A potential comment positioned after the RR and on the same line.
Comment string Comment string
@ -144,6 +144,8 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
// //
// for x := range dns.ParseZone(strings.NewReader(z), "", "") { // for x := range dns.ParseZone(strings.NewReader(z), "", "") {
// if x.Error != nil { // if x.Error != nil {
// // log.Println(x.Error)
// } else {
// // Do something with x.RR // // Do something with x.RR
// } // }
// } // }
@ -375,8 +377,8 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}} t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
return return
} }
if e := generate(l, c, t, origin); e != "" { if errMsg := generate(l, c, t, origin); errMsg != "" {
t <- &Token{Error: &ParseError{f, e, l}} t <- &Token{Error: &ParseError{f, errMsg, l}}
return return
} }
st = zExpectOwnerDir st = zExpectOwnerDir
@ -625,6 +627,7 @@ func zlexer(s *scan, c chan lex) {
if stri > 0 { if stri > 0 {
l.value = zString l.value = zString
l.token = string(str[:stri]) l.token = string(str[:stri])
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri l.length = stri
debug.Printf("[4 %+v]", l.token) debug.Printf("[4 %+v]", l.token)
c <- l c <- l
@ -661,6 +664,7 @@ func zlexer(s *scan, c chan lex) {
owner = true owner = true
l.value = zNewline l.value = zNewline
l.token = "\n" l.token = "\n"
l.tokenUpper = l.token
l.length = 1 l.length = 1
l.comment = string(com[:comi]) l.comment = string(com[:comi])
debug.Printf("[3 %+v %+v]", l.token, l.comment) debug.Printf("[3 %+v %+v]", l.token, l.comment)
@ -694,6 +698,7 @@ func zlexer(s *scan, c chan lex) {
} }
l.value = zNewline l.value = zNewline
l.token = "\n" l.token = "\n"
l.tokenUpper = l.token
l.length = 1 l.length = 1
debug.Printf("[1 %+v]", l.token) debug.Printf("[1 %+v]", l.token)
c <- l c <- l
@ -738,6 +743,7 @@ func zlexer(s *scan, c chan lex) {
if stri != 0 { if stri != 0 {
l.value = zString l.value = zString
l.token = string(str[:stri]) l.token = string(str[:stri])
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri l.length = stri
debug.Printf("[%+v]", l.token) debug.Printf("[%+v]", l.token)
@ -748,6 +754,7 @@ func zlexer(s *scan, c chan lex) {
// send quote itself as separate token // send quote itself as separate token
l.value = zQuote l.value = zQuote
l.token = "\"" l.token = "\""
l.tokenUpper = l.token
l.length = 1 l.length = 1
c <- l c <- l
quote = !quote quote = !quote
@ -773,6 +780,7 @@ func zlexer(s *scan, c chan lex) {
brace-- brace--
if brace < 0 { if brace < 0 {
l.token = "extra closing brace" l.token = "extra closing brace"
l.tokenUpper = l.token
l.err = true l.err = true
debug.Printf("[%+v]", l.token) debug.Printf("[%+v]", l.token)
c <- l c <- l
@ -797,6 +805,7 @@ func zlexer(s *scan, c chan lex) {
if stri > 0 { if stri > 0 {
// Send remainder // Send remainder
l.token = string(str[:stri]) l.token = string(str[:stri])
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri l.length = stri
l.value = zString l.value = zString
debug.Printf("[%+v]", l.token) debug.Printf("[%+v]", l.token)
@ -964,8 +973,8 @@ func stringToNodeID(l lex) (uint64, *ParseError) {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
} }
s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19] s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19]
u, e := strconv.ParseUint(s, 16, 64) u, err := strconv.ParseUint(s, 16, 64)
if e != nil { if err != nil {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
} }
return u, nil return u, nil

View file

@ -1443,64 +1443,6 @@ func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, "" return rr, nil, ""
} }
func setWKS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(WKS)
rr.Hdr = h
l := <-c
if l.length == 0 {
return rr, nil, l.comment
}
rr.Address = net.ParseIP(l.token)
if rr.Address == nil || l.err {
return nil, &ParseError{f, "bad WKS Address", l}, ""
}
<-c // zBlank
l = <-c
proto := "tcp"
i, e := strconv.Atoi(l.token)
if e != nil || l.err {
return nil, &ParseError{f, "bad WKS Protocol", l}, ""
}
rr.Protocol = uint8(i)
switch rr.Protocol {
case 17:
proto = "udp"
case 6:
proto = "tcp"
default:
return nil, &ParseError{f, "bad WKS Protocol", l}, ""
}
<-c
l = <-c
rr.BitMap = make([]uint16, 0)
var (
k int
err error
)
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zBlank:
// Ok
case zString:
if k, err = net.LookupPort(proto, l.token); err != nil {
i, e := strconv.Atoi(l.token) // If a number use that
if e != nil {
return nil, &ParseError{f, "bad WKS BitMap", l}, ""
}
rr.BitMap = append(rr.BitMap, uint16(i))
}
rr.BitMap = append(rr.BitMap, uint16(k))
default:
return nil, &ParseError{f, "bad WKS BitMap", l}, ""
}
l = <-c
}
return rr, nil, l.comment
}
func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(SSHFP) rr := new(SSHFP)
rr.Hdr = h rr.Hdr = h
@ -1804,6 +1746,41 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, c1 return rr, nil, c1
} }
func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(SMIMEA)
rr.Hdr = h
l := <-c
if l.length == 0 {
return rr, nil, l.comment
}
i, e := strconv.Atoi(l.token)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA Usage", l}, ""
}
rr.Usage = uint8(i)
<-c // zBlank
l = <-c
i, e = strconv.Atoi(l.token)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA Selector", l}, ""
}
rr.Selector = uint8(i)
<-c // zBlank
l = <-c
i, e = strconv.Atoi(l.token)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, ""
}
rr.MatchingType = uint8(i)
// So this needs be e2 (i.e. different than e), because...??t
s, e2, c1 := endingToString(c, "bad SMIMEA Certificate", f)
if e2 != nil {
return nil, e2, c1
}
rr.Certificate = s
return rr, nil, c1
}
func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(RFC3597) rr := new(RFC3597)
rr.Hdr = h rr.Hdr = h
@ -2103,73 +2080,6 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, "" return rr, nil, ""
} }
func setIPSECKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(IPSECKEY)
rr.Hdr = h
l := <-c
if l.length == 0 {
return rr, nil, l.comment
}
i, err := strconv.Atoi(l.token)
if err != nil || l.err {
return nil, &ParseError{f, "bad IPSECKEY Precedence", l}, ""
}
rr.Precedence = uint8(i)
<-c // zBlank
l = <-c
i, err = strconv.Atoi(l.token)
if err != nil || l.err {
return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
}
rr.GatewayType = uint8(i)
<-c // zBlank
l = <-c
i, err = strconv.Atoi(l.token)
if err != nil || l.err {
return nil, &ParseError{f, "bad IPSECKEY Algorithm", l}, ""
}
rr.Algorithm = uint8(i)
// Now according to GatewayType we can have different elements here
<-c // zBlank
l = <-c
switch rr.GatewayType {
case 0:
fallthrough
case 3:
rr.GatewayName = l.token
if l.token == "@" {
rr.GatewayName = o
}
_, ok := IsDomainName(l.token)
if !ok || l.length == 0 || l.err {
return nil, &ParseError{f, "bad IPSECKEY GatewayName", l}, ""
}
if rr.GatewayName[l.length-1] != '.' {
rr.GatewayName = appendOrigin(rr.GatewayName, o)
}
case 1:
rr.GatewayA = net.ParseIP(l.token)
if rr.GatewayA == nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayA", l}, ""
}
case 2:
rr.GatewayAAAA = net.ParseIP(l.token)
if rr.GatewayAAAA == nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayAAAA", l}, ""
}
default:
return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
}
s, e, c1 := endingToString(c, "bad IPSECKEY PublicKey", f)
if e != nil {
return nil, e, c1
}
rr.PublicKey = s
return rr, nil, c1
}
func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(CAA) rr := new(CAA)
rr.Hdr = h rr.Hdr = h
@ -2203,68 +2113,67 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
} }
var typeToparserFunc = map[uint16]parserFunc{ var typeToparserFunc = map[uint16]parserFunc{
TypeAAAA: parserFunc{setAAAA, false}, TypeAAAA: {setAAAA, false},
TypeAFSDB: parserFunc{setAFSDB, false}, TypeAFSDB: {setAFSDB, false},
TypeA: parserFunc{setA, false}, TypeA: {setA, false},
TypeCAA: parserFunc{setCAA, true}, TypeCAA: {setCAA, true},
TypeCDS: parserFunc{setCDS, true}, TypeCDS: {setCDS, true},
TypeCDNSKEY: parserFunc{setCDNSKEY, true}, TypeCDNSKEY: {setCDNSKEY, true},
TypeCERT: parserFunc{setCERT, true}, TypeCERT: {setCERT, true},
TypeCNAME: parserFunc{setCNAME, false}, TypeCNAME: {setCNAME, false},
TypeDHCID: parserFunc{setDHCID, true}, TypeDHCID: {setDHCID, true},
TypeDLV: parserFunc{setDLV, true}, TypeDLV: {setDLV, true},
TypeDNAME: parserFunc{setDNAME, false}, TypeDNAME: {setDNAME, false},
TypeKEY: parserFunc{setKEY, true}, TypeKEY: {setKEY, true},
TypeDNSKEY: parserFunc{setDNSKEY, true}, TypeDNSKEY: {setDNSKEY, true},
TypeDS: parserFunc{setDS, true}, TypeDS: {setDS, true},
TypeEID: parserFunc{setEID, true}, TypeEID: {setEID, true},
TypeEUI48: parserFunc{setEUI48, false}, TypeEUI48: {setEUI48, false},
TypeEUI64: parserFunc{setEUI64, false}, TypeEUI64: {setEUI64, false},
TypeGID: parserFunc{setGID, false}, TypeGID: {setGID, false},
TypeGPOS: parserFunc{setGPOS, false}, TypeGPOS: {setGPOS, false},
TypeHINFO: parserFunc{setHINFO, true}, TypeHINFO: {setHINFO, true},
TypeHIP: parserFunc{setHIP, true}, TypeHIP: {setHIP, true},
TypeIPSECKEY: parserFunc{setIPSECKEY, true}, TypeKX: {setKX, false},
TypeKX: parserFunc{setKX, false}, TypeL32: {setL32, false},
TypeL32: parserFunc{setL32, false}, TypeL64: {setL64, false},
TypeL64: parserFunc{setL64, false}, TypeLOC: {setLOC, true},
TypeLOC: parserFunc{setLOC, true}, TypeLP: {setLP, false},
TypeLP: parserFunc{setLP, false}, TypeMB: {setMB, false},
TypeMB: parserFunc{setMB, false}, TypeMD: {setMD, false},
TypeMD: parserFunc{setMD, false}, TypeMF: {setMF, false},
TypeMF: parserFunc{setMF, false}, TypeMG: {setMG, false},
TypeMG: parserFunc{setMG, false}, TypeMINFO: {setMINFO, false},
TypeMINFO: parserFunc{setMINFO, false}, TypeMR: {setMR, false},
TypeMR: parserFunc{setMR, false}, TypeMX: {setMX, false},
TypeMX: parserFunc{setMX, false}, TypeNAPTR: {setNAPTR, false},
TypeNAPTR: parserFunc{setNAPTR, false}, TypeNID: {setNID, false},
TypeNID: parserFunc{setNID, false}, TypeNIMLOC: {setNIMLOC, true},
TypeNIMLOC: parserFunc{setNIMLOC, true}, TypeNINFO: {setNINFO, true},
TypeNINFO: parserFunc{setNINFO, true}, TypeNSAPPTR: {setNSAPPTR, false},
TypeNSAPPTR: parserFunc{setNSAPPTR, false}, TypeNSEC3PARAM: {setNSEC3PARAM, false},
TypeNSEC3PARAM: parserFunc{setNSEC3PARAM, false}, TypeNSEC3: {setNSEC3, true},
TypeNSEC3: parserFunc{setNSEC3, true}, TypeNSEC: {setNSEC, true},
TypeNSEC: parserFunc{setNSEC, true}, TypeNS: {setNS, false},
TypeNS: parserFunc{setNS, false}, TypeOPENPGPKEY: {setOPENPGPKEY, true},
TypeOPENPGPKEY: parserFunc{setOPENPGPKEY, true}, TypePTR: {setPTR, false},
TypePTR: parserFunc{setPTR, false}, TypePX: {setPX, false},
TypePX: parserFunc{setPX, false}, TypeSIG: {setSIG, true},
TypeSIG: parserFunc{setSIG, true}, TypeRKEY: {setRKEY, true},
TypeRKEY: parserFunc{setRKEY, true}, TypeRP: {setRP, false},
TypeRP: parserFunc{setRP, false}, TypeRRSIG: {setRRSIG, true},
TypeRRSIG: parserFunc{setRRSIG, true}, TypeRT: {setRT, false},
TypeRT: parserFunc{setRT, false}, TypeSMIMEA: {setSMIMEA, true},
TypeSOA: parserFunc{setSOA, false}, TypeSOA: {setSOA, false},
TypeSPF: parserFunc{setSPF, true}, TypeSPF: {setSPF, true},
TypeSRV: parserFunc{setSRV, false}, TypeSRV: {setSRV, false},
TypeSSHFP: parserFunc{setSSHFP, true}, TypeSSHFP: {setSSHFP, true},
TypeTALINK: parserFunc{setTALINK, false}, TypeTALINK: {setTALINK, false},
TypeTA: parserFunc{setTA, true}, TypeTA: {setTA, true},
TypeTLSA: parserFunc{setTLSA, true}, TypeTLSA: {setTLSA, true},
TypeTXT: parserFunc{setTXT, true}, TypeTXT: {setTXT, true},
TypeUID: parserFunc{setUID, false}, TypeUID: {setUID, false},
TypeUINFO: parserFunc{setUINFO, true}, TypeUINFO: {setUINFO, true},
TypeURI: parserFunc{setURI, true}, TypeURI: {setURI, true},
TypeWKS: parserFunc{setWKS, true}, TypeX25: {setX25, false},
TypeX25: parserFunc{setX25, false},
} }

234
vendor/github.com/miekg/dns/server.go generated vendored
View file

@ -4,6 +4,8 @@ package dns
import ( import (
"bytes" "bytes"
"crypto/tls"
"encoding/binary"
"io" "io"
"net" "net"
"sync" "sync"
@ -47,7 +49,7 @@ type response struct {
tsigRequestMAC string tsigRequestMAC string
tsigSecret map[string]string // the tsig secrets tsigSecret map[string]string // the tsig secrets
udp *net.UDPConn // i/o connection if UDP was used udp *net.UDPConn // i/o connection if UDP was used
tcp *net.TCPConn // i/o connection if TCP was used tcp net.Conn // i/o connection if TCP was used
udpSession *SessionUDP // oob data to get egress interface right udpSession *SessionUDP // oob data to get egress interface right
remoteAddr net.Addr // address of the client remoteAddr net.Addr // address of the client
writer Writer // writer to output the raw DNS bits writer Writer // writer to output the raw DNS bits
@ -92,13 +94,35 @@ func HandleFailed(w ResponseWriter, r *Msg) {
func failedHandler() Handler { return HandlerFunc(HandleFailed) } func failedHandler() Handler { return HandlerFunc(HandleFailed) }
// ListenAndServe Starts a server on addresss and network speficied. Invoke handler // ListenAndServe Starts a server on address and network specified Invoke handler
// for incoming queries. // for incoming queries.
func ListenAndServe(addr string, network string, handler Handler) error { func ListenAndServe(addr string, network string, handler Handler) error {
server := &Server{Addr: addr, Net: network, Handler: handler} server := &Server{Addr: addr, Net: network, Handler: handler}
return server.ListenAndServe() return server.ListenAndServe()
} }
// ListenAndServeTLS acts like http.ListenAndServeTLS, more information in
// http://golang.org/pkg/net/http/#ListenAndServeTLS
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return err
}
config := tls.Config{
Certificates: []tls.Certificate{cert},
}
server := &Server{
Addr: addr,
Net: "tcp-tls",
TLSConfig: &config,
Handler: handler,
}
return server.ListenAndServe()
}
// ActivateAndServe activates a server with a listener from systemd, // ActivateAndServe activates a server with a listener from systemd,
// l and p should not both be non-nil. // l and p should not both be non-nil.
// If both l and p are not nil only p will be used. // If both l and p are not nil only p will be used.
@ -123,7 +147,7 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
b[i] |= ('a' - 'A') b[i] |= ('a' - 'A')
} }
} }
if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key if h, ok := mux.z[string(b[:l])]; ok { // causes garbage, might want to change the map key
if t != TypeDS { if t != TypeDS {
return h return h
} }
@ -210,7 +234,7 @@ type Writer interface {
type Reader interface { type Reader interface {
// ReadTCP reads a raw message from a TCP connection. Implementations may alter // ReadTCP reads a raw message from a TCP connection. Implementations may alter
// connection properties, for example the read-deadline. // connection properties, for example the read-deadline.
ReadTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
// ReadUDP reads a raw message from a UDP connection. Implementations may alter // ReadUDP reads a raw message from a UDP connection. Implementations may alter
// connection properties, for example the read-deadline. // connection properties, for example the read-deadline.
ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
@ -222,7 +246,7 @@ type defaultReader struct {
*Server *Server
} }
func (dr *defaultReader) ReadTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) { func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
return dr.readTCP(conn, timeout) return dr.readTCP(conn, timeout)
} }
@ -242,10 +266,12 @@ type DecorateWriter func(Writer) Writer
type Server struct { type Server struct {
// Address to listen on, ":dns" if empty. // Address to listen on, ":dns" if empty.
Addr string Addr string
// if "tcp" it will invoke a TCP listener, otherwise an UDP one. // if "tcp" or "tcp-tls" (DNS over TLS) it will invoke a TCP listener, otherwise an UDP one
Net string Net string
// TCP Listener to use, this is to aid in systemd's socket activation. // TCP Listener to use, this is to aid in systemd's socket activation.
Listener net.Listener Listener net.Listener
// TLS connection configuration
TLSConfig *tls.Config
// UDP "Listener" to use, this is to aid in systemd's socket activation. // UDP "Listener" to use, this is to aid in systemd's socket activation.
PacketConn net.PacketConn PacketConn net.PacketConn
// Handler to invoke, dns.DefaultServeMux if nil. // Handler to invoke, dns.DefaultServeMux if nil.
@ -262,7 +288,7 @@ type Server struct {
// Secret(s) for Tsig map[<zonename>]<base64 secret>. // Secret(s) for Tsig map[<zonename>]<base64 secret>.
TsigSecret map[string]string TsigSecret map[string]string
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to // Unsafe instructs the server to disregard any sanity checks and directly hand the message to
// the handler. It will specfically not check if the query has the QR bit not set. // the handler. It will specifically not check if the query has the QR bit not set.
Unsafe bool Unsafe bool
// If NotifyStartedFunc is set it is called once the server has started listening. // If NotifyStartedFunc is set it is called once the server has started listening.
NotifyStartedFunc func() NotifyStartedFunc func()
@ -271,26 +297,21 @@ type Server struct {
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages. // DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
DecorateWriter DecorateWriter DecorateWriter DecorateWriter
// For graceful shutdown. // Graceful shutdown handling
stopUDP chan bool
stopTCP chan bool
wgUDP sync.WaitGroup
wgTCP sync.WaitGroup
// make start/shutdown not racy inFlight sync.WaitGroup
lock sync.Mutex
lock sync.RWMutex
started bool started bool
} }
// ListenAndServe starts a nameserver on the configured address in *Server. // ListenAndServe starts a nameserver on the configured address in *Server.
func (srv *Server) ListenAndServe() error { func (srv *Server) ListenAndServe() error {
srv.lock.Lock() srv.lock.Lock()
defer srv.lock.Unlock()
if srv.started { if srv.started {
srv.lock.Unlock()
return &Error{err: "server already started"} return &Error{err: "server already started"}
} }
srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
srv.started = true
addr := srv.Addr addr := srv.Addr
if addr == "" { if addr == "" {
addr = ":domain" addr = ":domain"
@ -300,34 +321,57 @@ func (srv *Server) ListenAndServe() error {
} }
switch srv.Net { switch srv.Net {
case "tcp", "tcp4", "tcp6": case "tcp", "tcp4", "tcp6":
a, e := net.ResolveTCPAddr(srv.Net, addr) a, err := net.ResolveTCPAddr(srv.Net, addr)
if e != nil { if err != nil {
return e return err
} }
l, e := net.ListenTCP(srv.Net, a) l, err := net.ListenTCP(srv.Net, a)
if e != nil { if err != nil {
return e return err
} }
srv.Listener = l srv.Listener = l
srv.started = true
srv.lock.Unlock() srv.lock.Unlock()
return srv.serveTCP(l) err = srv.serveTCP(l)
case "udp", "udp4", "udp6": srv.lock.Lock() // to satisfy the defer at the top
a, e := net.ResolveUDPAddr(srv.Net, addr) return err
if e != nil { case "tcp-tls", "tcp4-tls", "tcp6-tls":
return e network := "tcp"
if srv.Net == "tcp4-tls" {
network = "tcp4"
} else if srv.Net == "tcp6" {
network = "tcp6"
} }
l, e := net.ListenUDP(srv.Net, a)
if e != nil { l, err := tls.Listen(network, addr, srv.TLSConfig)
return e if err != nil {
return err
}
srv.Listener = l
srv.started = true
srv.lock.Unlock()
err = srv.serveTCP(l)
srv.lock.Lock() // to satisfy the defer at the top
return err
case "udp", "udp4", "udp6":
a, err := net.ResolveUDPAddr(srv.Net, addr)
if err != nil {
return err
}
l, err := net.ListenUDP(srv.Net, a)
if err != nil {
return err
} }
if e := setUDPSocketOptions(l); e != nil { if e := setUDPSocketOptions(l); e != nil {
return e return e
} }
srv.PacketConn = l srv.PacketConn = l
srv.started = true
srv.lock.Unlock() srv.lock.Unlock()
return srv.serveUDP(l) err = srv.serveUDP(l)
srv.lock.Lock() // to satisfy the defer at the top
return err
} }
srv.lock.Unlock()
return &Error{err: "bad network"} return &Error{err: "bad network"}
} }
@ -335,15 +379,12 @@ func (srv *Server) ListenAndServe() error {
// configured in *Server. Its main use is to start a server from systemd. // configured in *Server. Its main use is to start a server from systemd.
func (srv *Server) ActivateAndServe() error { func (srv *Server) ActivateAndServe() error {
srv.lock.Lock() srv.lock.Lock()
defer srv.lock.Unlock()
if srv.started { if srv.started {
srv.lock.Unlock()
return &Error{err: "server already started"} return &Error{err: "server already started"}
} }
srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
srv.started = true
pConn := srv.PacketConn pConn := srv.PacketConn
l := srv.Listener l := srv.Listener
srv.lock.Unlock()
if pConn != nil { if pConn != nil {
if srv.UDPSize == 0 { if srv.UDPSize == 0 {
srv.UDPSize = MinMsgSize srv.UDPSize = MinMsgSize
@ -352,13 +393,19 @@ func (srv *Server) ActivateAndServe() error {
if e := setUDPSocketOptions(t); e != nil { if e := setUDPSocketOptions(t); e != nil {
return e return e
} }
return srv.serveUDP(t) srv.started = true
srv.lock.Unlock()
e := srv.serveUDP(t)
srv.lock.Lock() // to satisfy the defer at the top
return e
} }
} }
if l != nil { if l != nil {
if t, ok := l.(*net.TCPListener); ok { srv.started = true
return srv.serveTCP(t) srv.lock.Unlock()
} e := srv.serveTCP(l)
srv.lock.Lock() // to satisfy the defer at the top
return e
} }
return &Error{err: "bad listeners"} return &Error{err: "bad listeners"}
} }
@ -374,36 +421,20 @@ func (srv *Server) Shutdown() error {
return &Error{err: "server not started"} return &Error{err: "server not started"}
} }
srv.started = false srv.started = false
net, addr := srv.Net, srv.Addr
switch {
case srv.Listener != nil:
a := srv.Listener.Addr()
net, addr = a.Network(), a.String()
case srv.PacketConn != nil:
a := srv.PacketConn.LocalAddr()
net, addr = a.Network(), a.String()
}
srv.lock.Unlock() srv.lock.Unlock()
fin := make(chan bool) if srv.PacketConn != nil {
switch net { srv.PacketConn.Close()
case "tcp", "tcp4", "tcp6": }
go func() { if srv.Listener != nil {
srv.stopTCP <- true srv.Listener.Close()
srv.wgTCP.Wait()
fin <- true
}()
case "udp", "udp4", "udp6":
go func() {
srv.stopUDP <- true
srv.wgUDP.Wait()
fin <- true
}()
} }
c := &Client{Net: net} fin := make(chan bool)
go c.Exchange(new(Msg), addr) // extra query to help ReadXXX loop to pass go func() {
srv.inFlight.Wait()
fin <- true
}()
select { select {
case <-time.After(srv.getReadTimeout()): case <-time.After(srv.getReadTimeout()):
@ -424,7 +455,7 @@ func (srv *Server) getReadTimeout() time.Duration {
// serveTCP starts a TCP listener for the server. // serveTCP starts a TCP listener for the server.
// Each request is handled in a separate goroutine. // Each request is handled in a separate goroutine.
func (srv *Server) serveTCP(l *net.TCPListener) error { func (srv *Server) serveTCP(l net.Listener) error {
defer l.Close() defer l.Close()
if srv.NotifyStartedFunc != nil { if srv.NotifyStartedFunc != nil {
@ -443,20 +474,24 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
rtimeout := srv.getReadTimeout() rtimeout := srv.getReadTimeout()
// deadline is not used here // deadline is not used here
for { for {
rw, e := l.AcceptTCP() rw, err := l.Accept()
if e != nil { if err != nil {
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
continue continue
} }
m, e := reader.ReadTCP(rw, rtimeout) return err
select { }
case <-srv.stopTCP: m, err := reader.ReadTCP(rw, rtimeout)
srv.lock.RLock()
if !srv.started {
srv.lock.RUnlock()
return nil return nil
default:
} }
if e != nil { srv.lock.RUnlock()
if err != nil {
continue continue
} }
srv.wgTCP.Add(1) srv.inFlight.Add(1)
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw) go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
} }
} }
@ -482,22 +517,25 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
rtimeout := srv.getReadTimeout() rtimeout := srv.getReadTimeout()
// deadline is not used here // deadline is not used here
for { for {
m, s, e := reader.ReadUDP(l, rtimeout) m, s, err := reader.ReadUDP(l, rtimeout)
select { srv.lock.RLock()
case <-srv.stopUDP: if !srv.started {
srv.lock.RUnlock()
return nil return nil
default:
} }
if e != nil { srv.lock.RUnlock()
if err != nil {
continue continue
} }
srv.wgUDP.Add(1) srv.inFlight.Add(1)
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil) go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
} }
} }
// Serve a new connection. // Serve a new connection.
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t *net.TCPConn) { func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
defer srv.inFlight.Done()
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s} w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
if srv.DecorateWriter != nil { if srv.DecorateWriter != nil {
w.writer = srv.DecorateWriter(w) w.writer = srv.DecorateWriter(w)
@ -507,15 +545,6 @@ func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *Ses
q := 0 // counter for the amount of TCP queries we get q := 0 // counter for the amount of TCP queries we get
defer func() {
if u != nil {
srv.wgUDP.Done()
}
if t != nil {
srv.wgTCP.Done()
}
}()
reader := Reader(&defaultReader{srv}) reader := Reader(&defaultReader{srv})
if srv.DecorateReader != nil { if srv.DecorateReader != nil {
reader = srv.DecorateReader(reader) reader = srv.DecorateReader(reader)
@ -548,6 +577,9 @@ Redo:
h.ServeDNS(w, req) // Writes back to the client h.ServeDNS(w, req) // Writes back to the client
Exit: Exit:
if w.tcp == nil {
return
}
// TODO(miek): make this number configurable? // TODO(miek): make this number configurable?
if q > maxTCPQueries { // close socket after this many queries if q > maxTCPQueries { // close socket after this many queries
w.Close() w.Close()
@ -565,8 +597,8 @@ Exit:
if srv.IdleTimeout != nil { if srv.IdleTimeout != nil {
idleTimeout = srv.IdleTimeout() idleTimeout = srv.IdleTimeout()
} }
m, e := reader.ReadTCP(w.tcp, idleTimeout) m, err = reader.ReadTCP(w.tcp, idleTimeout)
if e == nil { if err == nil {
q++ q++
goto Redo goto Redo
} }
@ -574,7 +606,7 @@ Exit:
return return
} }
func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) { func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
conn.SetReadDeadline(time.Now().Add(timeout)) conn.SetReadDeadline(time.Now().Add(timeout))
l := make([]byte, 2) l := make([]byte, 2)
n, err := conn.Read(l) n, err := conn.Read(l)
@ -584,7 +616,7 @@ func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, er
} }
return nil, ErrShortRead return nil, ErrShortRead
} }
length, _ := unpackUint16(l, 0) length := binary.BigEndian.Uint16(l)
if length == 0 { if length == 0 {
return nil, ErrShortRead return nil, ErrShortRead
} }
@ -612,10 +644,10 @@ func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, er
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
conn.SetReadDeadline(time.Now().Add(timeout)) conn.SetReadDeadline(time.Now().Add(timeout))
m := make([]byte, srv.UDPSize) m := make([]byte, srv.UDPSize)
n, s, e := ReadFromSessionUDP(conn, m) n, s, err := ReadFromSessionUDP(conn, m)
if e != nil || n == 0 { if err != nil || n == 0 {
if e != nil { if err != nil {
return nil, nil, e return nil, nil, err
} }
return nil, nil, ErrShortRead return nil, nil, ErrShortRead
} }
@ -659,7 +691,7 @@ func (w *response) Write(m []byte) (int, error) {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, 2+lm) l := make([]byte, 2, 2+lm)
l[0], l[1] = packUint16(uint16(lm)) binary.BigEndian.PutUint16(l, uint16(lm))
m = append(l, m...) m = append(l, m...)
n, err := io.Copy(w.tcp, bytes.NewReader(m)) n, err := io.Copy(w.tcp, bytes.NewReader(m))

25
vendor/github.com/miekg/dns/sig0.go generated vendored
View file

@ -5,6 +5,7 @@ import (
"crypto/dsa" "crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"encoding/binary"
"math/big" "math/big"
"strings" "strings"
"time" "time"
@ -67,13 +68,13 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
} }
// Adjust sig data length // Adjust sig data length
rdoff := len(mbuf) + 1 + 2 + 2 + 4 rdoff := len(mbuf) + 1 + 2 + 2 + 4
rdlen, _ := unpackUint16(buf, rdoff) rdlen := binary.BigEndian.Uint16(buf[rdoff:])
rdlen += uint16(len(sig)) rdlen += uint16(len(sig))
buf[rdoff], buf[rdoff+1] = packUint16(rdlen) binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
// Adjust additional count // Adjust additional count
adc, _ := unpackUint16(buf, 10) adc := binary.BigEndian.Uint16(buf[10:])
adc++ adc++
buf[10], buf[11] = packUint16(adc) binary.BigEndian.PutUint16(buf[10:], adc)
return buf, nil return buf, nil
} }
@ -103,10 +104,11 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
hasher := hash.New() hasher := hash.New()
buflen := len(buf) buflen := len(buf)
qdc, _ := unpackUint16(buf, 4) qdc := binary.BigEndian.Uint16(buf[4:])
anc, _ := unpackUint16(buf, 6) anc := binary.BigEndian.Uint16(buf[6:])
auc, _ := unpackUint16(buf, 8) auc := binary.BigEndian.Uint16(buf[8:])
adc, offset := unpackUint16(buf, 10) adc := binary.BigEndian.Uint16(buf[10:])
offset := 12
var err error var err error
for i := uint16(0); i < qdc && offset < buflen; i++ { for i := uint16(0); i < qdc && offset < buflen; i++ {
_, offset, err = UnpackDomainName(buf, offset) _, offset, err = UnpackDomainName(buf, offset)
@ -127,7 +129,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
continue continue
} }
var rdlen uint16 var rdlen uint16
rdlen, offset = unpackUint16(buf, offset) rdlen = binary.BigEndian.Uint16(buf[offset:])
offset += 2
offset += int(rdlen) offset += int(rdlen)
} }
if offset >= buflen { if offset >= buflen {
@ -149,9 +152,9 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
if offset+4+4 >= buflen { if offset+4+4 >= buflen {
return &Error{err: "overflow unpacking signed message"} return &Error{err: "overflow unpacking signed message"}
} }
expire := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3]) expire := binary.BigEndian.Uint32(buf[offset:])
offset += 4 offset += 4
incept := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3]) incept := binary.BigEndian.Uint32(buf[offset:])
offset += 4 offset += 4
now := uint32(time.Now().Unix()) now := uint32(time.Now().Unix())
if now < incept || now > expire { if now < incept || now > expire {

47
vendor/github.com/miekg/dns/smimea.go generated vendored Normal file
View file

@ -0,0 +1,47 @@
package dns
import (
"crypto/sha256"
"crypto/x509"
"encoding/hex"
)
// Sign creates a SMIMEA record from an SSL certificate.
func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
r.Hdr.Rrtype = TypeSMIMEA
r.Usage = uint8(usage)
r.Selector = uint8(selector)
r.MatchingType = uint8(matchingType)
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
if err != nil {
return err
}
return nil
}
// Verify verifies a SMIMEA record against an SSL certificate. If it is OK
// a nil error is returned.
func (r *SMIMEA) 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?
}
// SIMEAName returns the ownername of a SMIMEA resource record as per the
// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
func SMIMEAName(email_address string, domain_name string) (string, error) {
hasher := sha256.New()
hasher.Write([]byte(email_address))
// RFC Section 3: "The local-part is hashed using the SHA2-256
// algorithm with the hash truncated to 28 octets and
// represented in its hexadecimal representation to become the
// left-most label in the prepared domain name"
return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain_name, nil
}

47
vendor/github.com/miekg/dns/tlsa.go generated vendored
View file

@ -1,50 +1,11 @@
package dns package dns
import ( import (
"crypto/sha256"
"crypto/sha512"
"crypto/x509" "crypto/x509"
"encoding/hex"
"errors"
"io"
"net" "net"
"strconv" "strconv"
) )
// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
switch matchingType {
case 0:
switch selector {
case 0:
return hex.EncodeToString(cert.Raw), nil
case 1:
return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
}
case 1:
h := sha256.New()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
return hex.EncodeToString(h.Sum(nil)), nil
}
case 2:
h := sha512.New()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
return hex.EncodeToString(h.Sum(nil)), nil
}
}
return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
}
// Sign creates a TLSA record from an SSL certificate. // Sign creates a TLSA record from an SSL certificate.
func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) { func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
r.Hdr.Rrtype = TypeTLSA r.Hdr.Rrtype = TypeTLSA
@ -78,9 +39,9 @@ func TLSAName(name, service, network string) (string, error) {
if !IsFqdn(name) { if !IsFqdn(name) {
return "", ErrFqdn return "", ErrFqdn
} }
p, e := net.LookupPort(network, service) p, err := net.LookupPort(network, service)
if e != nil { if err != nil {
return "", e return "", err
} }
return "_" + strconv.Itoa(p) + "_" + network + "." + name, nil return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
} }

165
vendor/github.com/miekg/dns/tsig.go generated vendored
View file

@ -6,6 +6,7 @@ import (
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"encoding/binary"
"encoding/hex" "encoding/hex"
"hash" "hash"
"io" "io"
@ -30,15 +31,11 @@ type TSIG struct {
TimeSigned uint64 `dns:"uint48"` TimeSigned uint64 `dns:"uint48"`
Fudge uint16 Fudge uint16
MACSize uint16 MACSize uint16
MAC string `dns:"size-hex"` MAC string `dns:"size-hex:MACSize"`
OrigId uint16 OrigId uint16
Error uint16 Error uint16
OtherLen uint16 OtherLen uint16
OtherData string `dns:"size-hex"` OtherData string `dns:"size-hex:OtherLen"`
}
func (rr *TSIG) Header() *RR_Header {
return &rr.Hdr
} }
// TSIG has no official presentation format, but this will suffice. // TSIG has no official presentation format, but this will suffice.
@ -58,15 +55,6 @@ func (rr *TSIG) String() string {
return s return s
} }
func (rr *TSIG) len() int {
return rr.Hdr.len() + len(rr.Algorithm) + 1 + 6 +
4 + len(rr.MAC)/2 + 1 + 6 + len(rr.OtherData)/2 + 1
}
func (rr *TSIG) copy() RR {
return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
}
// The following values must be put in wireformat, so that the MAC can be calculated. // The following values must be put in wireformat, so that the MAC can be calculated.
// RFC 2845, section 3.4.2. TSIG Variables. // RFC 2845, section 3.4.2. TSIG Variables.
type tsigWireFmt struct { type tsigWireFmt struct {
@ -81,14 +69,13 @@ type tsigWireFmt struct {
// MACSize, MAC and OrigId excluded // MACSize, MAC and OrigId excluded
Error uint16 Error uint16
OtherLen uint16 OtherLen uint16
OtherData string `dns:"size-hex"` OtherData string `dns:"size-hex:OtherLen"`
} }
// If we have the MAC use this type to convert it to wiredata. // If we have the MAC use this type to convert it to wiredata. Section 3.4.3. Request MAC
// Section 3.4.3. Request MAC
type macWireFmt struct { type macWireFmt struct {
MACSize uint16 MACSize uint16
MAC string `dns:"size-hex"` MAC string `dns:"size-hex:MACSize"`
} }
// 3.3. Time values used in TSIG calculations // 3.3. Time values used in TSIG calculations
@ -125,7 +112,7 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
t := new(TSIG) t := new(TSIG)
var h hash.Hash var h hash.Hash
switch rr.Algorithm { switch strings.ToLower(rr.Algorithm) {
case HmacMD5: case HmacMD5:
h = hmac.New(md5.New, []byte(rawsecret)) h = hmac.New(md5.New, []byte(rawsecret))
case HmacSHA1: case HmacSHA1:
@ -154,7 +141,9 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
return nil, "", err return nil, "", err
} }
mbuf = append(mbuf, tbuf...) mbuf = append(mbuf, tbuf...)
rawSetExtraLen(mbuf, uint16(len(m.Extra)+1)) // Update the ArCount directly in the buffer.
binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
return mbuf, t.MAC, nil return mbuf, t.MAC, nil
} }
@ -191,7 +180,7 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
} }
var h hash.Hash var h hash.Hash
switch tsig.Algorithm { switch strings.ToLower(tsig.Algorithm) {
case HmacMD5: case HmacMD5:
h = hmac.New(md5.New, rawsecret) h = hmac.New(md5.New, rawsecret)
case HmacSHA1: case HmacSHA1:
@ -225,7 +214,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
m.MACSize = uint16(len(requestMAC) / 2) m.MACSize = uint16(len(requestMAC) / 2)
m.MAC = requestMAC m.MAC = requestMAC
buf = make([]byte, len(requestMAC)) // long enough buf = make([]byte, len(requestMAC)) // long enough
n, _ := PackStruct(m, buf, 0) n, _ := packMacWire(m, buf)
buf = buf[:n] buf = buf[:n]
} }
@ -234,7 +223,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
tsig := new(timerWireFmt) tsig := new(timerWireFmt)
tsig.TimeSigned = rr.TimeSigned tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge tsig.Fudge = rr.Fudge
n, _ := PackStruct(tsig, tsigvar, 0) n, _ := packTimerWire(tsig, tsigvar)
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} else { } else {
tsig := new(tsigWireFmt) tsig := new(tsigWireFmt)
@ -247,7 +236,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
tsig.Error = rr.Error tsig.Error = rr.Error
tsig.OtherLen = rr.OtherLen tsig.OtherLen = rr.OtherLen
tsig.OtherData = rr.OtherData tsig.OtherData = rr.OtherData
n, _ := PackStruct(tsig, tsigvar, 0) n, _ := packTsigWire(tsig, tsigvar)
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} }
@ -262,60 +251,54 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
// Strip the TSIG from the raw message. // Strip the TSIG from the raw message.
func stripTsig(msg []byte) ([]byte, *TSIG, error) { func stripTsig(msg []byte) ([]byte, *TSIG, error) {
// Copied from msg.go's Unpack() // Copied from msg.go's Unpack() Header, but modified.
// Header. var (
var dh Header dh Header
var err error err error
dns := new(Msg) )
rr := new(TSIG) off, tsigoff := 0, 0
off := 0
tsigoff := 0 if dh, off, err = unpackMsgHdr(msg, off); err != nil {
if off, err = UnpackStruct(&dh, msg, off); err != nil {
return nil, nil, err return nil, nil, err
} }
if dh.Arcount == 0 { if dh.Arcount == 0 {
return nil, nil, ErrNoSig return nil, nil, ErrNoSig
} }
// Rcode, see msg.go Unpack() // Rcode, see msg.go Unpack()
if int(dh.Bits&0xF) == RcodeNotAuth { if int(dh.Bits&0xF) == RcodeNotAuth {
return nil, nil, ErrAuth return nil, nil, ErrAuth
} }
// Arrays. for i := 0; i < int(dh.Qdcount); i++ {
dns.Question = make([]Question, dh.Qdcount) _, off, err = unpackQuestion(msg, off)
dns.Answer = make([]RR, dh.Ancount) if err != nil {
dns.Ns = make([]RR, dh.Nscount) return nil, nil, err
dns.Extra = make([]RR, dh.Arcount) }
}
for i := 0; i < len(dns.Question); i++ { _, off, err = unpackRRslice(int(dh.Ancount), msg, off)
off, err = UnpackStruct(&dns.Question[i], msg, off)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
} _, off, err = unpackRRslice(int(dh.Nscount), msg, off)
for i := 0; i < len(dns.Answer); i++ {
dns.Answer[i], off, err = UnpackRR(msg, off)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
}
for i := 0; i < len(dns.Ns); i++ { rr := new(TSIG)
dns.Ns[i], off, err = UnpackRR(msg, off) var extra RR
if err != nil { for i := 0; i < int(dh.Arcount); i++ {
return nil, nil, err
}
}
for i := 0; i < len(dns.Extra); i++ {
tsigoff = off tsigoff = off
dns.Extra[i], off, err = UnpackRR(msg, off) extra, off, err = UnpackRR(msg, off)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if dns.Extra[i].Header().Rrtype == TypeTSIG { if extra.Header().Rrtype == TypeTSIG {
rr = dns.Extra[i].(*TSIG) rr = extra.(*TSIG)
// Adjust Arcount. // Adjust Arcount.
arcount, _ := unpackUint16(msg, 10) arcount := binary.BigEndian.Uint16(msg[10:])
msg[10], msg[11] = packUint16(arcount - 1) binary.BigEndian.PutUint16(msg[10:], arcount-1)
break break
} }
} }
@ -331,3 +314,71 @@ func tsigTimeToString(t uint64) string {
ti := time.Unix(int64(t), 0).UTC() ti := time.Unix(int64(t), 0).UTC()
return ti.Format("20060102150405") 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
}

569
vendor/github.com/miekg/dns/types.go generated vendored

File diff suppressed because it is too large Load diff

271
vendor/github.com/miekg/dns/types_generate.go generated vendored Normal file
View file

@ -0,0 +1,271 @@
//+build ignore
// types_generate.go is meant to run with go generate. It will use
// go/{importer,types} to track down all the RR struct types. Then for each type
// it will generate conversion tables (TypeToRR and TypeToString) and banal
// methods (len, Header, copy) based on the struct tags. The generated source is
// written to ztypes.go, and is meant to be checked into git.
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/types"
"log"
"os"
"strings"
"text/template"
)
var skipLen = map[string]struct{}{
"NSEC": {},
"NSEC3": {},
"OPT": {},
}
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from type_generate.go
package dns
import (
"encoding/base64"
"net"
)
`
var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
// TypeToRR is a map of constructors for each RR type.
var TypeToRR = map[uint16]func() RR{
{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
{{end}}{{end}} }
`))
var typeToString = template.Must(template.New("typeToString").Parse(`
// TypeToString is a map of strings for each RR type.
var TypeToString = map[uint16]string{
{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
}
`))
var headerFunc = template.Must(template.New("headerFunc").Parse(`
// Header() functions
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
{{end}}
`))
// getTypeStruct will take a type and the package scope, and return the
// (innermost) struct if the type is considered a RR type (currently defined as
// those structs beginning with a RR_Header, could be redefined as implementing
// the RR interface). The bool return value indicates if embedded structs were
// resolved.
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
st, ok := t.Underlying().(*types.Struct)
if !ok {
return nil, false
}
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
return st, false
}
if st.Field(0).Anonymous() {
st, _ := getTypeStruct(st.Field(0).Type(), scope)
return st, true
}
return nil, false
}
func main() {
// Import and type-check the package
pkg, err := importer.Default().Import("github.com/miekg/dns")
fatalIfErr(err)
scope := pkg.Scope()
// Collect constants like TypeX
var numberedTypes []string
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
b, ok := o.Type().(*types.Basic)
if !ok || b.Kind() != types.Uint16 {
continue
}
if !strings.HasPrefix(o.Name(), "Type") {
continue
}
name := strings.TrimPrefix(o.Name(), "Type")
if name == "PrivateRR" {
continue
}
numberedTypes = append(numberedTypes, name)
}
// Collect actual types (*X)
var namedTypes []string
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
continue
}
if name == "PrivateRR" {
continue
}
// Check if corresponding TypeX exists
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
log.Fatalf("Constant Type%s does not exist.", o.Name())
}
namedTypes = append(namedTypes, o.Name())
}
b := &bytes.Buffer{}
b.WriteString(packageHdr)
// Generate TypeToRR
fatalIfErr(TypeToRR.Execute(b, namedTypes))
// Generate typeToString
fatalIfErr(typeToString.Execute(b, numberedTypes))
// Generate headerFunc
fatalIfErr(headerFunc.Execute(b, namedTypes))
// Generate len()
fmt.Fprint(b, "// len() functions\n")
for _, name := range namedTypes {
if _, ok := skipLen[name]; ok {
continue
}
o := scope.Lookup(name)
st, isEmbedded := getTypeStruct(o.Type(), scope)
if isEmbedded {
continue
}
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
for i := 1; i < st.NumFields(); i++ {
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
if _, ok := st.Field(i).Type().(*types.Slice); ok {
switch st.Tag(i) {
case `dns:"-"`:
// ignored
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
continue
}
switch {
case st.Tag(i) == `dns:"-"`:
// ignored
case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
o("l += len(rr.%s) + 1\n")
case st.Tag(i) == `dns:"octet"`:
o("l += len(rr.%s)\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
fallthrough
case st.Tag(i) == `dns:"base64"`:
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
fallthrough
case st.Tag(i) == `dns:"hex"`:
o("l += len(rr.%s)/2 + 1\n")
case st.Tag(i) == `dns:"a"`:
o("l += net.IPv4len // %s\n")
case st.Tag(i) == `dns:"aaaa"`:
o("l += net.IPv6len // %s\n")
case st.Tag(i) == `dns:"txt"`:
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
case st.Tag(i) == `dns:"uint48"`:
o("l += 6 // %s\n")
case st.Tag(i) == "":
switch st.Field(i).Type().(*types.Basic).Kind() {
case types.Uint8:
o("l += 1 // %s\n")
case types.Uint16:
o("l += 2 // %s\n")
case types.Uint32:
o("l += 4 // %s\n")
case types.Uint64:
o("l += 8 // %s\n")
case types.String:
o("l += len(rr.%s) + 1\n")
default:
log.Fatalln(name, st.Field(i).Name())
}
default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
}
}
fmt.Fprintf(b, "return l }\n")
}
// Generate copy()
fmt.Fprint(b, "// copy() functions\n")
for _, name := range namedTypes {
o := scope.Lookup(name)
st, isEmbedded := getTypeStruct(o.Type(), scope)
if isEmbedded {
continue
}
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
fields := []string{"*rr.Hdr.copyHeader()"}
for i := 1; i < st.NumFields(); i++ {
f := st.Field(i).Name()
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
t := sl.Underlying().String()
t = strings.TrimPrefix(t, "[]")
if strings.Contains(t, ".") {
splits := strings.Split(t, ".")
t = splits[len(splits)-1]
}
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
f, t, f, f, f)
fields = append(fields, f)
continue
}
if st.Field(i).Type().String() == "net.IP" {
fields = append(fields, "copyIP(rr."+f+")")
continue
}
fields = append(fields, "rr."+f)
}
fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
fmt.Fprintf(b, "}\n")
}
// gofmt
res, err := format.Source(b.Bytes())
if err != nil {
b.WriteTo(os.Stderr)
log.Fatal(err)
}
// write result
f, err := os.Create("ztypes.go")
fatalIfErr(err)
defer f.Close()
f.Write(res)
}
func fatalIfErr(err error) {
if err != nil {
log.Fatal(err)
}
}

2
vendor/github.com/miekg/dns/udp.go generated vendored
View file

@ -1,4 +1,4 @@
// +build !windows // +build !windows,!plan9
package dns package dns

View file

@ -24,6 +24,12 @@ func setUDPSocketOptions4(conn *net.UDPConn) error {
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
return err return err
} }
// Calling File() above results in the connection becoming blocking, we must fix that.
// See https://github.com/miekg/dns/issues/279
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
return err
}
return nil return nil
} }
@ -36,6 +42,10 @@ func setUDPSocketOptions6(conn *net.UDPConn) error {
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
return err return err
} }
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
return err
}
return nil return nil
} }

View file

@ -1,4 +1,4 @@
// +build !linux // +build !linux,!plan9
package dns package dns

34
vendor/github.com/miekg/dns/udp_plan9.go generated vendored Normal file
View file

@ -0,0 +1,34 @@
package dns
import (
"net"
)
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
// 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, 40)
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.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
return n, err
}

View file

@ -3,18 +3,22 @@ package dns
// NameUsed sets the RRs in the prereq section to // NameUsed sets the RRs in the prereq section to
// "Name is in use" RRs. RFC 2136 section 2.4.4. // "Name is in use" RRs. RFC 2136 section 2.4.4.
func (u *Msg) NameUsed(rr []RR) { func (u *Msg) NameUsed(rr []RR) {
u.Answer = make([]RR, len(rr)) if u.Answer == nil {
for i, r := range rr { u.Answer = make([]RR, 0, len(rr))
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}} }
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 // NameNotUsed sets the RRs in the prereq section to
// "Name is in not use" RRs. RFC 2136 section 2.4.5. // "Name is in not use" RRs. RFC 2136 section 2.4.5.
func (u *Msg) NameNotUsed(rr []RR) { func (u *Msg) NameNotUsed(rr []RR) {
u.Answer = make([]RR, len(rr)) if u.Answer == nil {
for i, r := range rr { u.Answer = make([]RR, 0, len(rr))
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}} }
for _, r := range rr {
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
} }
} }
@ -24,34 +28,34 @@ func (u *Msg) Used(rr []RR) {
if len(u.Question) == 0 { if len(u.Question) == 0 {
panic("dns: empty question section") panic("dns: empty question section")
} }
u.Answer = make([]RR, len(rr)) if u.Answer == nil {
for i, r := range rr { u.Answer = make([]RR, 0, len(rr))
u.Answer[i] = r }
u.Answer[i].Header().Class = u.Question[0].Qclass for _, r := range rr {
r.Header().Class = u.Question[0].Qclass
u.Answer = append(u.Answer, r)
} }
} }
// RRsetUsed sets the RRs in the prereq section to // RRsetUsed sets the RRs in the prereq section to
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1. // "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
func (u *Msg) RRsetUsed(rr []RR) { func (u *Msg) RRsetUsed(rr []RR) {
u.Answer = make([]RR, len(rr)) if u.Answer == nil {
for i, r := range rr { u.Answer = make([]RR, 0, len(rr))
u.Answer[i] = r }
u.Answer[i].Header().Class = ClassANY for _, r := range rr {
u.Answer[i].Header().Ttl = 0 u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
u.Answer[i].Header().Rdlength = 0
} }
} }
// RRsetNotUsed sets the RRs in the prereq section to // RRsetNotUsed sets the RRs in the prereq section to
// "RRset does not exist" RRs. RFC 2136 section 2.4.3. // "RRset does not exist" RRs. RFC 2136 section 2.4.3.
func (u *Msg) RRsetNotUsed(rr []RR) { func (u *Msg) RRsetNotUsed(rr []RR) {
u.Answer = make([]RR, len(rr)) if u.Answer == nil {
for i, r := range rr { u.Answer = make([]RR, 0, len(rr))
u.Answer[i] = r }
u.Answer[i].Header().Class = ClassNONE for _, r := range rr {
u.Answer[i].Header().Rdlength = 0 u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
u.Answer[i].Header().Ttl = 0
} }
} }
@ -60,35 +64,43 @@ func (u *Msg) Insert(rr []RR) {
if len(u.Question) == 0 { if len(u.Question) == 0 {
panic("dns: empty question section") panic("dns: empty question section")
} }
u.Ns = make([]RR, len(rr)) if u.Ns == nil {
for i, r := range rr { u.Ns = make([]RR, 0, len(rr))
u.Ns[i] = r }
u.Ns[i].Header().Class = u.Question[0].Qclass 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. // RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
func (u *Msg) RemoveRRset(rr []RR) { func (u *Msg) RemoveRRset(rr []RR) {
u.Ns = make([]RR, len(rr)) if u.Ns == nil {
for i, r := range rr { u.Ns = make([]RR, 0, len(rr))
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}} }
for _, r := range rr {
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
} }
} }
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3 // 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) { func (u *Msg) RemoveName(rr []RR) {
u.Ns = make([]RR, len(rr)) if u.Ns == nil {
for i, r := range rr { u.Ns = make([]RR, 0, len(rr))
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}} }
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 the RRSset, see RFC 2136 section 2.5.4 // Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
func (u *Msg) Remove(rr []RR) { func (u *Msg) Remove(rr []RR) {
u.Ns = make([]RR, len(rr)) if u.Ns == nil {
for i, r := range rr { u.Ns = make([]RR, 0, len(rr))
u.Ns[i] = r }
u.Ns[i].Header().Class = ClassNONE for _, r := range rr {
u.Ns[i].Header().Ttl = 0 r.Header().Class = ClassNONE
r.Header().Ttl = 0
u.Ns = append(u.Ns, r)
} }
} }

16
vendor/github.com/miekg/dns/xfr.go generated vendored
View file

@ -23,15 +23,27 @@ type Transfer struct {
// Think we need to away to stop the transfer // Think we need to away to stop the transfer
// In performs an incoming transfer with the server in a. // 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) { func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
timeout := dnsTimeout timeout := dnsTimeout
if t.DialTimeout != 0 { if t.DialTimeout != 0 {
timeout = t.DialTimeout timeout = t.DialTimeout
} }
if t.Conn == nil {
t.Conn, err = DialTimeout("tcp", a, timeout) t.Conn, err = DialTimeout("tcp", a, timeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
if err := t.WriteMsg(q); err != nil { if err := t.WriteMsg(q); err != nil {
return nil, err return nil, err
} }
@ -150,8 +162,8 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
// //
// ch := make(chan *dns.Envelope) // ch := make(chan *dns.Envelope)
// tr := new(dns.Transfer) // tr := new(dns.Transfer)
// tr.Out(w, r, ch) // go tr.Out(w, r, ch)
// c <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}} // ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
// close(ch) // close(ch)
// w.Hijack() // w.Hijack()
// // w.Close() // Client closes connection // // w.Close() // Client closes connection

3529
vendor/github.com/miekg/dns/zmsg.go generated vendored Normal file

File diff suppressed because it is too large Load diff

842
vendor/github.com/miekg/dns/ztypes.go generated vendored Normal file
View file

@ -0,0 +1,842 @@
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from type_generate.go
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) },
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) },
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) },
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) },
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) },
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) },
}
// TypeToString is a map of strings for each RR type.
var TypeToString = map[uint16]string{
TypeA: "A",
TypeAAAA: "AAAA",
TypeAFSDB: "AFSDB",
TypeANY: "ANY",
TypeATMA: "ATMA",
TypeAXFR: "AXFR",
TypeCAA: "CAA",
TypeCDNSKEY: "CDNSKEY",
TypeCDS: "CDS",
TypeCERT: "CERT",
TypeCNAME: "CNAME",
TypeDHCID: "DHCID",
TypeDLV: "DLV",
TypeDNAME: "DNAME",
TypeDNSKEY: "DNSKEY",
TypeDS: "DS",
TypeEID: "EID",
TypeEUI48: "EUI48",
TypeEUI64: "EUI64",
TypeGID: "GID",
TypeGPOS: "GPOS",
TypeHINFO: "HINFO",
TypeHIP: "HIP",
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",
TypeTA: "TA",
TypeTALINK: "TALINK",
TypeTKEY: "TKEY",
TypeTLSA: "TLSA",
TypeTSIG: "TSIG",
TypeTXT: "TXT",
TypeUID: "UID",
TypeUINFO: "UINFO",
TypeUNSPEC: "UNSPEC",
TypeURI: "URI",
TypeX25: "X25",
TypeNSAPPTR: "NSAP-PTR",
}
// Header() functions
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 *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 *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 *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 *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 *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 }
// len() functions
func (rr *A) len() int {
l := rr.Hdr.len()
l += net.IPv4len // A
return l
}
func (rr *AAAA) len() int {
l := rr.Hdr.len()
l += net.IPv6len // AAAA
return l
}
func (rr *AFSDB) len() int {
l := rr.Hdr.len()
l += 2 // Subtype
l += len(rr.Hostname) + 1
return l
}
func (rr *ANY) len() int {
l := rr.Hdr.len()
return l
}
func (rr *CAA) len() int {
l := rr.Hdr.len()
l += 1 // Flag
l += len(rr.Tag) + 1
l += len(rr.Value)
return l
}
func (rr *CERT) len() int {
l := rr.Hdr.len()
l += 2 // Type
l += 2 // KeyTag
l += 1 // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
return l
}
func (rr *CNAME) len() int {
l := rr.Hdr.len()
l += len(rr.Target) + 1
return l
}
func (rr *DHCID) len() int {
l := rr.Hdr.len()
l += base64.StdEncoding.DecodedLen(len(rr.Digest))
return l
}
func (rr *DNAME) len() int {
l := rr.Hdr.len()
l += len(rr.Target) + 1
return l
}
func (rr *DNSKEY) len() int {
l := rr.Hdr.len()
l += 2 // Flags
l += 1 // Protocol
l += 1 // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *DS) len() int {
l := rr.Hdr.len()
l += 2 // KeyTag
l += 1 // Algorithm
l += 1 // DigestType
l += len(rr.Digest)/2 + 1
return l
}
func (rr *EID) len() int {
l := rr.Hdr.len()
l += len(rr.Endpoint)/2 + 1
return l
}
func (rr *EUI48) len() int {
l := rr.Hdr.len()
l += 6 // Address
return l
}
func (rr *EUI64) len() int {
l := rr.Hdr.len()
l += 8 // Address
return l
}
func (rr *GID) len() int {
l := rr.Hdr.len()
l += 4 // Gid
return l
}
func (rr *GPOS) len() int {
l := rr.Hdr.len()
l += len(rr.Longitude) + 1
l += len(rr.Latitude) + 1
l += len(rr.Altitude) + 1
return l
}
func (rr *HINFO) len() int {
l := rr.Hdr.len()
l += len(rr.Cpu) + 1
l += len(rr.Os) + 1
return l
}
func (rr *HIP) len() int {
l := rr.Hdr.len()
l += 1 // HitLength
l += 1 // PublicKeyAlgorithm
l += 2 // PublicKeyLength
l += len(rr.Hit)/2 + 1
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
for _, x := range rr.RendezvousServers {
l += len(x) + 1
}
return l
}
func (rr *KX) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += len(rr.Exchanger) + 1
return l
}
func (rr *L32) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += net.IPv4len // Locator32
return l
}
func (rr *L64) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += 8 // Locator64
return l
}
func (rr *LOC) len() int {
l := rr.Hdr.len()
l += 1 // Version
l += 1 // Size
l += 1 // HorizPre
l += 1 // VertPre
l += 4 // Latitude
l += 4 // Longitude
l += 4 // Altitude
return l
}
func (rr *LP) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += len(rr.Fqdn) + 1
return l
}
func (rr *MB) len() int {
l := rr.Hdr.len()
l += len(rr.Mb) + 1
return l
}
func (rr *MD) len() int {
l := rr.Hdr.len()
l += len(rr.Md) + 1
return l
}
func (rr *MF) len() int {
l := rr.Hdr.len()
l += len(rr.Mf) + 1
return l
}
func (rr *MG) len() int {
l := rr.Hdr.len()
l += len(rr.Mg) + 1
return l
}
func (rr *MINFO) len() int {
l := rr.Hdr.len()
l += len(rr.Rmail) + 1
l += len(rr.Email) + 1
return l
}
func (rr *MR) len() int {
l := rr.Hdr.len()
l += len(rr.Mr) + 1
return l
}
func (rr *MX) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += len(rr.Mx) + 1
return l
}
func (rr *NAPTR) len() int {
l := rr.Hdr.len()
l += 2 // Order
l += 2 // Preference
l += len(rr.Flags) + 1
l += len(rr.Service) + 1
l += len(rr.Regexp) + 1
l += len(rr.Replacement) + 1
return l
}
func (rr *NID) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += 8 // NodeID
return l
}
func (rr *NIMLOC) len() int {
l := rr.Hdr.len()
l += len(rr.Locator)/2 + 1
return l
}
func (rr *NINFO) len() int {
l := rr.Hdr.len()
for _, x := range rr.ZSData {
l += len(x) + 1
}
return l
}
func (rr *NS) len() int {
l := rr.Hdr.len()
l += len(rr.Ns) + 1
return l
}
func (rr *NSAPPTR) len() int {
l := rr.Hdr.len()
l += len(rr.Ptr) + 1
return l
}
func (rr *NSEC3PARAM) len() int {
l := rr.Hdr.len()
l += 1 // Hash
l += 1 // Flags
l += 2 // Iterations
l += 1 // SaltLength
l += len(rr.Salt)/2 + 1
return l
}
func (rr *OPENPGPKEY) len() int {
l := rr.Hdr.len()
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *PTR) len() int {
l := rr.Hdr.len()
l += len(rr.Ptr) + 1
return l
}
func (rr *PX) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += len(rr.Map822) + 1
l += len(rr.Mapx400) + 1
return l
}
func (rr *RFC3597) len() int {
l := rr.Hdr.len()
l += len(rr.Rdata)/2 + 1
return l
}
func (rr *RKEY) len() int {
l := rr.Hdr.len()
l += 2 // Flags
l += 1 // Protocol
l += 1 // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l
}
func (rr *RP) len() int {
l := rr.Hdr.len()
l += len(rr.Mbox) + 1
l += len(rr.Txt) + 1
return l
}
func (rr *RRSIG) len() int {
l := rr.Hdr.len()
l += 2 // TypeCovered
l += 1 // Algorithm
l += 1 // Labels
l += 4 // OrigTtl
l += 4 // Expiration
l += 4 // Inception
l += 2 // KeyTag
l += len(rr.SignerName) + 1
l += base64.StdEncoding.DecodedLen(len(rr.Signature))
return l
}
func (rr *RT) len() int {
l := rr.Hdr.len()
l += 2 // Preference
l += len(rr.Host) + 1
return l
}
func (rr *SMIMEA) len() int {
l := rr.Hdr.len()
l += 1 // Usage
l += 1 // Selector
l += 1 // MatchingType
l += len(rr.Certificate)/2 + 1
return l
}
func (rr *SOA) len() int {
l := rr.Hdr.len()
l += len(rr.Ns) + 1
l += len(rr.Mbox) + 1
l += 4 // Serial
l += 4 // Refresh
l += 4 // Retry
l += 4 // Expire
l += 4 // Minttl
return l
}
func (rr *SPF) len() int {
l := rr.Hdr.len()
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *SRV) len() int {
l := rr.Hdr.len()
l += 2 // Priority
l += 2 // Weight
l += 2 // Port
l += len(rr.Target) + 1
return l
}
func (rr *SSHFP) len() int {
l := rr.Hdr.len()
l += 1 // Algorithm
l += 1 // Type
l += len(rr.FingerPrint)/2 + 1
return l
}
func (rr *TA) len() int {
l := rr.Hdr.len()
l += 2 // KeyTag
l += 1 // Algorithm
l += 1 // DigestType
l += len(rr.Digest)/2 + 1
return l
}
func (rr *TALINK) len() int {
l := rr.Hdr.len()
l += len(rr.PreviousName) + 1
l += len(rr.NextName) + 1
return l
}
func (rr *TKEY) len() int {
l := rr.Hdr.len()
l += len(rr.Algorithm) + 1
l += 4 // Inception
l += 4 // Expiration
l += 2 // Mode
l += 2 // Error
l += 2 // KeySize
l += len(rr.Key) + 1
l += 2 // OtherLen
l += len(rr.OtherData) + 1
return l
}
func (rr *TLSA) len() int {
l := rr.Hdr.len()
l += 1 // Usage
l += 1 // Selector
l += 1 // MatchingType
l += len(rr.Certificate)/2 + 1
return l
}
func (rr *TSIG) len() int {
l := rr.Hdr.len()
l += len(rr.Algorithm) + 1
l += 6 // TimeSigned
l += 2 // Fudge
l += 2 // MACSize
l += len(rr.MAC)/2 + 1
l += 2 // OrigId
l += 2 // Error
l += 2 // OtherLen
l += len(rr.OtherData)/2 + 1
return l
}
func (rr *TXT) len() int {
l := rr.Hdr.len()
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *UID) len() int {
l := rr.Hdr.len()
l += 4 // Uid
return l
}
func (rr *UINFO) len() int {
l := rr.Hdr.len()
l += len(rr.Uinfo) + 1
return l
}
func (rr *URI) len() int {
l := rr.Hdr.len()
l += 2 // Priority
l += 2 // Weight
l += len(rr.Target)
return l
}
func (rr *X25) len() int {
l := rr.Hdr.len()
l += len(rr.PSDNAddress) + 1
return l
}
// copy() functions
func (rr *A) copy() RR {
return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)}
}
func (rr *AAAA) copy() RR {
return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)}
}
func (rr *AFSDB) copy() RR {
return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname}
}
func (rr *ANY) copy() RR {
return &ANY{*rr.Hdr.copyHeader()}
}
func (rr *CAA) copy() RR {
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
}
func (rr *CERT) copy() RR {
return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
}
func (rr *CNAME) copy() RR {
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
}
func (rr *DHCID) copy() RR {
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
}
func (rr *DNAME) copy() RR {
return &DNAME{*rr.Hdr.copyHeader(), rr.Target}
}
func (rr *DNSKEY) copy() RR {
return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
}
func (rr *DS) copy() RR {
return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
}
func (rr *EID) copy() RR {
return &EID{*rr.Hdr.copyHeader(), rr.Endpoint}
}
func (rr *EUI48) copy() RR {
return &EUI48{*rr.Hdr.copyHeader(), rr.Address}
}
func (rr *EUI64) copy() RR {
return &EUI64{*rr.Hdr.copyHeader(), rr.Address}
}
func (rr *GID) copy() RR {
return &GID{*rr.Hdr.copyHeader(), rr.Gid}
}
func (rr *GPOS) copy() RR {
return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude}
}
func (rr *HINFO) copy() RR {
return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os}
}
func (rr *HIP) copy() RR {
RendezvousServers := make([]string, len(rr.RendezvousServers))
copy(RendezvousServers, rr.RendezvousServers)
return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
}
func (rr *KX) copy() RR {
return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger}
}
func (rr *L32) copy() RR {
return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)}
}
func (rr *L64) copy() RR {
return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64}
}
func (rr *LOC) copy() RR {
return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
}
func (rr *LP) copy() RR {
return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn}
}
func (rr *MB) copy() RR {
return &MB{*rr.Hdr.copyHeader(), rr.Mb}
}
func (rr *MD) copy() RR {
return &MD{*rr.Hdr.copyHeader(), rr.Md}
}
func (rr *MF) copy() RR {
return &MF{*rr.Hdr.copyHeader(), rr.Mf}
}
func (rr *MG) copy() RR {
return &MG{*rr.Hdr.copyHeader(), rr.Mg}
}
func (rr *MINFO) copy() RR {
return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email}
}
func (rr *MR) copy() RR {
return &MR{*rr.Hdr.copyHeader(), rr.Mr}
}
func (rr *MX) copy() RR {
return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx}
}
func (rr *NAPTR) copy() RR {
return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
}
func (rr *NID) copy() RR {
return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID}
}
func (rr *NIMLOC) copy() RR {
return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator}
}
func (rr *NINFO) copy() RR {
ZSData := make([]string, len(rr.ZSData))
copy(ZSData, rr.ZSData)
return &NINFO{*rr.Hdr.copyHeader(), ZSData}
}
func (rr *NS) copy() RR {
return &NS{*rr.Hdr.copyHeader(), rr.Ns}
}
func (rr *NSAPPTR) copy() RR {
return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr}
}
func (rr *NSEC) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap)
return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap}
}
func (rr *NSEC3) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap)
return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
}
func (rr *NSEC3PARAM) copy() RR {
return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
}
func (rr *OPENPGPKEY) copy() RR {
return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey}
}
func (rr *OPT) copy() RR {
Option := make([]EDNS0, len(rr.Option))
copy(Option, rr.Option)
return &OPT{*rr.Hdr.copyHeader(), Option}
}
func (rr *PTR) copy() RR {
return &PTR{*rr.Hdr.copyHeader(), rr.Ptr}
}
func (rr *PX) copy() RR {
return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400}
}
func (rr *RFC3597) copy() RR {
return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata}
}
func (rr *RKEY) copy() RR {
return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
}
func (rr *RP) copy() RR {
return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt}
}
func (rr *RRSIG) copy() RR {
return &RRSIG{*rr.Hdr.copyHeader(), 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.copyHeader(), rr.Preference, rr.Host}
}
func (rr *SMIMEA) copy() RR {
return &SMIMEA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
}
func (rr *SOA) copy() RR {
return &SOA{*rr.Hdr.copyHeader(), 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.copyHeader(), Txt}
}
func (rr *SRV) copy() RR {
return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
}
func (rr *SSHFP) copy() RR {
return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
}
func (rr *TA) copy() RR {
return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
}
func (rr *TALINK) copy() RR {
return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName}
}
func (rr *TKEY) copy() RR {
return &TKEY{*rr.Hdr.copyHeader(), 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.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
}
func (rr *TSIG) copy() RR {
return &TSIG{*rr.Hdr.copyHeader(), 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.copyHeader(), Txt}
}
func (rr *UID) copy() RR {
return &UID{*rr.Hdr.copyHeader(), rr.Uid}
}
func (rr *UINFO) copy() RR {
return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo}
}
func (rr *URI) copy() RR {
return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target}
}
func (rr *X25) copy() RR {
return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress}
}

6
vendor/vendor.json vendored
View file

@ -167,10 +167,10 @@
"revisionTime": "2015-04-06T19:39:34+02:00" "revisionTime": "2015-04-06T19:39:34+02:00"
}, },
{ {
"checksumSHA1": "Xnvgv0Jdze5n7ynajmcEOssBZPg=", "checksumSHA1": "Wahi4g/9XiHhSLAJ+8jskg71PCU=",
"path": "github.com/miekg/dns", "path": "github.com/miekg/dns",
"revision": "8395762c3490507cf5a27405fcd0e3d3dc547109", "revision": "58f52c57ce9df13460ac68200cef30a008b9c468",
"revisionTime": "2015-09-05T08:12:15+01:00" "revisionTime": "2016-10-18T06:08:08Z"
}, },
{ {
"checksumSHA1": "OpY4giv8kPIYbaunD7BSgCynj78=", "checksumSHA1": "OpY4giv8kPIYbaunD7BSgCynj78=",