ソースを参照

Bump the DNS library and revendor

Signed-off-by: Sam Whited <sam@samwhited.com>
Sam Whited 5 年 前
コミット
2a480d515e
50 ファイル変更4874 行追加3356 行削除
  1. 1 1
      libnetwork/resolver.go
  2. 1 1
      libnetwork/vendor.conf
  3. 2 4
      libnetwork/vendor/github.com/miekg/dns/LICENSE
  4. 38 31
      libnetwork/vendor/github.com/miekg/dns/README.md
  5. 61 0
      libnetwork/vendor/github.com/miekg/dns/acceptfunc.go
  6. 62 243
      libnetwork/vendor/github.com/miekg/dns/client.go
  7. 2 6
      libnetwork/vendor/github.com/miekg/dns/clientconfig.go
  8. 106 16
      libnetwork/vendor/github.com/miekg/dns/defaults.go
  9. 49 12
      libnetwork/vendor/github.com/miekg/dns/dns.go
  10. 58 49
      libnetwork/vendor/github.com/miekg/dns/dnssec.go
  11. 4 42
      libnetwork/vendor/github.com/miekg/dns/dnssec_keygen.go
  12. 133 108
      libnetwork/vendor/github.com/miekg/dns/dnssec_keyscan.go
  13. 8 7
      libnetwork/vendor/github.com/miekg/dns/dnssec_privkey.go
  14. 51 55
      libnetwork/vendor/github.com/miekg/dns/doc.go
  15. 38 0
      libnetwork/vendor/github.com/miekg/dns/duplicate.go
  16. 90 42
      libnetwork/vendor/github.com/miekg/dns/edns.go
  17. 7 1
      libnetwork/vendor/github.com/miekg/dns/format.go
  18. 10 1
      libnetwork/vendor/github.com/miekg/dns/fuzz.go
  19. 204 116
      libnetwork/vendor/github.com/miekg/dns/generate.go
  20. 11 0
      libnetwork/vendor/github.com/miekg/dns/go.mod
  21. 47 26
      libnetwork/vendor/github.com/miekg/dns/labels.go
  22. 44 0
      libnetwork/vendor/github.com/miekg/dns/listen_go111.go
  23. 23 0
      libnetwork/vendor/github.com/miekg/dns/listen_go_not111.go
  24. 367 385
      libnetwork/vendor/github.com/miekg/dns/msg.go
  25. 225 52
      libnetwork/vendor/github.com/miekg/dns/msg_helpers.go
  26. 111 0
      libnetwork/vendor/github.com/miekg/dns/msg_truncate.go
  27. 18 29
      libnetwork/vendor/github.com/miekg/dns/nsecx.go
  28. 47 81
      libnetwork/vendor/github.com/miekg/dns/privaterr.go
  29. 0 49
      libnetwork/vendor/github.com/miekg/dns/rawmsg.go
  30. 14 0
      libnetwork/vendor/github.com/miekg/dns/reverse.go
  31. 5 3
      libnetwork/vendor/github.com/miekg/dns/sanitize.go
  32. 559 223
      libnetwork/vendor/github.com/miekg/dns/scan.go
  33. 225 433
      libnetwork/vendor/github.com/miekg/dns/scan_rr.go
  34. 0 56
      libnetwork/vendor/github.com/miekg/dns/scanner.go
  35. 123 0
      libnetwork/vendor/github.com/miekg/dns/serve_mux.go
  36. 318 336
      libnetwork/vendor/github.com/miekg/dns/server.go
  37. 11 20
      libnetwork/vendor/github.com/miekg/dns/sig0.go
  38. 7 3
      libnetwork/vendor/github.com/miekg/dns/singleinflight.go
  39. 1 4
      libnetwork/vendor/github.com/miekg/dns/smimea.go
  40. 1 4
      libnetwork/vendor/github.com/miekg/dns/tlsa.go
  41. 13 10
      libnetwork/vendor/github.com/miekg/dns/tsig.go
  42. 282 136
      libnetwork/vendor/github.com/miekg/dns/types.go
  43. 2 4
      libnetwork/vendor/github.com/miekg/dns/udp_windows.go
  44. 9 5
      libnetwork/vendor/github.com/miekg/dns/update.go
  45. 1 1
      libnetwork/vendor/github.com/miekg/dns/version.go
  46. 35 29
      libnetwork/vendor/github.com/miekg/dns/xfr.go
  47. 0 155
      libnetwork/vendor/github.com/miekg/dns/zcompress.go
  48. 1157 0
      libnetwork/vendor/github.com/miekg/dns/zduplicate.go
  49. 92 411
      libnetwork/vendor/github.com/miekg/dns/zmsg.go
  50. 201 166
      libnetwork/vendor/github.com/miekg/dns/ztypes.go

+ 1 - 1
libnetwork/resolver.go

@@ -484,7 +484,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
 			resp, err = co.ReadMsg()
 			// Truncated DNS replies should be sent to the client so that the
 			// client can retry over TCP
-			if err != nil && err != dns.ErrTruncated {
+			if err != nil && !resp.Truncated {
 				r.forwardQueryEnd()
 				logrus.Debugf("[resolver] read from DNS server failed, %s", err)
 				continue

+ 1 - 1
libnetwork/vendor.conf

@@ -35,7 +35,7 @@ github.com/sean-/seed                   e2103e2c35297fb7e17febb81e49b312087a2372
 github.com/hashicorp/go-sockaddr        c7188e74f6acae5a989bdc959aa779f8b9f42faf # v1.0.2
 github.com/hashicorp/serf               598c54895cc5a7b1a24a398d635e8c0ea0959870
 github.com/mattn/go-shellwords          02e3cf038dcea8290e44424da473dd12be796a8a # v1.0.3
-github.com/miekg/dns                    e57bf427e68187a27e22adceac868350d7a7079b # v1.0.7
+github.com/miekg/dns                    6c0c4e6581f8e173cc562c8b3363ab984e4ae071 # v1.1.27
 github.com/opencontainers/go-digest     279bed98673dd5bef374d3b6e4b09e2af76183bf # v1.0.0-rc1
 github.com/opencontainers/image-spec    d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
 github.com/opencontainers/runc          2b18fe1d885ee5083ef9f0838fee39b62d653e30

+ 2 - 4
libnetwork/vendor/github.com/miekg/dns/LICENSE

@@ -1,7 +1,3 @@
-Extensions of the original work are copyright (c) 2011 Miek Gieben
-
-As this is fork of the official Go code the same license applies:
-
 Copyright (c) 2009 The Go Authors. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -30,3 +26,5 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+As this is fork of the official Go code the same license applies.
+Extensions of the original work are copyright (c) 2011 Miek Gieben

+ 38 - 31
libnetwork/vendor/github.com/miekg/dns/README.md

@@ -7,10 +7,10 @@
 
 > Less is more.
 
-Complete and usable DNS library. All widely used Resource Records are supported, including the
-DNSSEC types. It follows a lean and mean philosophy. 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 can build servers and resolvers with it.
+Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
+It follows a lean and mean philosophy. 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
+can build servers and resolvers with it.
 
 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 two versions of Go.
@@ -42,10 +42,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/tianon/rawdns
 * https://mesosphere.github.io/mesos-dns/
 * https://pulse.turbobytes.com/
-* https://play.google.com/store/apps/details?id=com.turbobytes.dig
 * https://github.com/fcambus/statzone
 * https://github.com/benschw/dns-clb-go
-* https://github.com/corny/dnscheck for http://public-dns.info/
+* https://github.com/corny/dnscheck for <http://public-dns.info/>
 * https://namesmith.io
 * https://github.com/miekg/unbound
 * https://github.com/miekg/exdns
@@ -56,7 +55,7 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/bamarni/dockness
 * https://github.com/fffaraz/microdns
 * http://kelda.io
-* https://github.com/ipdcode/hades (JD.COM)
+* https://github.com/ipdcode/hades <https://jd.com>
 * https://github.com/StackExchange/dnscontrol/
 * https://www.dnsperf.com/
 * https://dnssectest.net/
@@ -64,42 +63,47 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/oif/apex
 * https://github.com/jedisct1/dnscrypt-proxy
 * https://github.com/jedisct1/rpdns
+* https://github.com/xor-gate/sshfp
+* https://github.com/rs/dnstrace
+* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
+* https://github.com/semihalev/sdns
+* https://render.com
+* https://github.com/peterzen/goresolver
+* https://github.com/folbricht/routedns
 
 Send pull request if you want to be listed here.
 
 # Features
 
-* UDP/TCP queries, IPv4 and IPv6;
-* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
-* Fast:
-    * Reply speed around ~ 80K qps (faster hardware results in more qps);
-    * Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
-* Server side programming (mimicking the net/http package);
-* Client side programming;
-* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
-* EDNS0, NSID, Cookies;
-* AXFR/IXFR;
-* TSIG, SIG(0);
-* DNS over TLS: optional encrypted connection between client and server;
-* DNS name compression;
-* Depends only on the standard library.
+* UDP/TCP queries, IPv4 and IPv6
+* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported
+* Fast
+* Server side programming (mimicking the net/http package)
+* Client side programming
+* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
+* EDNS0, NSID, Cookies
+* AXFR/IXFR
+* TSIG, SIG(0)
+* DNS over TLS (DoT): encrypted connection between client and server over TCP
+* DNS name compression
 
 Have fun!
 
 Miek Gieben  -  2010-2012  -  <miek@miek.nl>
+DNS Authors 2012-
 
 # Building
 
-Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
-work:
+This library uses Go modules and uses semantic versioning. Building is done with the `go` tool, so
+the following should work:
 
     go get github.com/miekg/dns
     go build github.com/miekg/dns
 
 ## Examples
 
-A short "how to use the API" is at the beginning of doc.go (this also will show
-when you call `godoc github.com/miekg/dns`).
+A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
+github.com/miekg/dns`).
 
 Example programs can be found in the `github.com/miekg/exdns` repository.
 
@@ -123,6 +127,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 2915 - NAPTR record
 * 2929 - DNS IANA Considerations
 * 3110 - RSASHA1 DNS keys
+* 3123 - APL record
 * 3225 - DO bit (DNSSEC OK)
 * 340{1,2,3} - NAPTR record
 * 3445 - Limiting the scope of (DNS)KEY
@@ -149,6 +154,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 6844 - CAA record
 * 6891 - EDNS0 update
 * 6895 - DNS IANA considerations
+* 6944 - DNSSEC DNSKEY Algorithm Status
 * 6975 - Algorithm Understanding in DNSSEC
 * 7043 - EUI48/EUI64 records
 * 7314 - DNS (EDNS) EXPIRE Option
@@ -157,12 +163,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 7553 - URI record
 * 7858 - DNS over TLS: Initiation and Performance Considerations
 * 7871 - EDNS0 Client Subnet
-* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
+* 7873 - Domain Name System (DNS) Cookies
 * 8080 - EdDSA for DNSSEC
+* 8499 - DNS Terminology
 
-## Loosely based upon
+## Loosely Based Upon
 
-* `ldns`
-* `NSD`
-* `Net::DNS`
-* `GRONG`
+* ldns - <https://nlnetlabs.nl/projects/ldns/about/>
+* NSD - <https://nlnetlabs.nl/projects/nsd/about/>
+* Net::DNS - <http://www.net-dns.org/>
+* GRONG - <https://github.com/bortzmeyer/grong>

+ 61 - 0
libnetwork/vendor/github.com/miekg/dns/acceptfunc.go

@@ -0,0 +1,61 @@
+package dns
+
+// MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError.
+// It returns a MsgAcceptAction to indicate what should happen with the message.
+type MsgAcceptFunc func(dh Header) MsgAcceptAction
+
+// DefaultMsgAcceptFunc checks the request and will reject if:
+//
+// * isn't a request (don't respond in that case)
+//
+// * opcode isn't OpcodeQuery or OpcodeNotify
+//
+// * Zero bit isn't zero
+//
+// * has more than 1 question in the question section
+//
+// * has more than 1 RR in the Answer section
+//
+// * has more than 0 RRs in the Authority section
+//
+// * has more than 2 RRs in the Additional section
+//
+var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
+
+// MsgAcceptAction represents the action to be taken.
+type MsgAcceptAction int
+
+const (
+	MsgAccept               MsgAcceptAction = iota // Accept the message
+	MsgReject                                      // Reject the message with a RcodeFormatError
+	MsgIgnore                                      // Ignore the error and send nothing back.
+	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented
+)
+
+func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
+	if isResponse := dh.Bits&_QR != 0; isResponse {
+		return MsgIgnore
+	}
+
+	// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
+	opcode := int(dh.Bits>>11) & 0xF
+	if opcode != OpcodeQuery && opcode != OpcodeNotify {
+		return MsgRejectNotImplemented
+	}
+
+	if dh.Qdcount != 1 {
+		return MsgReject
+	}
+	// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
+	if dh.Ancount > 1 {
+		return MsgReject
+	}
+	// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
+	if dh.Nscount > 1 {
+		return MsgReject
+	}
+	if dh.Arcount > 2 {
+		return MsgReject
+	}
+	return MsgAccept
+}

+ 62 - 243
libnetwork/vendor/github.com/miekg/dns/client.go

@@ -3,24 +3,20 @@ package dns
 // A client implementation.
 
 import (
-	"bytes"
 	"context"
 	"crypto/tls"
 	"encoding/binary"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
-	"net/http"
-	"net/url"
 	"strings"
 	"time"
 )
 
-const dnsTimeout time.Duration = 2 * time.Second
-const tcpIdleTimeout time.Duration = 8 * time.Second
-
-const dohMimeType = "application/dns-udpwireformat"
+const (
+	dnsTimeout     time.Duration = 2 * time.Second
+	tcpIdleTimeout time.Duration = 8 * time.Second
+)
 
 // A Conn represents a connection to a DNS server.
 type Conn struct {
@@ -43,7 +39,6 @@ type Client struct {
 	DialTimeout    time.Duration     // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - 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
-	HTTPClient     *http.Client      // The http.Client to use for DNS-over-HTTPS
 	TsigSecret     map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
 	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
 	group          singleflight
@@ -88,33 +83,22 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 	// create a new dialer with the appropriate timeout
 	var d net.Dialer
 	if c.Dialer == nil {
-		d = net.Dialer{}
+		d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())}
 	} else {
-		d = net.Dialer(*c.Dialer)
-	}
-	d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
-
-	network := "udp"
-	useTLS := false
-
-	switch c.Net {
-	case "tcp-tls":
-		network = "tcp"
-		useTLS = true
-	case "tcp4-tls":
-		network = "tcp4"
-		useTLS = true
-	case "tcp6-tls":
-		network = "tcp6"
-		useTLS = true
-	default:
-		if c.Net != "" {
-			network = c.Net
-		}
+		d = *c.Dialer
+	}
+
+	network := c.Net
+	if network == "" {
+		network = "udp"
 	}
 
+	useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
+
 	conn = new(Conn)
 	if useTLS {
+		network = strings.TrimSuffix(network, "-tls")
+
 		conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
 	} else {
 		conn.Conn, err = d.Dial(network, address)
@@ -122,6 +106,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 	if err != nil {
 		return nil, err
 	}
+
 	return conn, nil
 }
 
@@ -141,33 +126,18 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
 // attribute appropriately
 func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
 	if !c.SingleInflight {
-		if c.Net == "https" {
-			// TODO(tmthrgd): pipe timeouts into exchangeDOH
-			return c.exchangeDOH(context.TODO(), m, address)
-		}
-
 		return c.exchange(m, address)
 	}
 
-	t := "nop"
-	if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
-		t = t1
-	}
-	cl := "nop"
-	if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
-		cl = cl1
-	}
-	r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
-		if c.Net == "https" {
-			// TODO(tmthrgd): pipe timeouts into exchangeDOH
-			return c.exchangeDOH(context.TODO(), m, address)
-		}
-
+	q := m.Question[0]
+	key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
+	r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
 		return c.exchange(m, address)
 	})
 	if r != nil && shared {
 		r = r.Copy()
 	}
+
 	return r, rtt, err
 }
 
@@ -208,77 +178,6 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
 	return r, rtt, err
 }
 
-func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	p, err := m.Pack()
-	if err != nil {
-		return nil, 0, err
-	}
-
-	// TODO(tmthrgd): Allow the path to be customised?
-	u := &url.URL{
-		Scheme: "https",
-		Host:   a,
-		Path:   "/.well-known/dns-query",
-	}
-	if u.Port() == "443" {
-		u.Host = u.Hostname()
-	}
-
-	req, err := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(p))
-	if err != nil {
-		return nil, 0, err
-	}
-
-	req.Header.Set("Content-Type", dohMimeType)
-	req.Header.Set("Accept", dohMimeType)
-
-	t := time.Now()
-
-	hc := http.DefaultClient
-	if c.HTTPClient != nil {
-		hc = c.HTTPClient
-	}
-
-	if ctx != context.Background() && ctx != context.TODO() {
-		req = req.WithContext(ctx)
-	}
-
-	resp, err := hc.Do(req)
-	if err != nil {
-		return nil, 0, err
-	}
-	defer closeHTTPBody(resp.Body)
-
-	if resp.StatusCode != http.StatusOK {
-		return nil, 0, fmt.Errorf("dns: server returned HTTP %d error: %q", resp.StatusCode, resp.Status)
-	}
-
-	if ct := resp.Header.Get("Content-Type"); ct != dohMimeType {
-		return nil, 0, fmt.Errorf("dns: unexpected Content-Type %q; expected %q", ct, dohMimeType)
-	}
-
-	p, err = ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, 0, err
-	}
-
-	rtt = time.Since(t)
-
-	r = new(Msg)
-	if err := r.Unpack(p); err != nil {
-		return r, 0, err
-	}
-
-	// TODO: TSIG? Is it even supported over DoH?
-
-	return r, rtt, nil
-}
-
-func closeHTTPBody(r io.ReadCloser) error {
-	io.Copy(ioutil.Discard, io.LimitReader(r, 8<<20))
-	return r.Close()
-}
-
 // ReadMsg reads a message from the connection co.
 // If the received message contains a TSIG record the transaction signature
 // is verified. This method always tries to return the message, however if an
@@ -317,24 +216,21 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 		err error
 	)
 
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		r := t.(io.Reader)
-
-		// First two bytes specify the length of the entire message.
-		l, err := tcpMsgLen(r)
-		if err != nil {
-			return nil, err
-		}
-		p = make([]byte, l)
-		n, err = tcpRead(r, p)
-	default:
+	if _, ok := co.Conn.(net.PacketConn); ok {
 		if co.UDPSize > MinMsgSize {
 			p = make([]byte, co.UDPSize)
 		} else {
 			p = make([]byte, MinMsgSize)
 		}
 		n, err = co.Read(p)
+	} else {
+		var length uint16
+		if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
+			return nil, err
+		}
+
+		p = make([]byte, length)
+		n, err = io.ReadFull(co.Conn, p)
 	}
 
 	if err != nil {
@@ -354,78 +250,26 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 	return p, err
 }
 
-// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
-func tcpMsgLen(t io.Reader) (int, error) {
-	p := []byte{0, 0}
-	n, err := t.Read(p)
-	if err != nil {
-		return 0, err
-	}
-
-	// As seen with my local router/switch, returns 1 byte on the above read,
-	// resulting a a ShortRead. Just write it out (instead of loop) and read the
-	// other byte.
-	if n == 1 {
-		n1, err := t.Read(p[1:])
-		if err != nil {
-			return 0, err
-		}
-		n += n1
-	}
-
-	if n != 2 {
-		return 0, ErrShortRead
-	}
-	l := binary.BigEndian.Uint16(p)
-	if l == 0 {
-		return 0, ErrShortRead
-	}
-	return int(l), nil
-}
-
-// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
-func tcpRead(t io.Reader, p []byte) (int, error) {
-	n, err := t.Read(p)
-	if err != nil {
-		return n, err
-	}
-	for n < len(p) {
-		j, err := t.Read(p[n:])
-		if err != nil {
-			return n, err
-		}
-		n += j
-	}
-	return n, err
-}
-
 // Read implements the net.Conn read method.
 func (co *Conn) Read(p []byte) (n int, err error) {
 	if co.Conn == nil {
 		return 0, ErrConnEmpty
 	}
-	if len(p) < 2 {
-		return 0, io.ErrShortBuffer
+
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		// UDP connection
+		return co.Conn.Read(p)
 	}
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		r := t.(io.Reader)
 
-		l, err := tcpMsgLen(r)
-		if err != nil {
-			return 0, err
-		}
-		if l > len(p) {
-			return int(l), io.ErrShortBuffer
-		}
-		return tcpRead(r, p[:l])
+	var length uint16
+	if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
+		return 0, err
 	}
-	// UDP connection
-	n, err = co.Conn.Read(p)
-	if err != nil {
-		return n, err
+	if int(length) > len(p) {
+		return 0, io.ErrShortBuffer
 	}
-	return n, err
+
+	return io.ReadFull(co.Conn, p[:length])
 }
 
 // WriteMsg sends a message through the connection co.
@@ -447,33 +291,25 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
 	if err != nil {
 		return err
 	}
-	if _, err = co.Write(out); err != nil {
-		return err
-	}
-	return nil
+	_, err = co.Write(out)
+	return err
 }
 
 // Write implements the net.Conn Write method.
-func (co *Conn) Write(p []byte) (n int, err error) {
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		w := t.(io.Writer)
-
-		lp := len(p)
-		if lp < 2 {
-			return 0, io.ErrShortBuffer
-		}
-		if lp > MaxMsgSize {
-			return 0, &Error{err: "message too large"}
-		}
-		l := make([]byte, 2, lp+2)
-		binary.BigEndian.PutUint16(l, uint16(lp))
-		p = append(l, p...)
-		n, err := io.Copy(w, bytes.NewReader(p))
-		return int(n), err
-	}
-	n, err = co.Conn.Write(p)
-	return n, err
+func (co *Conn) Write(p []byte) (int, error) {
+	if len(p) > MaxMsgSize {
+		return 0, &Error{err: "message too large"}
+	}
+
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		return co.Conn.Write(p)
+	}
+
+	l := make([]byte, 2)
+	binary.BigEndian.PutUint16(l, uint16(len(p)))
+
+	n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
+	return int(n), err
 }
 
 // Return the appropriate timeout for a specific request
@@ -516,7 +352,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
 
 // ExchangeConn performs a synchronous query. It sends the message m via the connection
 // c and waits for a reply. The connection c is not closed by ExchangeConn.
-// This function is going away, but can easily be mimicked:
+// Deprecated: This function is going away, but can easily be mimicked:
 //
 //	co := &dns.Conn{Conn: c} // c is your net.Conn
 //	co.WriteMsg(m)
@@ -540,11 +376,7 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
 // DialTimeout acts like Dial but takes a timeout.
 func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
-	conn, err = client.Dial(address)
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // DialWithTLS connects to the address on the named network with TLS.
@@ -553,12 +385,7 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
 		network += "-tls"
 	}
 	client := Client{Net: network, TLSConfig: tlsConfig}
-	conn, err = client.Dial(address)
-
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
@@ -567,30 +394,22 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
 		network += "-tls"
 	}
 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
-	conn, err = client.Dial(address)
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // ExchangeContext acts like Exchange, but honors the deadline on the provided
 // context, if present. If there is both a context deadline and a configured
 // timeout on the client, the earliest of the two takes effect.
 func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	if !c.SingleInflight && c.Net == "https" {
-		return c.exchangeDOH(ctx, m, a)
-	}
-
 	var timeout time.Duration
 	if deadline, ok := ctx.Deadline(); !ok {
 		timeout = 0
 	} else {
-		timeout = deadline.Sub(time.Now())
+		timeout = time.Until(deadline)
 	}
 	// not passing the context to the underlying calls, as the API does not support
 	// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
-	// TODO(tmthrgd): this is a race condition
+	// TODO(tmthrgd,miekg): this is a race condition.
 	c.Dialer = &net.Dialer{Timeout: timeout}
 	return c.Exchange(m, a)
 }

+ 2 - 6
libnetwork/vendor/github.com/miekg/dns/clientconfig.go

@@ -68,14 +68,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
 			}
 
 		case "search": // set search path to given servers
-			c.Search = make([]string, len(f)-1)
-			for i := 0; i < len(c.Search); i++ {
-				c.Search[i] = f[i+1]
-			}
+			c.Search = append([]string(nil), f[1:]...)
 
 		case "options": // magic options
-			for i := 1; i < len(f); i++ {
-				s := f[i]
+			for _, s := range f[1:] {
 				switch {
 				case len(s) >= 6 && s[:6] == "ndots:":
 					n, _ := strconv.Atoi(s[6:])

+ 106 - 16
libnetwork/vendor/github.com/miekg/dns/defaults.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"net"
 	"strconv"
+	"strings"
 )
 
 const hexDigit = "0123456789abcdef"
@@ -145,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
 // record in the additional section will do. It returns the OPT record
 // found or nil.
 func (dns *Msg) IsEdns0() *OPT {
-	// EDNS0 is at the end of the additional section, start there.
-	// We might want to change this to *only* look at the last two
-	// records. So we see TSIG and/or OPT - this a slightly bigger
-	// change though.
+	// RFC 6891, Section 6.1.1 allows the OPT record to appear
+	// anywhere in the additional record section, but it's usually at
+	// the end so start there.
 	for i := len(dns.Extra) - 1; i >= 0; i-- {
 		if dns.Extra[i].Header().Rrtype == TypeOPT {
 			return dns.Extra[i].(*OPT)
@@ -157,17 +157,93 @@ func (dns *Msg) IsEdns0() *OPT {
 	return nil
 }
 
+// popEdns0 is like IsEdns0, but it removes the record from the message.
+func (dns *Msg) popEdns0() *OPT {
+	// RFC 6891, Section 6.1.1 allows the OPT record to appear
+	// anywhere in the additional record section, but it's usually at
+	// the end so start there.
+	for i := len(dns.Extra) - 1; i >= 0; i-- {
+		if dns.Extra[i].Header().Rrtype == TypeOPT {
+			opt := dns.Extra[i].(*OPT)
+			dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
+			return opt
+		}
+	}
+	return nil
+}
+
 // IsDomainName checks if s is a valid domain name, it returns the number of
 // labels and true, when a domain name is valid.  Note that non fully qualified
 // domain name is considered valid, in this case the last label is counted in
 // the number of labels.  When false is returned the number of labels is not
 // 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.
+// label fits in 63 characters and that the entire name will fit into the 255
+// octet wire format limit.
 func IsDomainName(s string) (labels int, ok bool) {
-	_, labels, err := packDomainName(s, nil, 0, nil, false)
-	return labels, err == nil
+	// XXX: The logic in this function was copied from packDomainName and
+	// should be kept in sync with that function.
+
+	const lenmsg = 256
+
+	if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata.
+		return 0, false
+	}
+
+	s = Fqdn(s)
+
+	// Each dot ends a segment of the name. Except for escaped dots (\.), which
+	// are normal dots.
+
+	var (
+		off    int
+		begin  int
+		wasDot bool
+	)
+	for i := 0; i < len(s); i++ {
+		switch s[i] {
+		case '\\':
+			if off+1 > lenmsg {
+				return labels, false
+			}
+
+			// check for \DDD
+			if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
+				i += 3
+				begin += 3
+			} else {
+				i++
+				begin++
+			}
+
+			wasDot = false
+		case '.':
+			if wasDot {
+				// two dots back to back is not legal
+				return labels, false
+			}
+			wasDot = true
+
+			labelLen := i - begin
+			if labelLen >= 1<<6 { // top two bits of length must be clear
+				return labels, false
+			}
+
+			// off can already (we're in a loop) be bigger than lenmsg
+			// this happens when a name isn't fully qualified
+			off += 1 + labelLen
+			if off > lenmsg {
+				return labels, false
+			}
+
+			labels++
+			begin = i + 1
+		default:
+			wasDot = false
+		}
+	}
+
+	return labels, true
 }
 
 // IsSubDomain checks if child is indeed a child of the parent. If child and parent
@@ -181,7 +257,7 @@ func IsSubDomain(parent, child string) bool {
 // The checking is performed on the binary payload.
 func IsMsg(buf []byte) error {
 	// Header
-	if len(buf) < 12 {
+	if len(buf) < headerSize {
 		return errors.New("dns: bad message header")
 	}
 	// Header: Opcode
@@ -191,11 +267,18 @@ func IsMsg(buf []byte) error {
 
 // IsFqdn checks if a domain name is fully qualified.
 func IsFqdn(s string) bool {
-	l := len(s)
-	if l == 0 {
+	s2 := strings.TrimSuffix(s, ".")
+	if s == s2 {
 		return false
 	}
-	return s[l-1] == '.'
+
+	i := strings.LastIndexFunc(s2, func(r rune) bool {
+		return r != '\\'
+	})
+
+	// Test whether we have an even number of escape sequences before
+	// the dot or none.
+	return (len(s2)-i)%2 != 0
 }
 
 // IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
@@ -244,12 +327,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
 	if ip == nil {
 		return "", &Error{err: "unrecognized address: " + addr}
 	}
-	if ip.To4() != nil {
-		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
-			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
+	if v4 := ip.To4(); v4 != nil {
+		buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
+		// Add it, in reverse, to the buffer
+		for i := len(v4) - 1; i >= 0; i-- {
+			buf = strconv.AppendInt(buf, int64(v4[i]), 10)
+			buf = append(buf, '.')
+		}
+		// Append "in-addr.arpa." and return (buf already has the final .)
+		buf = append(buf, "in-addr.arpa."...)
+		return string(buf), nil
 	}
 	// Must be IPv6
-	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
+	buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
 	// Add it, in reverse, to the buffer
 	for i := len(ip) - 1; i >= 0; i-- {
 		v := ip[i]

+ 49 - 12
libnetwork/vendor/github.com/miekg/dns/dns.go

@@ -34,10 +34,30 @@ type RR interface {
 
 	// copy returns a copy of the RR
 	copy() RR
-	// len returns the length (in octets) of the uncompressed RR in wire format.
-	len() int
-	// pack packs an RR into wire format.
-	pack([]byte, int, map[string]int, bool) (int, error)
+
+	// len returns the length (in octets) of the compressed or uncompressed RR in wire format.
+	//
+	// If compression is nil, the uncompressed size will be returned, otherwise the compressed
+	// size will be returned and domain names will be added to the map for future compression.
+	len(off int, compression map[string]struct{}) int
+
+	// pack packs the records RDATA into wire format. The header will
+	// already have been packed into msg.
+	pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error)
+
+	// unpack unpacks an RR from wire format.
+	//
+	// This will only be called on a new and empty RR type with only the header populated. It
+	// will only be called if the record's RDATA is non-empty.
+	unpack(msg []byte, off int) (off1 int, err error)
+
+	// parse parses an RR from zone file format.
+	//
+	// This will only be called on a new and empty RR type with only the header populated.
+	parse(c *zlexer, origin string) *ParseError
+
+	// isDuplicate returns whether the two RRs are duplicates.
+	isDuplicate(r2 RR) bool
 }
 
 // RR_Header is the header all DNS resource records share.
@@ -70,28 +90,45 @@ func (h *RR_Header) String() string {
 	return s
 }
 
-func (h *RR_Header) len() int {
-	l := len(h.Name) + 1
+func (h *RR_Header) len(off int, compression map[string]struct{}) int {
+	l := domainNameLen(h.Name, off, compression, true)
 	l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
 	return l
 }
 
+func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	// RR_Header has no RDATA to pack.
+	return off, nil
+}
+
+func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
+	panic("dns: internal error: unpack should never be called on RR_Header")
+}
+
+func (h *RR_Header) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on RR_Header")
+}
+
 // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
 func (rr *RFC3597) ToRFC3597(r RR) error {
-	buf := make([]byte, r.len()*2)
-	off, err := PackRR(r, buf, 0, nil, false)
+	buf := make([]byte, Len(r)*2)
+	headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
 	if err != nil {
 		return err
 	}
 	buf = buf[:off]
-	if int(r.Header().Rdlength) > off {
-		return ErrBuf
+
+	*rr = RFC3597{Hdr: *r.Header()}
+	rr.Hdr.Rdlength = uint16(off - headerEnd)
+
+	if noRdata(rr.Hdr) {
+		return nil
 	}
 
-	rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength))
+	_, err = rr.unpack(buf, headerEnd)
 	if err != nil {
 		return err
 	}
-	*rr = *rfc3597.(*RFC3597)
+
 	return nil
 }

+ 58 - 49
libnetwork/vendor/github.com/miekg/dns/dnssec.go

@@ -67,9 +67,6 @@ var AlgorithmToString = map[uint8]string{
 	PRIVATEOID:       "PRIVATEOID",
 }
 
-// StringToAlgorithm is the reverse of AlgorithmToString.
-var StringToAlgorithm = reverseInt8(AlgorithmToString)
-
 // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
 var AlgorithmToHash = map[uint8]crypto.Hash{
 	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725
@@ -102,9 +99,6 @@ var HashToString = map[uint8]string{
 	SHA512: "SHA512",
 }
 
-// StringToHash is a map of names to hash IDs.
-var StringToHash = reverseInt8(HashToString)
-
 // DNSKEY flag values.
 const (
 	SEP    = 1
@@ -147,8 +141,8 @@ func (k *DNSKEY) KeyTag() uint16 {
 	switch k.Algorithm {
 	case RSAMD5:
 		// Look at the bottom two bytes of the modules, which the last
-		// item in the pubkey. We could do this faster by looking directly
-		// at the base64 values. But I'm lazy.
+		// item in the pubkey.
+		// This algorithm has been deprecated, but keep this key-tag calculation.
 		modulus, _ := fromBase64([]byte(k.PublicKey))
 		if len(modulus) > 1 {
 			x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
@@ -173,7 +167,7 @@ func (k *DNSKEY) KeyTag() uint16 {
 				keytag += int(v) << 8
 			}
 		}
-		keytag += (keytag >> 16) & 0xFFFF
+		keytag += keytag >> 16 & 0xFFFF
 		keytag &= 0xFFFF
 	}
 	return uint16(keytag)
@@ -268,16 +262,17 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		return ErrKey
 	}
 
+	h0 := rrset[0].Header()
 	rr.Hdr.Rrtype = TypeRRSIG
-	rr.Hdr.Name = rrset[0].Header().Name
-	rr.Hdr.Class = rrset[0].Header().Class
+	rr.Hdr.Name = h0.Name
+	rr.Hdr.Class = h0.Class
 	if rr.OrigTtl == 0 { // If set don't override
-		rr.OrigTtl = rrset[0].Header().Ttl
+		rr.OrigTtl = h0.Ttl
 	}
-	rr.TypeCovered = rrset[0].Header().Rrtype
-	rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
+	rr.TypeCovered = h0.Rrtype
+	rr.Labels = uint8(CountLabel(h0.Name))
 
-	if strings.HasPrefix(rrset[0].Header().Name, "*") {
+	if strings.HasPrefix(h0.Name, "*") {
 		rr.Labels-- // wildcard, remove from label count
 	}
 
@@ -323,6 +318,9 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		}
 
 		rr.Signature = toBase64(signature)
+	case RSAMD5, DSA, DSANSEC3SHA1:
+		// See RFC 6944.
+		return ErrAlg
 	default:
 		h := hash.New()
 		h.Write(signdata)
@@ -401,7 +399,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	if rr.Algorithm != k.Algorithm {
 		return ErrKey
 	}
-	if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
+	if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
 		return ErrKey
 	}
 	if k.Protocol != 3 {
@@ -411,10 +409,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	// IsRRset checked that we have at least one RR and that the RRs in
 	// the set have consistent type, class, and name. Also check that type and
 	// class matches the RRSIG record.
-	if rrset[0].Header().Class != rr.Hdr.Class {
-		return ErrRRset
-	}
-	if rrset[0].Header().Rrtype != rr.TypeCovered {
+	if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
 		return ErrRRset
 	}
 
@@ -512,8 +507,8 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
 	}
 	modi := (int64(rr.Inception) - utc) / year68
 	mode := (int64(rr.Expiration) - utc) / year68
-	ti := int64(rr.Inception) + (modi * year68)
-	te := int64(rr.Expiration) + (mode * year68)
+	ti := int64(rr.Inception) + modi*year68
+	te := int64(rr.Expiration) + mode*year68
 	return ti <= utc && utc <= te
 }
 
@@ -533,6 +528,11 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
 		return nil
 	}
 
+	if len(keybuf) < 1+1+64 {
+		// Exponent must be at least 1 byte and modulus at least 64
+		return nil
+	}
+
 	// RFC 2537/3110, section 2. RSA Public KEY Resource Records
 	// Length is in the 0th byte, unless its zero, then it
 	// it in bytes 1 and 2 and its a 16 bit number
@@ -542,25 +542,35 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
 		explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
 		keyoff = 3
 	}
+
+	if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
+		// Exponent larger than supported by the crypto package,
+		// empty, or contains prohibited leading zero.
+		return nil
+	}
+
+	modoff := keyoff + int(explen)
+	modlen := len(keybuf) - modoff
+	if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
+		// Modulus is too small, large, or contains prohibited leading zero.
+		return nil
+	}
+
 	pubkey := new(rsa.PublicKey)
 
-	pubkey.N = big.NewInt(0)
-	shift := uint64((explen - 1) * 8)
-	expo := uint64(0)
-	for i := int(explen - 1); i > 0; i-- {
-		expo += uint64(keybuf[keyoff+i]) << shift
-		shift -= 8
-	}
-	// Remainder
-	expo += uint64(keybuf[keyoff])
-	if expo > (2<<31)+1 {
-		// Larger expo than supported.
-		// println("dns: F5 primes (or larger) are not supported")
+	var expo uint64
+	// The exponent of length explen is between keyoff and modoff.
+	for _, v := range keybuf[keyoff:modoff] {
+		expo <<= 8
+		expo |= uint64(v)
+	}
+	if expo > 1<<31-1 {
+		// Larger exponent than supported by the crypto package.
 		return nil
 	}
-	pubkey.E = int(expo)
 
-	pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
+	pubkey.E = int(expo)
+	pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
 	return pubkey
 }
 
@@ -585,10 +595,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
 			return nil
 		}
 	}
-	pubkey.X = big.NewInt(0)
-	pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
-	pubkey.Y = big.NewInt(0)
-	pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
+	pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
+	pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
 	return pubkey
 }
 
@@ -609,10 +617,10 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
 	p, keybuf := keybuf[:size], keybuf[size:]
 	g, y := keybuf[:size], keybuf[size:]
 	pubkey := new(dsa.PublicKey)
-	pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
-	pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
-	pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
-	pubkey.Y = big.NewInt(0).SetBytes(y)
+	pubkey.Parameters.Q = new(big.Int).SetBytes(q)
+	pubkey.Parameters.P = new(big.Int).SetBytes(p)
+	pubkey.Parameters.G = new(big.Int).SetBytes(g)
+	pubkey.Y = new(big.Int).SetBytes(y)
 	return pubkey
 }
 
@@ -642,15 +650,16 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 	wires := make(wireSlice, len(rrset))
 	for i, r := range rrset {
 		r1 := r.copy()
-		r1.Header().Ttl = s.OrigTtl
-		labels := SplitDomainName(r1.Header().Name)
+		h := r1.Header()
+		h.Ttl = s.OrigTtl
+		labels := SplitDomainName(h.Name)
 		// 6.2. Canonical RR Form. (4) - wildcards
 		if len(labels) > int(s.Labels) {
 			// Wildcard
-			r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
+			h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
 		}
 		// RFC 4034: 6.2.  Canonical RR Form. (2) - domain name to lowercase
-		r1.Header().Name = strings.ToLower(r1.Header().Name)
+		h.Name = strings.ToLower(h.Name)
 		// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
 		//   NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
 		//   HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
@@ -708,7 +717,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 			x.Target = strings.ToLower(x.Target)
 		}
 		// 6.2. Canonical RR Form. (5) - origTTL
-		wire := make([]byte, r1.len()+1) // +1 to be safe(r)
+		wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
 		off, err1 := PackRR(r1, wire, 0, nil, false)
 		if err1 != nil {
 			return nil, err1

+ 4 - 42
libnetwork/vendor/github.com/miekg/dns/dnssec_keygen.go

@@ -2,7 +2,6 @@ package dns
 
 import (
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rand"
@@ -20,11 +19,9 @@ import (
 // bits should be set to the size of the algorithm.
 func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
 	switch k.Algorithm {
-	case DSA, DSANSEC3SHA1:
-		if bits != 1024 {
-			return nil, ErrKeySize
-		}
-	case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
+	case RSAMD5, DSA, DSANSEC3SHA1:
+		return nil, ErrAlg
+	case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
 		if bits < 512 || bits > 4096 {
 			return nil, ErrKeySize
 		}
@@ -47,20 +44,7 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
 	}
 
 	switch k.Algorithm {
-	case DSA, DSANSEC3SHA1:
-		params := new(dsa.Parameters)
-		if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
-			return nil, err
-		}
-		priv := new(dsa.PrivateKey)
-		priv.PublicKey.Parameters = *params
-		err := dsa.GenerateKey(priv, rand.Reader)
-		if err != nil {
-			return nil, err
-		}
-		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
-		return priv, nil
-	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
+	case RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
 		priv, err := rsa.GenerateKey(rand.Reader, bits)
 		if err != nil {
 			return nil, err
@@ -120,16 +104,6 @@ func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
 	return true
 }
 
-// Set the public key for DSA
-func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
-	if _Q == nil || _P == nil || _G == nil || _Y == nil {
-		return false
-	}
-	buf := dsaToBuf(_Q, _P, _G, _Y)
-	k.PublicKey = toBase64(buf)
-	return true
-}
-
 // Set the public key for Ed25519
 func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
 	if _K == nil {
@@ -164,15 +138,3 @@ func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
 	buf = append(buf, intToBytes(_Y, intlen)...)
 	return buf
 }
-
-// Set the public key for X and Y for Curve. The two
-// values are just concatenated.
-func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
-	t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
-	buf := []byte{byte(t)}
-	buf = append(buf, intToBytes(_Q, 20)...)
-	buf = append(buf, intToBytes(_P, 64+t*8)...)
-	buf = append(buf, intToBytes(_G, 64+t*8)...)
-	buf = append(buf, intToBytes(_Y, 64+t*8)...)
-	return buf
-}

+ 133 - 108
libnetwork/vendor/github.com/miekg/dns/dnssec_keyscan.go

@@ -1,9 +1,8 @@
 package dns
 
 import (
-	"bytes"
+	"bufio"
 	"crypto"
-	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/rsa"
 	"io"
@@ -44,19 +43,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
 		return nil, ErrPrivKey
 	}
 	switch uint8(algo) {
-	case DSA:
-		priv, err := readPrivateKeyDSA(m)
-		if err != nil {
-			return nil, err
-		}
-		pub := k.publicKeyDSA()
-		if pub == nil {
-			return nil, ErrKey
-		}
-		priv.PublicKey = *pub
-		return priv, nil
-	case RSAMD5:
-		fallthrough
+	case RSAMD5, DSA, DSANSEC3SHA1:
+		return nil, ErrAlg
 	case RSASHA1:
 		fallthrough
 	case RSASHA1NSEC3SHA1:
@@ -109,21 +97,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
 			}
 			switch k {
 			case "modulus":
-				p.PublicKey.N = big.NewInt(0)
-				p.PublicKey.N.SetBytes(v1)
+				p.PublicKey.N = new(big.Int).SetBytes(v1)
 			case "publicexponent":
-				i := big.NewInt(0)
-				i.SetBytes(v1)
+				i := new(big.Int).SetBytes(v1)
 				p.PublicKey.E = int(i.Int64()) // int64 should be large enough
 			case "privateexponent":
-				p.D = big.NewInt(0)
-				p.D.SetBytes(v1)
+				p.D = new(big.Int).SetBytes(v1)
 			case "prime1":
-				p.Primes[0] = big.NewInt(0)
-				p.Primes[0].SetBytes(v1)
+				p.Primes[0] = new(big.Int).SetBytes(v1)
 			case "prime2":
-				p.Primes[1] = big.NewInt(0)
-				p.Primes[1].SetBytes(v1)
+				p.Primes[1] = new(big.Int).SetBytes(v1)
 			}
 		case "exponent1", "exponent2", "coefficient":
 			// not used in Go (yet)
@@ -134,27 +117,9 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
 	return p, nil
 }
 
-func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
-	p := new(dsa.PrivateKey)
-	p.X = big.NewInt(0)
-	for k, v := range m {
-		switch k {
-		case "private_value(x)":
-			v1, err := fromBase64([]byte(v))
-			if err != nil {
-				return nil, err
-			}
-			p.X.SetBytes(v1)
-		case "created", "publish", "activate":
-			/* not used in Go (yet) */
-		}
-	}
-	return p, nil
-}
-
 func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
 	p := new(ecdsa.PrivateKey)
-	p.D = big.NewInt(0)
+	p.D = new(big.Int)
 	// TODO: validate that the required flags are present
 	for k, v := range m {
 		switch k {
@@ -181,22 +146,10 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
 			if err != nil {
 				return nil, err
 			}
-			if len(p1) != 32 {
+			if len(p1) != ed25519.SeedSize {
 				return nil, ErrPrivKey
 			}
-			// RFC 8080 and Golang's x/crypto/ed25519 differ as to how the
-			// private keys are represented. RFC 8080 specifies that private
-			// keys be stored solely as the seed value (p1 above) while the
-			// ed25519 package represents them as the seed value concatenated
-			// to the public key, which is derived from the seed value.
-			//
-			// ed25519.GenerateKey reads exactly 32 bytes from the passed in
-			// io.Reader and uses them as the seed. It also derives the
-			// public key and produces a compatible private key.
-			_, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
-			if err != nil {
-				return nil, err
-			}
+			p = ed25519.NewKeyFromSeed(p1)
 		case "created", "publish", "activate":
 			/* not used in Go (yet) */
 		}
@@ -207,23 +160,12 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
 // parseKey reads a private key from r. It returns a map[string]string,
 // with the key-value pairs, or an error when the file is not correct.
 func parseKey(r io.Reader, file string) (map[string]string, error) {
-	s, cancel := scanInit(r)
 	m := make(map[string]string)
-	c := make(chan lex)
-	k := ""
-	defer func() {
-		cancel()
-		// zlexer can send up to two tokens, the next one and possibly 1 remainders.
-		// Do a non-blocking read.
-		_, ok := <-c
-		_, ok = <-c
-		if !ok {
-			// too bad
-		}
-	}()
-	// Start the lexer
-	go klexer(s, c)
-	for l := range c {
+	var k string
+
+	c := newKLexer(r)
+
+	for l, ok := c.Next(); ok; l, ok = c.Next() {
 		// It should alternate
 		switch l.value {
 		case zKey:
@@ -232,41 +174,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
 			if k == "" {
 				return nil, &ParseError{file, "no private key seen", l}
 			}
-			//println("Setting", strings.ToLower(k), "to", l.token, "b")
+
 			m[strings.ToLower(k)] = l.token
 			k = ""
 		}
 	}
+
+	// Surface any read errors from r.
+	if err := c.Err(); err != nil {
+		return nil, &ParseError{file: file, err: err.Error()}
+	}
+
 	return m, nil
 }
 
-// klexer scans the sourcefile and returns tokens on the channel c.
-func klexer(s *scan, c chan lex) {
-	var l lex
-	str := "" // Hold the current read text
-	commt := false
-	key := true
-	x, err := s.tokenText()
-	defer close(c)
-	for err == nil {
-		l.column = s.position.Column
-		l.line = s.position.Line
+type klexer struct {
+	br io.ByteReader
+
+	readErr error
+
+	line   int
+	column int
+
+	key bool
+
+	eol bool // end-of-line
+}
+
+func newKLexer(r io.Reader) *klexer {
+	br, ok := r.(io.ByteReader)
+	if !ok {
+		br = bufio.NewReaderSize(r, 1024)
+	}
+
+	return &klexer{
+		br: br,
+
+		line: 1,
+
+		key: true,
+	}
+}
+
+func (kl *klexer) Err() error {
+	if kl.readErr == io.EOF {
+		return nil
+	}
+
+	return kl.readErr
+}
+
+// readByte returns the next byte from the input
+func (kl *klexer) readByte() (byte, bool) {
+	if kl.readErr != nil {
+		return 0, false
+	}
+
+	c, err := kl.br.ReadByte()
+	if err != nil {
+		kl.readErr = err
+		return 0, false
+	}
+
+	// delay the newline handling until the next token is delivered,
+	// fixes off-by-one errors when reporting a parse error.
+	if kl.eol {
+		kl.line++
+		kl.column = 0
+		kl.eol = false
+	}
+
+	if c == '\n' {
+		kl.eol = true
+	} else {
+		kl.column++
+	}
+
+	return c, true
+}
+
+func (kl *klexer) Next() (lex, bool) {
+	var (
+		l lex
+
+		str strings.Builder
+
+		commt bool
+	)
+
+	for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
+		l.line, l.column = kl.line, kl.column
+
 		switch x {
 		case ':':
-			if commt {
+			if commt || !kl.key {
 				break
 			}
-			l.token = str
-			if key {
-				l.value = zKey
-				c <- l
-				// Next token is a space, eat it
-				s.tokenText()
-				key = false
-				str = ""
-			} else {
-				l.value = zValue
-			}
+
+			kl.key = false
+
+			// Next token is a space, eat it
+			kl.readByte()
+
+			l.value = zKey
+			l.token = str.String()
+			return l, true
 		case ';':
 			commt = true
 		case '\n':
@@ -274,24 +286,37 @@ func klexer(s *scan, c chan lex) {
 				// Reset a comment
 				commt = false
 			}
+
+			if kl.key && str.Len() == 0 {
+				// ignore empty lines
+				break
+			}
+
+			kl.key = true
+
 			l.value = zValue
-			l.token = str
-			c <- l
-			str = ""
-			commt = false
-			key = true
+			l.token = str.String()
+			return l, true
 		default:
 			if commt {
 				break
 			}
-			str += string(x)
+
+			str.WriteByte(x)
 		}
-		x, err = s.tokenText()
 	}
-	if len(str) > 0 {
+
+	if kl.readErr != nil && kl.readErr != io.EOF {
+		// Don't return any tokens after a read error occurs.
+		return lex{value: zEOF}, false
+	}
+
+	if str.Len() > 0 {
 		// Send remainder
-		l.token = str
 		l.value = zValue
-		c <- l
+		l.token = str.String()
+		return l, true
 	}
+
+	return lex{value: zEOF}, false
 }

+ 8 - 7
libnetwork/vendor/github.com/miekg/dns/dnssec_privkey.go

@@ -13,6 +13,8 @@ import (
 
 const format = "Private-key-format: v1.3\n"
 
+var bigIntOne = big.NewInt(1)
+
 // PrivateKeyString converts a PrivateKey to a string. This string has the same
 // format as the private-key-file of BIND9 (Private-key-format: v1.3).
 // It needs some info from the key (the algorithm), so its a method of the DNSKEY
@@ -31,12 +33,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
 		prime2 := toBase64(p.Primes[1].Bytes())
 		// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
 		// and from: http://code.google.com/p/go/issues/detail?id=987
-		one := big.NewInt(1)
-		p1 := big.NewInt(0).Sub(p.Primes[0], one)
-		q1 := big.NewInt(0).Sub(p.Primes[1], one)
-		exp1 := big.NewInt(0).Mod(p.D, p1)
-		exp2 := big.NewInt(0).Mod(p.D, q1)
-		coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
+		p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
+		q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
+		exp1 := new(big.Int).Mod(p.D, p1)
+		exp2 := new(big.Int).Mod(p.D, q1)
+		coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
 
 		exponent1 := toBase64(exp1.Bytes())
 		exponent2 := toBase64(exp2.Bytes())
@@ -82,7 +83,7 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
 			"Public_value(y): " + pub + "\n"
 
 	case ed25519.PrivateKey:
-		private := toBase64(p[:32])
+		private := toBase64(p.Seed())
 		return format +
 			"Algorithm: " + algorithm + "\n" +
 			"PrivateKey: " + private + "\n"

+ 51 - 55
libnetwork/vendor/github.com/miekg/dns/doc.go

@@ -1,20 +1,20 @@
 /*
 Package dns implements a full featured interface to the Domain Name System.
-Server- and client-side programming is supported.
-The package allows complete control over what is sent out to the DNS. The package
-API follows the less-is-more principle, by presenting a small, clean interface.
+Both server- and client-side programming is supported. The package allows
+complete control over what is sent out to the DNS. The API follows the
+less-is-more principle, by presenting a small, clean interface.
 
-The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
+It supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
 TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
-Note that domain names MUST be fully qualified, before sending them, unqualified
+
+Note that domain names MUST be fully qualified before sending them, unqualified
 names in a message will result in a packing failure.
 
-Resource records are native types. They are not stored in wire format.
-Basic usage pattern for creating a new resource record:
+Resource records are native types. They are not stored in wire format. Basic
+usage pattern for creating a new resource record:
 
      r := new(dns.MX)
-     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
-     Class: dns.ClassINET, Ttl: 3600}
+     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
      r.Preference = 10
      r.Mx = "mx.miek.nl."
 
@@ -30,8 +30,8 @@ Or even:
 
      mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
 
-In the DNS messages are exchanged, these messages contain resource
-records (sets). Use pattern for creating a message:
+In the DNS messages are exchanged, these messages contain resource records
+(sets). Use pattern for creating a message:
 
      m := new(dns.Msg)
      m.SetQuestion("miek.nl.", dns.TypeMX)
@@ -40,8 +40,8 @@ Or when not certain if the domain name is fully qualified:
 
 	m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
 
-The message m is now a message with the question section set to ask
-the MX records for the miek.nl. zone.
+The message m is now a message with the question section set to ask the MX
+records for the miek.nl. zone.
 
 The following is slightly more verbose, but more flexible:
 
@@ -51,9 +51,8 @@ The following is slightly more verbose, but more flexible:
      m1.Question = make([]dns.Question, 1)
      m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
 
-After creating a message it can be sent.
-Basic use pattern for synchronous querying the DNS at a
-server configured on 127.0.0.1 and port 53:
+After creating a message it can be sent. Basic use pattern for synchronous
+querying the DNS at a server configured on 127.0.0.1 and port 53:
 
      c := new(dns.Client)
      in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
@@ -84,7 +83,7 @@ with:
 
 	in, err := dns.Exchange(m1, "127.0.0.1:53")
 
-When this functions returns you will get dns message. A dns message consists
+When this functions returns you will get DNS message. A DNS message consists
 out of four sections.
 The question section: in.Question, the answer section: in.Answer,
 the authority section: in.Ns and the additional section: in.Extra.
@@ -99,25 +98,24 @@ the Answer section:
 
 Domain Name and TXT Character String Representations
 
-Both domain names and TXT character strings are converted to presentation
-form both when unpacked and when converted to strings.
+Both domain names and TXT character strings are converted to presentation form
+both when unpacked and when converted to strings.
 
 For TXT character strings, tabs, carriage returns and line feeds will be
-converted to \t, \r and \n respectively. Back slashes and quotations marks
-will be escaped. Bytes below 32 and above 127 will be converted to \DDD
-form.
+converted to \t, \r and \n respectively. Back slashes and quotations marks will
+be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
 
-For domain names, in addition to the above rules brackets, periods,
-spaces, semicolons and the at symbol are escaped.
+For domain names, in addition to the above rules brackets, periods, spaces,
+semicolons and the at symbol are escaped.
 
 DNSSEC
 
-DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
-uses public key cryptography to sign resource records. The
-public keys are stored in DNSKEY records and the signatures in RRSIG records.
+DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
+public key cryptography to sign resource records. The 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
-to a request.
+Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
+bit to a request.
 
      m := new(dns.Msg)
      m.SetEdns0(4096, true)
@@ -126,9 +124,9 @@ Signature generation, signature verification and key generation are all supporte
 
 DYNAMIC UPDATES
 
-Dynamic updates reuses the DNS message format, but renames three of
-the sections. Question is Zone, Answer is Prerequisite, Authority is
-Update, only the Additional is not renamed. See RFC 2136 for the gory details.
+Dynamic updates reuses the DNS message format, but renames three of the
+sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
+the Additional is not renamed. See RFC 2136 for the gory details.
 
 You can set a rather complex set of rules for the existence of absence of
 certain resource records or names in a zone to specify if resource records
@@ -145,10 +143,9 @@ DNS function shows which functions exist to specify the prerequisites.
   NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
   zone     rrset    rr       RRset exists (value dep)   dns.Used
 
-The prerequisite section can also be left empty.
-If you have decided on the prerequisites you can tell what RRs should
-be added or deleted. The next table shows the options you have and
-what functions to call.
+The prerequisite section can also be left empty. If you have decided on the
+prerequisites you can tell what RRs should be added or deleted. The next table
+shows the options you have and what functions to call.
 
  3.4.2.6 - Table Of Metavalues Used In Update Section
 
@@ -181,10 +178,10 @@ changes to the RRset after calling SetTsig() the signature will be incorrect.
 	...
 	// When sending the TSIG RR is calculated and filled in before sending
 
-When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
-TSIG, this is the basic use pattern. In this example we request an AXFR for
-miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
-and using the server 176.58.119.54:
+When requesting an zone transfer (almost all TSIG usage is when requesting zone
+transfers), with TSIG, this is the basic use pattern. In this example we
+request an AXFR for miek.nl. with TSIG key named "axfr." and secret
+"so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
 
 	t := new(dns.Transfer)
 	m := new(dns.Msg)
@@ -194,8 +191,8 @@ and using the server 176.58.119.54:
 	c, err := t.In(m, "176.58.119.54:53")
 	for r := range c { ... }
 
-You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
-If something is not correct an error is returned.
+You can now read the records from the transfer as they come in. Each envelope
+is checked with TSIG. If something is not correct an error is returned.
 
 Basic use pattern validating and replying to a message that has TSIG set.
 
@@ -220,28 +217,28 @@ Basic use pattern validating and replying to a message that has TSIG set.
 
 PRIVATE RRS
 
-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
+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
 can be used, before requesting an official type code from IANA.
 
-see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
+See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more
 information.
 
 EDNS0
 
-EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
-by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
+EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
+RFC 6891. It defines an new RR type, the OPT RR, which is then completely
 abused.
+
 Basic use pattern for creating an (empty) OPT RR:
 
 	o := new(dns.OPT)
 	o.Hdr.Name = "." // MUST be the root zone, per definition.
 	o.Hdr.Rrtype = dns.TypeOPT
 
-The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
-interfaces. Currently only a few have been standardized: EDNS0_NSID
-(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
-that these options may be combined in an OPT RR.
+The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
+Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
+EDNS0_SUBNET (RFC 7871). Note that these options may be combined in an OPT RR.
 Basic use pattern for a server to check if (and which) options are set:
 
 	// o is a dns.OPT
@@ -262,10 +259,9 @@ From RFC 2931:
     ... protection for glue records, DNS requests, protection for message headers
     on requests and responses, and protection of the overall integrity of a response.
 
-It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
-secret approach in TSIG.
-Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
-RSASHA512.
+It works like TSIG, except that SIG(0) uses public key cryptography, instead of
+the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
+ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
 
 Signing subsequent messages in multi-message sessions is not implemented.
 */

+ 38 - 0
libnetwork/vendor/github.com/miekg/dns/duplicate.go

@@ -0,0 +1,38 @@
+package dns
+
+//go:generate go run duplicate_generate.go
+
+// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
+// So this means the header data is equal *and* the RDATA is the same. Return true
+// is so, otherwise false.
+// It's a protocol violation to have identical RRs in a message.
+func IsDuplicate(r1, r2 RR) bool {
+	// Check whether the record header is identical.
+	if !r1.Header().isDuplicate(r2.Header()) {
+		return false
+	}
+
+	// Check whether the RDATA is identical.
+	return r1.isDuplicate(r2)
+}
+
+func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RR_Header)
+	if !ok {
+		return false
+	}
+	if r1.Class != r2.Class {
+		return false
+	}
+	if r1.Rrtype != r2.Rrtype {
+		return false
+	}
+	if !isDuplicateName(r1.Name, r2.Name) {
+		return false
+	}
+	// ignore TTL
+	return true
+}
+
+// isDuplicateName checks if the domain names s1 and s2 are equal.
+func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }

+ 90 - 42
libnetwork/vendor/github.com/miekg/dns/edns.go

@@ -78,36 +78,44 @@ func (rr *OPT) String() string {
 	return s
 }
 
-func (rr *OPT) len() int {
-	l := rr.Hdr.len()
-	for i := 0; i < len(rr.Option); i++ {
+func (rr *OPT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	for _, o := range rr.Option {
 		l += 4 // Account for 2-byte option code and 2-byte option length.
-		lo, _ := rr.Option[i].pack()
+		lo, _ := o.pack()
 		l += len(lo)
 	}
 	return l
 }
 
+func (rr *OPT) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on OPT")
+}
+
+func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
+
 // return the old value -> delete SetVersion?
 
 // Version returns the EDNS version used. Only zero is defined.
 func (rr *OPT) Version() uint8 {
-	return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
+	return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
 }
 
 // SetVersion sets the version of EDNS. This is usually zero.
 func (rr *OPT) SetVersion(v uint8) {
-	rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
+	rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16
 }
 
 // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
 func (rr *OPT) ExtendedRcode() int {
-	return int((rr.Hdr.Ttl & 0xFF000000) >> 24)
+	return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
 }
 
 // SetExtendedRcode sets the EDNS extended RCODE field.
-func (rr *OPT) SetExtendedRcode(v uint8) {
-	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24)
+//
+// If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
+func (rr *OPT) SetExtendedRcode(v uint16) {
+	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
 }
 
 // UDPSize returns the UDP buffer size.
@@ -151,6 +159,8 @@ type EDNS0 interface {
 	unpack([]byte) error
 	// String returns the string representation of the option.
 	String() string
+	// copy returns a deep-copy of the option.
+	copy() EDNS0
 }
 
 // EDNS0_NSID option is used to retrieve a nameserver
@@ -181,7 +191,8 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
 // Option implements the EDNS0 interface.
 func (e *EDNS0_NSID) Option() uint16        { return EDNS0NSID } // Option returns the option code.
 func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
-func (e *EDNS0_NSID) String() string        { return string(e.Nsid) }
+func (e *EDNS0_NSID) String() string        { return e.Nsid }
+func (e *EDNS0_NSID) copy() EDNS0           { return &EDNS0_NSID{e.Code, e.Nsid} }
 
 // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
 // an idea of where the client lives. See RFC 7871. It can then give back a different
@@ -271,22 +282,16 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
 		if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
 			return errors.New("dns: bad netmask")
 		}
-		addr := make([]byte, net.IPv4len)
-		for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
-			addr[i] = b[4+i]
-		}
-		e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
+		addr := make(net.IP, net.IPv4len)
+		copy(addr, b[4:])
+		e.Address = addr.To16()
 	case 2:
 		if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
 			return errors.New("dns: bad netmask")
 		}
-		addr := make([]byte, net.IPv6len)
-		for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
-			addr[i] = b[4+i]
-		}
-		e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
-			addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
-			addr[11], addr[12], addr[13], addr[14], addr[15]}
+		addr := make(net.IP, net.IPv6len)
+		copy(addr, b[4:])
+		e.Address = addr
 	default:
 		return errors.New("dns: bad address family")
 	}
@@ -305,6 +310,16 @@ func (e *EDNS0_SUBNET) String() (s string) {
 	return
 }
 
+func (e *EDNS0_SUBNET) copy() EDNS0 {
+	return &EDNS0_SUBNET{
+		e.Code,
+		e.Family,
+		e.SourceNetmask,
+		e.SourceScope,
+		e.Address,
+	}
+}
+
 // The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
 //
 //	o := new(dns.OPT)
@@ -340,11 +355,12 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
 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 }
+func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.Cookie} }
 
 // 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
 // up after themselves. This is a draft RFC and more information can be found at
-// http://files.dns-sd.org/draft-sekar-dns-ul.txt
+// https://tools.ietf.org/html/draft-sekar-dns-ul-02
 //
 //	o := new(dns.OPT)
 //	o.Hdr.Name = "."
@@ -354,23 +370,36 @@ func (e *EDNS0_COOKIE) String() string        { return e.Cookie }
 //	e.Lease = 120 // in seconds
 //	o.Option = append(o.Option, e)
 type EDNS0_UL struct {
-	Code  uint16 // Always EDNS0UL
-	Lease uint32
+	Code     uint16 // Always EDNS0UL
+	Lease    uint32
+	KeyLease uint32
 }
 
 // Option implements the EDNS0 interface.
 func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
-func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
+func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) }
+func (e *EDNS0_UL) copy() EDNS0    { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} }
 
 // Copied: http://golang.org/src/pkg/net/dnsmsg.go
 func (e *EDNS0_UL) pack() ([]byte, error) {
-	b := make([]byte, 4)
+	var b []byte
+	if e.KeyLease == 0 {
+		b = make([]byte, 4)
+	} else {
+		b = make([]byte, 8)
+		binary.BigEndian.PutUint32(b[4:], e.KeyLease)
+	}
 	binary.BigEndian.PutUint32(b, e.Lease)
 	return b, nil
 }
 
 func (e *EDNS0_UL) unpack(b []byte) error {
-	if len(b) < 4 {
+	switch len(b) {
+	case 4:
+		e.KeyLease = 0
+	case 8:
+		e.KeyLease = binary.BigEndian.Uint32(b[4:])
+	default:
 		return ErrBuf
 	}
 	e.Lease = binary.BigEndian.Uint32(b)
@@ -415,10 +444,13 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
 
 func (e *EDNS0_LLQ) String() string {
 	s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
-		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
+		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) +
 		" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
 	return s
 }
+func (e *EDNS0_LLQ) copy() EDNS0 {
+	return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
+}
 
 // EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
 type EDNS0_DAU struct {
@@ -433,15 +465,16 @@ func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
 
 func (e *EDNS0_DAU) String() string {
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := AlgorithmToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
 
 // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
 type EDNS0_DHU struct {
@@ -456,15 +489,16 @@ func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
 
 func (e *EDNS0_DHU) String() string {
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := HashToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := HashToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
 
 // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
 type EDNS0_N3U struct {
@@ -480,15 +514,16 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
 func (e *EDNS0_N3U) String() string {
 	// Re-use the hash map
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := HashToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := HashToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
 
 // EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
 type EDNS0_EXPIRE struct {
@@ -499,17 +534,19 @@ type EDNS0_EXPIRE struct {
 // Option implements the EDNS0 interface.
 func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
 func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
+func (e *EDNS0_EXPIRE) copy() EDNS0    { return &EDNS0_EXPIRE{e.Code, e.Expire} }
 
 func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
 	b := make([]byte, 4)
-	b[0] = byte(e.Expire >> 24)
-	b[1] = byte(e.Expire >> 16)
-	b[2] = byte(e.Expire >> 8)
-	b[3] = byte(e.Expire)
+	binary.BigEndian.PutUint32(b, e.Expire)
 	return b, nil
 }
 
 func (e *EDNS0_EXPIRE) unpack(b []byte) error {
+	if len(b) == 0 {
+		// zero-length EXPIRE query, see RFC 7314 Section 2
+		return nil
+	}
 	if len(b) < 4 {
 		return ErrBuf
 	}
@@ -540,6 +577,11 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
 func (e *EDNS0_LOCAL) String() string {
 	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
 }
+func (e *EDNS0_LOCAL) copy() EDNS0 {
+	b := make([]byte, len(e.Data))
+	copy(b, e.Data)
+	return &EDNS0_LOCAL{e.Code, b}
+}
 
 func (e *EDNS0_LOCAL) pack() ([]byte, error) {
 	b := make([]byte, len(e.Data))
@@ -612,6 +654,7 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
 	}
 	return
 }
+func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
 
 // EDNS0_PADDING option is used to add padding to a request/response. The default
 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
@@ -625,3 +668,8 @@ func (e *EDNS0_PADDING) Option() uint16        { return EDNS0PADDING }
 func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
 func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
 func (e *EDNS0_PADDING) String() string        { return fmt.Sprintf("%0X", e.Padding) }
+func (e *EDNS0_PADDING) copy() EDNS0 {
+	b := make([]byte, len(e.Padding))
+	copy(b, e.Padding)
+	return &EDNS0_PADDING{b}
+}

+ 7 - 1
libnetwork/vendor/github.com/miekg/dns/format.go

@@ -20,7 +20,7 @@ func Field(r RR, i int) string {
 		return ""
 	}
 	d := reflect.ValueOf(r).Elem().Field(i)
-	switch k := d.Kind(); k {
+	switch d.Kind() {
 	case reflect.String:
 		return d.String()
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -31,6 +31,9 @@ func Field(r RR, i int) string {
 		switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
 		case `dns:"a"`:
 			// TODO(miek): Hmm store this as 16 bytes
+			if d.Len() < net.IPv4len {
+				return ""
+			}
 			if d.Len() < net.IPv6len {
 				return net.IPv4(byte(d.Index(0).Uint()),
 					byte(d.Index(1).Uint()),
@@ -42,6 +45,9 @@ func Field(r RR, i int) string {
 				byte(d.Index(14).Uint()),
 				byte(d.Index(15).Uint())).String()
 		case `dns:"aaaa"`:
+			if d.Len() < net.IPv6len {
+				return ""
+			}
 			return net.IP{
 				byte(d.Index(0).Uint()),
 				byte(d.Index(1).Uint()),

+ 10 - 1
libnetwork/vendor/github.com/miekg/dns/fuzz.go

@@ -2,6 +2,8 @@
 
 package dns
 
+import "strings"
+
 func Fuzz(data []byte) int {
 	msg := new(Msg)
 
@@ -16,7 +18,14 @@ func Fuzz(data []byte) int {
 }
 
 func FuzzNewRR(data []byte) int {
-	if _, err := NewRR(string(data)); err != nil {
+	str := string(data)
+	// Do not fuzz lines that include the $INCLUDE keyword and hint the fuzzer
+	// at avoiding them.
+	// See GH#1025 for context.
+	if strings.Contains(strings.ToUpper(str), "$INCLUDE") {
+		return -1
+	}
+	if _, err := NewRR(str); err != nil {
 		return 0
 	}
 	return 1

+ 204 - 116
libnetwork/vendor/github.com/miekg/dns/generate.go

@@ -2,8 +2,8 @@ package dns
 
 import (
 	"bytes"
-	"errors"
 	"fmt"
+	"io"
 	"strconv"
 	"strings"
 )
@@ -18,142 +18,230 @@ import (
 // * rhs (rdata)
 // But we are lazy here, only the range is parsed *all* occurrences
 // of $ after that are interpreted.
-// Any error are returned as a string value, the empty string signals
-// "no error".
-func generate(l lex, c chan lex, t chan *Token, o string) string {
+func (zp *ZoneParser) generate(l lex) (RR, bool) {
+	token := l.token
 	step := 1
-	if i := strings.IndexAny(l.token, "/"); i != -1 {
-		if i+1 == len(l.token) {
-			return "bad step in $GENERATE range"
+	if i := strings.IndexByte(token, '/'); i >= 0 {
+		if i+1 == len(token) {
+			return zp.setParseError("bad step in $GENERATE range", l)
 		}
-		if s, err := strconv.Atoi(l.token[i+1:]); err == nil {
-			if s < 0 {
-				return "bad step in $GENERATE range"
-			}
-			step = s
-		} else {
-			return "bad step in $GENERATE range"
+
+		s, err := strconv.Atoi(token[i+1:])
+		if err != nil || s <= 0 {
+			return zp.setParseError("bad step in $GENERATE range", l)
 		}
-		l.token = l.token[:i]
+
+		step = s
+		token = token[:i]
 	}
-	sx := strings.SplitN(l.token, "-", 2)
+
+	sx := strings.SplitN(token, "-", 2)
 	if len(sx) != 2 {
-		return "bad start-stop in $GENERATE range"
+		return zp.setParseError("bad start-stop in $GENERATE range", l)
 	}
+
 	start, err := strconv.Atoi(sx[0])
 	if err != nil {
-		return "bad start in $GENERATE range"
+		return zp.setParseError("bad start in $GENERATE range", l)
 	}
+
 	end, err := strconv.Atoi(sx[1])
 	if err != nil {
-		return "bad stop in $GENERATE range"
+		return zp.setParseError("bad stop in $GENERATE range", l)
+	}
+	if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
+		return zp.setParseError("bad range in $GENERATE range", l)
 	}
-	if end < 0 || start < 0 || end < start {
-		return "bad range in $GENERATE range"
+
+	// _BLANK
+	l, ok := zp.c.Next()
+	if !ok || l.value != zBlank {
+		return zp.setParseError("garbage after $GENERATE range", l)
 	}
 
-	<-c // _BLANK
 	// Create a complete new string, which we then parse again.
-	s := ""
-BuildRR:
-	l = <-c
-	if l.value != zNewline && l.value != zEOF {
+	var s string
+	for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() {
+		if l.err {
+			return zp.setParseError("bad data in $GENERATE directive", l)
+		}
+		if l.value == zNewline {
+			break
+		}
+
 		s += l.token
-		goto BuildRR
-	}
-	for i := start; i <= end; i += step {
-		var (
-			escape bool
-			dom    bytes.Buffer
-			mod    string
-			err    error
-			offset int
-		)
-
-		for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
-			switch s[j] {
-			case '\\':
-				if escape {
-					dom.WriteByte('\\')
-					escape = false
-					continue
-				}
-				escape = true
-			case '$':
-				mod = "%d"
-				offset = 0
-				if escape {
-					dom.WriteByte('$')
-					escape = false
-					continue
-				}
-				escape = false
-				if j+1 >= len(s) { // End of the string
-					dom.WriteString(fmt.Sprintf(mod, i+offset))
-					continue
-				} else {
-					if s[j+1] == '$' {
-						dom.WriteByte('$')
-						j++
-						continue
-					}
-				}
-				// Search for { and }
-				if s[j+1] == '{' { // Modifier block
-					sep := strings.Index(s[j+2:], "}")
-					if sep == -1 {
-						return "bad modifier in $GENERATE"
-					}
-					mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
-					if err != nil {
-						return err.Error()
-					}
-					j += 2 + sep // Jump to it
-				}
-				dom.WriteString(fmt.Sprintf(mod, i+offset))
-			default:
-				if escape { // Pretty useless here
-					escape = false
-					continue
-				}
-				dom.WriteByte(s[j])
+	}
+
+	r := &generateReader{
+		s: s,
+
+		cur:   start,
+		start: start,
+		end:   end,
+		step:  step,
+
+		file: zp.file,
+		lex:  &l,
+	}
+	zp.sub = NewZoneParser(r, zp.origin, zp.file)
+	zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
+	zp.sub.generateDisallowed = true
+	zp.sub.SetDefaultTTL(defaultTtl)
+	return zp.subNext()
+}
+
+type generateReader struct {
+	s  string
+	si int
+
+	cur   int
+	start int
+	end   int
+	step  int
+
+	mod bytes.Buffer
+
+	escape bool
+
+	eof bool
+
+	file string
+	lex  *lex
+}
+
+func (r *generateReader) parseError(msg string, end int) *ParseError {
+	r.eof = true // Make errors sticky.
+
+	l := *r.lex
+	l.token = r.s[r.si-1 : end]
+	l.column += r.si // l.column starts one zBLANK before r.s
+
+	return &ParseError{r.file, msg, l}
+}
+
+func (r *generateReader) Read(p []byte) (int, error) {
+	// NewZLexer, through NewZoneParser, should use ReadByte and
+	// not end up here.
+
+	panic("not implemented")
+}
+
+func (r *generateReader) ReadByte() (byte, error) {
+	if r.eof {
+		return 0, io.EOF
+	}
+	if r.mod.Len() > 0 {
+		return r.mod.ReadByte()
+	}
+
+	if r.si >= len(r.s) {
+		r.si = 0
+		r.cur += r.step
+
+		r.eof = r.cur > r.end || r.cur < 0
+		return '\n', nil
+	}
+
+	si := r.si
+	r.si++
+
+	switch r.s[si] {
+	case '\\':
+		if r.escape {
+			r.escape = false
+			return '\\', nil
+		}
+
+		r.escape = true
+		return r.ReadByte()
+	case '$':
+		if r.escape {
+			r.escape = false
+			return '$', nil
+		}
+
+		mod := "%d"
+
+		if si >= len(r.s)-1 {
+			// End of the string
+			fmt.Fprintf(&r.mod, mod, r.cur)
+			return r.mod.ReadByte()
+		}
+
+		if r.s[si+1] == '$' {
+			r.si++
+			return '$', nil
+		}
+
+		var offset int
+
+		// Search for { and }
+		if r.s[si+1] == '{' {
+			// Modifier block
+			sep := strings.Index(r.s[si+2:], "}")
+			if sep < 0 {
+				return 0, r.parseError("bad modifier in $GENERATE", len(r.s))
 			}
+
+			var errMsg string
+			mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep])
+			if errMsg != "" {
+				return 0, r.parseError(errMsg, si+3+sep)
+			}
+			if r.start+offset < 0 || r.end+offset > 1<<31-1 {
+				return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
+			}
+
+			r.si += 2 + sep // Jump to it
 		}
-		// Re-parse the RR and send it on the current channel t
-		rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String())
-		if err != nil {
-			return err.Error()
+
+		fmt.Fprintf(&r.mod, mod, r.cur+offset)
+		return r.mod.ReadByte()
+	default:
+		if r.escape { // Pretty useless here
+			r.escape = false
+			return r.ReadByte()
 		}
-		t <- &Token{RR: rx}
-		// Its more efficient to first built the rrlist and then parse it in
-		// one go! But is this a problem?
+
+		return r.s[si], nil
 	}
-	return ""
 }
 
 // Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
-func modToPrintf(s string) (string, int, error) {
-	xs := strings.SplitN(s, ",", 3)
-	if len(xs) != 3 {
-		return "", 0, errors.New("bad modifier in $GENERATE")
-	}
-	// 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" {
-		return "", 0, errors.New("bad base in $GENERATE")
-	}
-	offset, err := strconv.Atoi(xs[0])
-	if err != nil || offset > 255 {
-		return "", 0, errors.New("bad offset in $GENERATE")
-	}
-	width, err := strconv.Atoi(xs[1])
-	if err != nil || width > 255 {
-		return "", offset, errors.New("bad width in $GENERATE")
-	}
-	switch {
-	case width < 0:
-		return "", offset, errors.New("bad width in $GENERATE")
-	case width == 0:
-		return "%" + xs[1] + xs[2], offset, nil
-	}
-	return "%0" + xs[1] + xs[2], offset, nil
+func modToPrintf(s string) (string, int, string) {
+	// Modifier is { offset [ ,width [ ,base ] ] } - provide default
+	// values for optional width and type, if necessary.
+	var offStr, widthStr, base string
+	switch xs := strings.Split(s, ","); len(xs) {
+	case 1:
+		offStr, widthStr, base = xs[0], "0", "d"
+	case 2:
+		offStr, widthStr, base = xs[0], xs[1], "d"
+	case 3:
+		offStr, widthStr, base = xs[0], xs[1], xs[2]
+	default:
+		return "", 0, "bad modifier in $GENERATE"
+	}
+
+	switch base {
+	case "o", "d", "x", "X":
+	default:
+		return "", 0, "bad base in $GENERATE"
+	}
+
+	offset, err := strconv.Atoi(offStr)
+	if err != nil {
+		return "", 0, "bad offset in $GENERATE"
+	}
+
+	width, err := strconv.Atoi(widthStr)
+	if err != nil || width < 0 || width > 255 {
+		return "", 0, "bad width in $GENERATE"
+	}
+
+	if width == 0 {
+		return "%" + base, offset, ""
+	}
+
+	return "%0" + widthStr + base, offset, ""
 }

+ 11 - 0
libnetwork/vendor/github.com/miekg/dns/go.mod

@@ -0,0 +1,11 @@
+module github.com/miekg/dns
+
+go 1.12
+
+require (
+	golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
+	golang.org/x/net v0.0.0-20190923162816-aa69164e4478
+	golang.org/x/sync v0.0.0-20190423024810-112230192c58
+	golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe
+	golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect
+)

+ 47 - 26
libnetwork/vendor/github.com/miekg/dns/labels.go

@@ -16,7 +16,7 @@ func SplitDomainName(s string) (labels []string) {
 	fqdnEnd := 0 // offset of the final '.' or the length of the name
 	idx := Split(s)
 	begin := 0
-	if s[len(s)-1] == '.' {
+	if IsFqdn(s) {
 		fqdnEnd = len(s) - 1
 	} else {
 		fqdnEnd = len(s)
@@ -28,16 +28,13 @@ func SplitDomainName(s string) (labels []string) {
 	case 1:
 		// no-op
 	default:
-		end := 0
-		for i := 1; i < len(idx); i++ {
-			end = idx[i]
+		for _, end := range idx[1:] {
 			labels = append(labels, s[begin:end-1])
 			begin = end
 		}
 	}
 
-	labels = append(labels, s[begin:fqdnEnd])
-	return labels
+	return append(labels, s[begin:fqdnEnd])
 }
 
 // CompareDomainName compares the names s1 and s2 and
@@ -129,20 +126,23 @@ func Split(s string) []int {
 // The bool end is true when the end of the string has been reached.
 // Also see PrevLabel.
 func NextLabel(s string, offset int) (i int, end bool) {
-	quote := false
+	if s == "" {
+		return 0, true
+	}
 	for i = offset; i < len(s)-1; i++ {
-		switch s[i] {
-		case '\\':
-			quote = !quote
-		default:
-			quote = false
-		case '.':
-			if quote {
-				quote = !quote
-				continue
-			}
-			return i + 1, false
+		if s[i] != '.' {
+			continue
+		}
+		j := i - 1
+		for j >= 0 && s[j] == '\\' {
+			j--
+		}
+
+		if (j-i)%2 == 0 {
+			continue
 		}
+
+		return i + 1, false
 	}
 	return i + 1, true
 }
@@ -152,17 +152,38 @@ func NextLabel(s string, offset int) (i int, end bool) {
 // The bool start is true when the start of the string has been overshot.
 // Also see NextLabel.
 func PrevLabel(s string, n int) (i int, start bool) {
+	if s == "" {
+		return 0, true
+	}
 	if n == 0 {
 		return len(s), false
 	}
-	lab := Split(s)
-	if lab == nil {
-		return 0, true
+
+	l := len(s) - 1
+	if s[l] == '.' {
+		l--
 	}
-	if n > len(lab) {
-		return 0, true
+
+	for ; l >= 0 && n > 0; l-- {
+		if s[l] != '.' {
+			continue
+		}
+		j := l - 1
+		for j >= 0 && s[j] == '\\' {
+			j--
+		}
+
+		if (j-l)%2 == 0 {
+			continue
+		}
+
+		n--
+		if n == 0 {
+			return l + 1, false
+		}
 	}
-	return lab[len(lab)-n], false
+
+	return 0, n > 1
 }
 
 // equal compares a and b while ignoring case. It returns true when equal otherwise false.
@@ -178,10 +199,10 @@ func equal(a, b string) bool {
 		ai := a[i]
 		bi := b[i]
 		if ai >= 'A' && ai <= 'Z' {
-			ai |= ('a' - 'A')
+			ai |= 'a' - 'A'
 		}
 		if bi >= 'A' && bi <= 'Z' {
-			bi |= ('a' - 'A')
+			bi |= 'a' - 'A'
 		}
 		if ai != bi {
 			return false

+ 44 - 0
libnetwork/vendor/github.com/miekg/dns/listen_go111.go

@@ -0,0 +1,44 @@
+// +build go1.11
+// +build aix darwin dragonfly freebsd linux netbsd openbsd
+
+package dns
+
+import (
+	"context"
+	"net"
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+const supportsReusePort = true
+
+func reuseportControl(network, address string, c syscall.RawConn) error {
+	var opErr error
+	err := c.Control(func(fd uintptr) {
+		opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
+	})
+	if err != nil {
+		return err
+	}
+
+	return opErr
+}
+
+func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
+	var lc net.ListenConfig
+	if reuseport {
+		lc.Control = reuseportControl
+	}
+
+	return lc.Listen(context.Background(), network, addr)
+}
+
+func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
+	var lc net.ListenConfig
+	if reuseport {
+		lc.Control = reuseportControl
+	}
+
+	return lc.ListenPacket(context.Background(), network, addr)
+}

+ 23 - 0
libnetwork/vendor/github.com/miekg/dns/listen_go_not111.go

@@ -0,0 +1,23 @@
+// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
+
+package dns
+
+import "net"
+
+const supportsReusePort = false
+
+func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
+	if reuseport {
+		// TODO(tmthrgd): return an error?
+	}
+
+	return net.Listen(network, addr)
+}
+
+func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
+	if reuseport {
+		// TODO(tmthrgd): return an error?
+	}
+
+	return net.ListenPacket(network, addr)
+}

ファイルの差分が大きいため隠しています
+ 367 - 385
libnetwork/vendor/github.com/miekg/dns/msg.go


+ 225 - 52
libnetwork/vendor/github.com/miekg/dns/msg_helpers.go

@@ -6,7 +6,7 @@ import (
 	"encoding/binary"
 	"encoding/hex"
 	"net"
-	"strconv"
+	"strings"
 )
 
 // helper functions called from the generated zmsg.go
@@ -25,12 +25,13 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
 }
 
 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:
+		// 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"}
+		}
+
 		copy(msg[off:], a.To4())
 		off += net.IPv4len
 	case 0:
@@ -51,12 +52,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
 }
 
 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:
+		if off+net.IPv6len > len(msg) {
+			return len(msg), &Error{err: "overflow packing aaaa"}
+		}
+
 		copy(msg[off:], aaaa)
 		off += net.IPv6len
 	case 0:
@@ -99,14 +100,14 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
 	return hdr, off, msg, err
 }
 
-// pack packs an RR header, returning the offset to the end of the header.
+// packHeader 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) {
+func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
 	if off == len(msg) {
 		return off, nil
 	}
 
-	off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
+	off, err := packDomainName(hdr.Name, msg, off, compression, compress)
 	if err != nil {
 		return len(msg), err
 	}
@@ -122,7 +123,7 @@ func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compr
 	if err != nil {
 		return len(msg), err
 	}
-	off, err = packUint16(hdr.Rdlength, msg, off)
+	off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
 	if err != nil {
 		return len(msg), err
 	}
@@ -141,20 +142,24 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b
 	return msg[:lenrd], nil
 }
 
+var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
+
 func fromBase32(s []byte) (buf []byte, err error) {
 	for i, b := range s {
 		if b >= 'a' && b <= 'z' {
 			s[i] = b - 32
 		}
 	}
-	buflen := base32.HexEncoding.DecodedLen(len(s))
+	buflen := base32HexNoPadEncoding.DecodedLen(len(s))
 	buf = make([]byte, buflen)
-	n, err := base32.HexEncoding.Decode(buf, s)
+	n, err := base32HexNoPadEncoding.Decode(buf, s)
 	buf = buf[:n]
 	return
 }
 
-func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) }
+func toBase32(b []byte) string {
+	return base32HexNoPadEncoding.EncodeToString(b)
+}
 
 func fromBase64(s []byte) (buf []byte, err error) {
 	buflen := base64.StdEncoding.DecodedLen(len(s))
@@ -173,14 +178,14 @@ 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
+	return 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)
+	msg[off] = i
 	return off + 1, nil
 }
 
@@ -219,8 +224,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
 		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])))
+	i = 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
 }
@@ -260,32 +265,36 @@ func unpackString(msg []byte, off int) (string, int, error) {
 		return "", off, &Error{err: "overflow unpacking txt"}
 	}
 	l := int(msg[off])
-	if off+l+1 > len(msg) {
+	off++
+	if off+l > 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)
-		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)
+	var s strings.Builder
+	consumed := 0
+	for i, b := range msg[off : off+l] {
+		switch {
+		case b == '"' || b == '\\':
+			if consumed == 0 {
+				s.Grow(l * 2)
 			}
+			s.Write(msg[off+consumed : off+i])
+			s.WriteByte('\\')
+			s.WriteByte(b)
+			consumed = i + 1
+		case b < ' ' || b > '~': // unprintable
+			if consumed == 0 {
+				s.Grow(l * 2)
+			}
+			s.Write(msg[off+consumed : off+i])
+			s.WriteString(escapeByte(b))
+			consumed = i + 1
 		}
 	}
-	off += 1 + l
-	return string(s), off, nil
+	if consumed == 0 { // no escaping needed
+		return string(msg[off : off+l]), off + l, nil
+	}
+	s.Write(msg[off+consumed : off+l])
+	return s.String(), off + l, nil
 }
 
 func packString(s string, msg []byte, off int) (int, error) {
@@ -359,7 +368,7 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
 	if err != nil {
 		return len(msg), err
 	}
-	if off+(len(h)) > len(msg) {
+	if off+len(h) > len(msg) {
 		return len(msg), &Error{err: "overflow packing hex"}
 	}
 	copy(msg[off:off+len(h)], h)
@@ -367,6 +376,22 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
 	return off, nil
 }
 
+func unpackStringAny(msg []byte, off, end int) (string, int, error) {
+	if end > len(msg) {
+		return "", len(msg), &Error{err: "overflow unpacking anything"}
+	}
+	return string(msg[off:end]), end, nil
+}
+
+func packStringAny(s string, msg []byte, off int) (int, error) {
+	if off+len(s) > len(msg) {
+		return len(msg), &Error{err: "overflow packing anything"}
+	}
+	copy(msg[off:off+len(s)], s)
+	off += len(s)
+	return off, nil
+}
+
 func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
 	txt, off, err := unpackTxt(msg, off)
 	if err != nil {
@@ -387,7 +412,7 @@ func packStringTxt(s []string, msg []byte, off int) (int, error) {
 func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
 	var edns []EDNS0
 Option:
-	code := uint16(0)
+	var code uint16
 	if off+4 > len(msg) {
 		return nil, len(msg), &Error{err: "overflow unpacking opt"}
 	}
@@ -420,6 +445,13 @@ Option:
 		}
 		edns = append(edns, e)
 		off += int(optlen)
+	case EDNS0EXPIRE:
+		e := new(EDNS0_EXPIRE)
+		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 {
@@ -482,7 +514,7 @@ Option:
 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) {
+		if err != nil || off+4 > len(msg) {
 			return len(msg), &Error{err: "overflow packing opt"}
 		}
 		binary.BigEndian.PutUint16(msg[off:], el.Option())      // Option code
@@ -541,8 +573,7 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 		}
 
 		// Walk the bytes in the window and extract the type bits
-		for j := 0; j < length; j++ {
-			b := msg[off+j]
+		for j, b := range msg[off : off+length] {
 			// Check the bits one by one, and set the type
 			if b&0x80 == 0x80 {
 				nsec = append(nsec, uint16(window*256+j*8+0))
@@ -575,13 +606,35 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 	return nsec, off, nil
 }
 
+// typeBitMapLen is a helper function which computes the "maximum" length of
+// a the NSEC Type BitMap field.
+func typeBitMapLen(bitmap []uint16) int {
+	var l int
+	var lastwindow, lastlength uint16
+	for _, t := range bitmap {
+		window := t / 256
+		length := (t-window*256)/8 + 1
+		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
+			l += int(lastlength) + 2
+			lastlength = 0
+		}
+		if window < lastwindow || length < lastlength {
+			// packDataNsec would return Error{err: "nsec bits out of order"} here, but
+			// when computing the length, we want do be liberal.
+			continue
+		}
+		lastwindow, lastlength = window, length
+	}
+	l += int(lastlength) + 2
+	return l
+}
+
 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]
+	for _, t := range bitmap {
 		window := t / 256
 		length := (t-window*256)/8 + 1
 		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
@@ -599,7 +652,7 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
 		// 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)))
+		msg[off+1+int(length)] |= byte(1 << (7 - t%8))
 		lastwindow, lastlength = window, length
 	}
 	off += int(lastlength) + 2
@@ -625,13 +678,133 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
 	return servers, off, nil
 }
 
-func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
+	var err error
+	for _, name := range names {
+		off, err = packDomainName(name, msg, off, compression, compress)
+		if err != nil {
+			return len(msg), err
+		}
+	}
+	return off, nil
+}
+
+func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
 	var err error
-	for j := 0; j < len(names); j++ {
-		off, err = PackDomainName(names[j], msg, off, compression, false && compress)
+	for i := range data {
+		off, err = packDataAplPrefix(&data[i], msg, off)
 		if err != nil {
 			return len(msg), err
 		}
 	}
 	return off, nil
 }
+
+func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
+	if len(p.Network.IP) != len(p.Network.Mask) {
+		return len(msg), &Error{err: "address and mask lengths don't match"}
+	}
+
+	var err error
+	prefix, _ := p.Network.Mask.Size()
+	addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		off, err = packUint16(1, msg, off)
+	case net.IPv6len:
+		off, err = packUint16(2, msg, off)
+	default:
+		err = &Error{err: "unrecognized address family"}
+	}
+	if err != nil {
+		return len(msg), err
+	}
+
+	off, err = packUint8(uint8(prefix), msg, off)
+	if err != nil {
+		return len(msg), err
+	}
+
+	var n uint8
+	if p.Negation {
+		n = 0x80
+	}
+	adflen := uint8(len(addr)) & 0x7f
+	off, err = packUint8(n|adflen, msg, off)
+	if err != nil {
+		return len(msg), err
+	}
+
+	if off+len(addr) > len(msg) {
+		return len(msg), &Error{err: "overflow packing APL prefix"}
+	}
+	off += copy(msg[off:], addr)
+
+	return off, nil
+}
+
+func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
+	var result []APLPrefix
+	for off < len(msg) {
+		prefix, end, err := unpackDataAplPrefix(msg, off)
+		if err != nil {
+			return nil, len(msg), err
+		}
+		off = end
+		result = append(result, prefix)
+	}
+	return result, off, nil
+}
+
+func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
+	family, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+	prefix, off, err := unpackUint8(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+	nlen, off, err := unpackUint8(msg, off)
+	if err != nil {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
+	}
+
+	var ip []byte
+	switch family {
+	case 1:
+		ip = make([]byte, net.IPv4len)
+	case 2:
+		ip = make([]byte, net.IPv6len)
+	default:
+		return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
+	}
+	if int(prefix) > 8*len(ip) {
+		return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
+	}
+
+	afdlen := int(nlen & 0x7f)
+	if (int(prefix)+7)/8 != afdlen {
+		return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"}
+	}
+	if off+afdlen > len(msg) {
+		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
+	}
+	off += copy(ip, msg[off:off+afdlen])
+	if prefix%8 > 0 {
+		last := ip[afdlen-1]
+		zero := uint8(0xff) >> (prefix % 8)
+		if last&zero > 0 {
+			return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
+		}
+	}
+
+	return APLPrefix{
+		Negation: (nlen & 0x80) != 0,
+		Network: net.IPNet{
+			IP:   ip,
+			Mask: net.CIDRMask(int(prefix), 8*len(ip)),
+		},
+	}, off, nil
+}

+ 111 - 0
libnetwork/vendor/github.com/miekg/dns/msg_truncate.go

@@ -0,0 +1,111 @@
+package dns
+
+// Truncate ensures the reply message will fit into the requested buffer
+// size by removing records that exceed the requested size.
+//
+// It will first check if the reply fits without compression and then with
+// compression. If it won't fit with compression, Truncate then walks the
+// record adding as many records as possible without exceeding the
+// requested buffer size.
+//
+// The TC bit will be set if any records were excluded from the message.
+// This indicates to that the client should retry over TCP.
+//
+// According to RFC 2181, the TC bit should only be set if not all of the
+// "required" RRs can be included in the response. Unfortunately, we have
+// no way of knowing which RRs are required so we set the TC bit if any RR
+// had to be omitted from the response.
+//
+// The appropriate buffer size can be retrieved from the requests OPT
+// record, if present, and is transport specific otherwise. dns.MinMsgSize
+// should be used for UDP requests without an OPT record, and
+// dns.MaxMsgSize for TCP requests without an OPT record.
+func (dns *Msg) Truncate(size int) {
+	if dns.IsTsig() != nil {
+		// To simplify this implementation, we don't perform
+		// truncation on responses with a TSIG record.
+		return
+	}
+
+	// RFC 6891 mandates that the payload size in an OPT record
+	// less than 512 bytes must be treated as equal to 512 bytes.
+	//
+	// For ease of use, we impose that restriction here.
+	if size < 512 {
+		size = 512
+	}
+
+	l := msgLenWithCompressionMap(dns, nil) // uncompressed length
+	if l <= size {
+		// Don't waste effort compressing this message.
+		dns.Compress = false
+		return
+	}
+
+	dns.Compress = true
+
+	edns0 := dns.popEdns0()
+	if edns0 != nil {
+		// Account for the OPT record that gets added at the end,
+		// by subtracting that length from our budget.
+		//
+		// The EDNS(0) OPT record must have the root domain and
+		// it's length is thus unaffected by compression.
+		size -= Len(edns0)
+	}
+
+	compression := make(map[string]struct{})
+
+	l = headerSize
+	for _, r := range dns.Question {
+		l += r.len(l, compression)
+	}
+
+	var numAnswer int
+	if l < size {
+		l, numAnswer = truncateLoop(dns.Answer, size, l, compression)
+	}
+
+	var numNS int
+	if l < size {
+		l, numNS = truncateLoop(dns.Ns, size, l, compression)
+	}
+
+	var numExtra int
+	if l < size {
+		l, numExtra = truncateLoop(dns.Extra, size, l, compression)
+	}
+
+	// See the function documentation for when we set this.
+	dns.Truncated = len(dns.Answer) > numAnswer ||
+		len(dns.Ns) > numNS || len(dns.Extra) > numExtra
+
+	dns.Answer = dns.Answer[:numAnswer]
+	dns.Ns = dns.Ns[:numNS]
+	dns.Extra = dns.Extra[:numExtra]
+
+	if edns0 != nil {
+		// Add the OPT record back onto the additional section.
+		dns.Extra = append(dns.Extra, edns0)
+	}
+}
+
+func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) {
+	for i, r := range rrs {
+		if r == nil {
+			continue
+		}
+
+		l += r.len(l, compression)
+		if l > size {
+			// Return size, rather than l prior to this record,
+			// to prevent any further records being added.
+			return size, i
+		}
+		if l == size {
+			return l, i + 1
+		}
+	}
+
+	return l, len(rrs)
+}

+ 18 - 29
libnetwork/vendor/github.com/miekg/dns/nsecx.go

@@ -2,49 +2,44 @@ package dns
 
 import (
 	"crypto/sha1"
-	"hash"
+	"encoding/hex"
 	"strings"
 )
 
-type saltWireFmt struct {
-	Salt string `dns:"size-hex"`
-}
-
 // HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
 func HashName(label string, ha uint8, iter uint16, salt string) string {
-	saltwire := new(saltWireFmt)
-	saltwire.Salt = salt
-	wire := make([]byte, DefaultMsgSize)
-	n, err := packSaltWire(saltwire, wire)
+	if ha != SHA1 {
+		return ""
+	}
+
+	wireSalt := make([]byte, hex.DecodedLen(len(salt)))
+	n, err := packStringHex(salt, wireSalt, 0)
 	if err != nil {
 		return ""
 	}
-	wire = wire[:n]
+	wireSalt = wireSalt[:n]
+
 	name := make([]byte, 255)
 	off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
 	if err != nil {
 		return ""
 	}
 	name = name[:off]
-	var s hash.Hash
-	switch ha {
-	case SHA1:
-		s = sha1.New()
-	default:
-		return ""
-	}
 
+	s := sha1.New()
 	// k = 0
 	s.Write(name)
-	s.Write(wire)
+	s.Write(wireSalt)
 	nsec3 := s.Sum(nil)
+
 	// k > 0
 	for k := uint16(0); k < iter; k++ {
 		s.Reset()
 		s.Write(nsec3)
-		s.Write(wire)
+		s.Write(wireSalt)
 		nsec3 = s.Sum(nsec3[:0])
 	}
+
 	return toBase32(nsec3)
 }
 
@@ -63,8 +58,10 @@ func (rr *NSEC3) Cover(name string) bool {
 	}
 
 	nextHash := rr.NextDomain
-	if ownerHash == nextHash { // empty interval
-		return false
+
+	// if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash
+	if ownerHash == nextHash && nameHash != ownerHash { // empty interval
+		return true
 	}
 	if ownerHash > nextHash { // end of zone
 		if nameHash > ownerHash { // covered since there is nothing after ownerHash
@@ -96,11 +93,3 @@ func (rr *NSEC3) Match(name string) bool {
 	}
 	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
-}

+ 47 - 81
libnetwork/vendor/github.com/miekg/dns/privaterr.go

@@ -1,9 +1,6 @@
 package dns
 
-import (
-	"fmt"
-	"strings"
-)
+import "strings"
 
 // PrivateRdata is an interface used for implementing "Private Use" RR types, see
 // RFC 6895. This allows one to experiment with new RR types, without requesting an
@@ -18,7 +15,7 @@ type PrivateRdata interface {
 	// Unpack is used when unpacking a private RR from a buffer.
 	// TODO(miek): diff. signature than Pack, see edns0.go for instance.
 	Unpack([]byte) (int, error)
-	// Copy copies the Rdata.
+	// Copy copies the Rdata into the PrivateRdata argument.
 	Copy(PrivateRdata) error
 	// Len returns the length in octets of the Rdata.
 	Len() int
@@ -29,21 +26,8 @@ type PrivateRdata interface {
 type PrivateRR struct {
 	Hdr  RR_Header
 	Data PrivateRdata
-}
-
-func mkPrivateRR(rrtype uint16) *PrivateRR {
-	// Panics if RR is not an instance of PrivateRR.
-	rrfunc, ok := TypeToRR[rrtype]
-	if !ok {
-		panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
-	}
 
-	anyrr := rrfunc()
-	switch rr := anyrr.(type) {
-	case *PrivateRR:
-		return rr
-	}
-	panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
+	generator func() PrivateRdata // for copy
 }
 
 // Header return the RR header of r.
@@ -52,97 +36,79 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
 func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
 
 // Private len and copy parts to satisfy RR interface.
-func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
+func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
+	l := r.Hdr.len(off, compression)
+	l += r.Data.Len()
+	return l
+}
+
 func (r *PrivateRR) copy() RR {
 	// make new RR like this:
-	rr := mkPrivateRR(r.Hdr.Rrtype)
-	rr.Hdr = r.Hdr
+	rr := &PrivateRR{r.Hdr, r.generator(), r.generator}
 
-	err := r.Data.Copy(rr.Data)
-	if err != nil {
-		panic("dns: got value that could not be used to copy Private rdata")
+	if err := r.Data.Copy(rr.Data); err != nil {
+		panic("dns: got value that could not be used to copy Private rdata: " + err.Error())
 	}
+
 	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
+
+func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
 	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
-// string and numeric representation of private RR type and generator function as argument.
-func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
-	rtypestr = strings.ToUpper(rtypestr)
-
-	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
-	TypeToString[rtype] = rtypestr
-	StringToType[rtypestr] = rtype
+func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
+	off1, err := r.Data.Unpack(msg[off:])
+	off += off1
+	return off, err
+}
 
-	typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
-		if noRdata(h) {
-			return &h, off, nil
+func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError {
+	var l lex
+	text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
+Fetch:
+	for {
+		// TODO(miek): we could also be returning _QUOTE, this might or might not
+		// be an issue (basically parsing TXT becomes hard)
+		switch l, _ = c.Next(); l.value {
+		case zNewline, zEOF:
+			break Fetch
+		case zString:
+			text = append(text, l.token)
 		}
-		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
+	err := r.Data.Parse(text)
+	if err != nil {
+		return &ParseError{"", err.Error(), l}
 	}
 
-	setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
-		rr := mkPrivateRR(h.Rrtype)
-		rr.Hdr = h
-
-		var l lex
-		text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
-	Fetch:
-		for {
-			// TODO(miek): we could also be returning _QUOTE, this might or might not
-			// be an issue (basically parsing TXT becomes hard)
-			switch l = <-c; l.value {
-			case zNewline, zEOF:
-				break Fetch
-			case zString:
-				text = append(text, l.token)
-			}
-		}
+	return nil
+}
 
-		err := rr.Data.Parse(text)
-		if err != nil {
-			return nil, &ParseError{f, err.Error(), l}, ""
-		}
+func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
 
-		return rr, nil, ""
-	}
+// PrivateHandle registers a private resource record type. It requires
+// string and numeric representation of private RR type and generator function as argument.
+func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
+	rtypestr = strings.ToUpper(rtypestr)
 
-	typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
+	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
+	TypeToString[rtype] = rtypestr
+	StringToType[rtypestr] = rtype
 }
 
-// PrivateHandleRemove removes defenitions required to support private RR type.
+// PrivateHandleRemove removes definitions required to support private RR type.
 func PrivateHandleRemove(rtype uint16) {
 	rtypestr, ok := TypeToString[rtype]
 	if ok {
 		delete(TypeToRR, rtype)
 		delete(TypeToString, rtype)
-		delete(typeToparserFunc, rtype)
 		delete(StringToType, rtypestr)
-		delete(typeToUnpack, rtype)
 	}
-	return
 }

+ 0 - 49
libnetwork/vendor/github.com/miekg/dns/rawmsg.go

@@ -1,49 +0,0 @@
-package dns
-
-import "encoding/binary"
-
-// rawSetRdlength sets the rdlength in the header of
-// the RR. The offset 'off' must be positioned at the
-// start of the header of the RR, 'end' must be the
-// end of the RR.
-func rawSetRdlength(msg []byte, off, end int) bool {
-	l := len(msg)
-Loop:
-	for {
-		if off+1 > l {
-			return false
-		}
-		c := int(msg[off])
-		off++
-		switch c & 0xC0 {
-		case 0x00:
-			if c == 0x00 {
-				// End of the domainname
-				break Loop
-			}
-			if off+c > l {
-				return false
-			}
-			off += c
-
-		case 0xC0:
-			// pointer, next byte included, ends domainname
-			off++
-			break Loop
-		}
-	}
-	// The domainname has been seen, we at the start of the fixed part in the header.
-	// Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
-	off += 2 + 2 + 4
-	if off+2 > l {
-		return false
-	}
-	//off+1 is the end of the header, 'end' is the end of the rr
-	//so 'end' - 'off+2' is the length of the rdata
-	rdatalen := end - (off + 2)
-	if rdatalen > 0xFFFF {
-		return false
-	}
-	binary.BigEndian.PutUint16(msg[off:], uint16(rdatalen))
-	return true
-}

+ 14 - 0
libnetwork/vendor/github.com/miekg/dns/reverse.go

@@ -12,6 +12,20 @@ var StringToOpcode = reverseInt(OpcodeToString)
 // StringToRcode is a map of rcodes to strings.
 var StringToRcode = reverseInt(RcodeToString)
 
+func init() {
+	// Preserve previous NOTIMP typo, see github.com/miekg/dns/issues/733.
+	StringToRcode["NOTIMPL"] = RcodeNotImplemented
+}
+
+// StringToAlgorithm is the reverse of AlgorithmToString.
+var StringToAlgorithm = reverseInt8(AlgorithmToString)
+
+// StringToHash is a map of names to hash IDs.
+var StringToHash = reverseInt8(HashToString)
+
+// StringToCertType is the reverseof CertTypeToString.
+var StringToCertType = reverseInt16(CertTypeToString)
+
 // Reverse a map
 func reverseInt8(m map[uint8]string) map[string]uint8 {
 	n := make(map[string]uint8, len(m))

+ 5 - 3
libnetwork/vendor/github.com/miekg/dns/sanitize.go

@@ -5,6 +5,7 @@ package dns
 // rrs.
 // m is used to store the RRs temporary. If it is nil a new map will be allocated.
 func Dedup(rrs []RR, m map[string]RR) []RR {
+
 	if m == nil {
 		m = make(map[string]RR)
 	}
@@ -14,10 +15,11 @@ func Dedup(rrs []RR, m map[string]RR) []RR {
 	for _, r := range rrs {
 		key := normalizedString(r)
 		keys = append(keys, &key)
-		if _, ok := m[key]; ok {
+		if mr, ok := m[key]; ok {
 			// Shortest TTL wins.
-			if m[key].Header().Ttl > r.Header().Ttl {
-				m[key].Header().Ttl = r.Header().Ttl
+			rh, mrh := r.Header(), mr.Header()
+			if mrh.Ttl > rh.Ttl {
+				mrh.Ttl = rh.Ttl
 			}
 			continue
 		}

ファイルの差分が大きいため隠しています
+ 559 - 223
libnetwork/vendor/github.com/miekg/dns/scan.go


ファイルの差分が大きいため隠しています
+ 225 - 433
libnetwork/vendor/github.com/miekg/dns/scan_rr.go


+ 0 - 56
libnetwork/vendor/github.com/miekg/dns/scanner.go

@@ -1,56 +0,0 @@
-package dns
-
-// Implement a simple scanner, return a byte stream from an io reader.
-
-import (
-	"bufio"
-	"context"
-	"io"
-	"text/scanner"
-)
-
-type scan struct {
-	src      *bufio.Reader
-	position scanner.Position
-	eof      bool // Have we just seen a eof
-	ctx      context.Context
-}
-
-func scanInit(r io.Reader) (*scan, context.CancelFunc) {
-	s := new(scan)
-	s.src = bufio.NewReader(r)
-	s.position.Line = 1
-
-	ctx, cancel := context.WithCancel(context.Background())
-	s.ctx = ctx
-
-	return s, cancel
-}
-
-// tokenText returns the next byte from the input
-func (s *scan) tokenText() (byte, error) {
-	c, err := s.src.ReadByte()
-	if err != nil {
-		return c, err
-	}
-	select {
-	case <-s.ctx.Done():
-		return c, context.Canceled
-	default:
-		break
-	}
-
-	// delay the newline handling until the next token is delivered,
-	// fixes off-by-one errors when reporting a parse error.
-	if s.eof == true {
-		s.position.Line++
-		s.position.Column = 0
-		s.eof = false
-	}
-	if c == '\n' {
-		s.eof = true
-		return c, nil
-	}
-	s.position.Column++
-	return c, nil
-}

+ 123 - 0
libnetwork/vendor/github.com/miekg/dns/serve_mux.go

@@ -0,0 +1,123 @@
+package dns
+
+import (
+	"strings"
+	"sync"
+)
+
+// ServeMux is an DNS request multiplexer. It matches the zone name of
+// each incoming request against a list of registered patterns add calls
+// the handler for the pattern that most closely matches the zone name.
+//
+// ServeMux is DNSSEC aware, meaning that queries for the DS record are
+// redirected to the parent zone (if that is also registered), otherwise
+// the child gets the query.
+//
+// ServeMux is also safe for concurrent access from multiple goroutines.
+//
+// The zero ServeMux is empty and ready for use.
+type ServeMux struct {
+	z map[string]Handler
+	m sync.RWMutex
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux {
+	return new(ServeMux)
+}
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+func (mux *ServeMux) match(q string, t uint16) Handler {
+	mux.m.RLock()
+	defer mux.m.RUnlock()
+	if mux.z == nil {
+		return nil
+	}
+
+	q = strings.ToLower(q)
+
+	var handler Handler
+	for off, end := 0, false; !end; off, end = NextLabel(q, off) {
+		if h, ok := mux.z[q[off:]]; ok {
+			if t != TypeDS {
+				return h
+			}
+			// Continue for DS to see if we have a parent too, if so delegate to the parent
+			handler = h
+		}
+	}
+
+	// Wildcard match, if we have found nothing try the root zone as a last resort.
+	if h, ok := mux.z["."]; ok {
+		return h
+	}
+
+	return handler
+}
+
+// Handle adds a handler to the ServeMux for pattern.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+	if pattern == "" {
+		panic("dns: invalid pattern " + pattern)
+	}
+	mux.m.Lock()
+	if mux.z == nil {
+		mux.z = make(map[string]Handler)
+	}
+	mux.z[Fqdn(pattern)] = handler
+	mux.m.Unlock()
+}
+
+// HandleFunc adds a handler function to the ServeMux for pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+	mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// HandleRemove deregisters the handler specific for pattern from the ServeMux.
+func (mux *ServeMux) HandleRemove(pattern string) {
+	if pattern == "" {
+		panic("dns: invalid pattern " + pattern)
+	}
+	mux.m.Lock()
+	delete(mux.z, Fqdn(pattern))
+	mux.m.Unlock()
+}
+
+// ServeDNS dispatches the request to the handler whose pattern most
+// closely matches the request message.
+//
+// ServeDNS is DNSSEC aware, meaning that queries for the DS record
+// are redirected to the parent zone (if that is also registered),
+// otherwise the child gets the query.
+//
+// If no handler is found, or there is no question, a standard SERVFAIL
+// message is returned
+func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
+	var h Handler
+	if len(req.Question) >= 1 { // allow more than one question
+		h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
+	}
+
+	if h != nil {
+		h.ServeDNS(w, req)
+	} else {
+		HandleFailed(w, req)
+	}
+}
+
+// Handle registers the handler with the given pattern
+// in the DefaultServeMux. The documentation for
+// ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleRemove deregisters the handle with the given pattern
+// in the DefaultServeMux.
+func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
+
+// HandleFunc registers the handler function with the given pattern
+// in the DefaultServeMux.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+	DefaultServeMux.HandleFunc(pattern, handler)
+}

+ 318 - 336
libnetwork/vendor/github.com/miekg/dns/server.go

@@ -3,30 +3,40 @@
 package dns
 
 import (
-	"bytes"
+	"context"
 	"crypto/tls"
 	"encoding/binary"
+	"errors"
 	"io"
 	"net"
+	"strings"
 	"sync"
-	"sync/atomic"
 	"time"
 )
 
 // Default maximum number of TCP queries before we close the socket.
 const maxTCPQueries = 128
 
-// Interval for stop worker if no load
-const idleWorkerTimeout = 10 * time.Second
-
-// Maximum number of workers
-const maxWorkersCount = 10000
+// aLongTimeAgo is a non-zero time, far in the past, used for
+// immediate cancelation of network operations.
+var aLongTimeAgo = time.Unix(1, 0)
 
 // Handler is implemented by any value that implements ServeDNS.
 type Handler interface {
 	ServeDNS(w ResponseWriter, r *Msg)
 }
 
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as DNS handlers.  If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Msg)
+
+// ServeDNS calls f(w, r).
+func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
+	f(w, r)
+}
+
 // A ResponseWriter interface is used by an DNS handler to
 // construct an DNS response.
 type ResponseWriter interface {
@@ -49,11 +59,17 @@ type ResponseWriter interface {
 	Hijack()
 }
 
+// A ConnectionStater interface is used by a DNS Handler to access TLS connection state
+// when available.
+type ConnectionStater interface {
+	ConnectionState() *tls.ConnectionState
+}
+
 type response struct {
-	msg            []byte
+	closed         bool // connection has been closed
 	hijacked       bool // connection has been hijacked by handler
-	tsigStatus     error
 	tsigTimersOnly bool
+	tsigStatus     error
 	tsigRequestMAC string
 	tsigSecret     map[string]string // the tsig secrets
 	udp            *net.UDPConn      // i/o connection if UDP was used
@@ -62,35 +78,6 @@ type response struct {
 	writer         Writer            // writer to output the raw DNS bits
 }
 
-// ServeMux is an DNS request multiplexer. It matches the
-// zone name of each incoming request against a list of
-// registered patterns add calls the handler for the pattern
-// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
-// that queries for the DS record are redirected to the parent zone (if that
-// is also registered), otherwise the child gets the query.
-// ServeMux is also safe for concurrent access from multiple goroutines.
-type ServeMux struct {
-	z map[string]Handler
-	m *sync.RWMutex
-}
-
-// NewServeMux allocates and returns a new ServeMux.
-func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
-
-// DefaultServeMux is the default ServeMux used by Serve.
-var DefaultServeMux = NewServeMux()
-
-// The HandlerFunc type is an adapter to allow the use of
-// ordinary functions as DNS handlers.  If f is a function
-// with the appropriate signature, HandlerFunc(f) is a
-// Handler object that calls f.
-type HandlerFunc func(ResponseWriter, *Msg)
-
-// ServeDNS calls f(w, r).
-func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
-	f(w, r)
-}
-
 // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
 func HandleFailed(w ResponseWriter, r *Msg) {
 	m := new(Msg)
@@ -99,8 +86,6 @@ func HandleFailed(w ResponseWriter, r *Msg) {
 	w.WriteMsg(m)
 }
 
-func failedHandler() Handler { return HandlerFunc(HandleFailed) }
-
 // ListenAndServe Starts a server on address and network specified Invoke handler
 // for incoming queries.
 func ListenAndServe(addr string, network string, handler Handler) error {
@@ -139,99 +124,6 @@ func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error {
 	return server.ActivateAndServe()
 }
 
-func (mux *ServeMux) match(q string, t uint16) Handler {
-	mux.m.RLock()
-	defer mux.m.RUnlock()
-	var handler Handler
-	b := make([]byte, len(q)) // worst case, one label of length q
-	off := 0
-	end := false
-	for {
-		l := len(q[off:])
-		for i := 0; i < l; i++ {
-			b[i] = q[off+i]
-			if b[i] >= 'A' && b[i] <= 'Z' {
-				b[i] |= ('a' - 'A')
-			}
-		}
-		if h, ok := mux.z[string(b[:l])]; ok { // causes garbage, might want to change the map key
-			if t != TypeDS {
-				return h
-			}
-			// Continue for DS to see if we have a parent too, if so delegeate to the parent
-			handler = h
-		}
-		off, end = NextLabel(q, off)
-		if end {
-			break
-		}
-	}
-	// Wildcard match, if we have found nothing try the root zone as a last resort.
-	if h, ok := mux.z["."]; ok {
-		return h
-	}
-	return handler
-}
-
-// Handle adds a handler to the ServeMux for pattern.
-func (mux *ServeMux) Handle(pattern string, handler Handler) {
-	if pattern == "" {
-		panic("dns: invalid pattern " + pattern)
-	}
-	mux.m.Lock()
-	mux.z[Fqdn(pattern)] = handler
-	mux.m.Unlock()
-}
-
-// HandleFunc adds a handler function to the ServeMux for pattern.
-func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
-	mux.Handle(pattern, HandlerFunc(handler))
-}
-
-// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
-func (mux *ServeMux) HandleRemove(pattern string) {
-	if pattern == "" {
-		panic("dns: invalid pattern " + pattern)
-	}
-	mux.m.Lock()
-	delete(mux.z, Fqdn(pattern))
-	mux.m.Unlock()
-}
-
-// ServeDNS dispatches the request to the handler whose
-// pattern most closely matches the request message. If DefaultServeMux
-// is used the correct thing for DS queries is done: a possible parent
-// is sought.
-// If no handler is found a standard SERVFAIL message is returned
-// If the request message does not have exactly one question in the
-// question section a SERVFAIL is returned, unlesss Unsafe is true.
-func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) {
-	var h Handler
-	if len(request.Question) < 1 { // allow more than one question
-		h = failedHandler()
-	} else {
-		if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil {
-			h = failedHandler()
-		}
-	}
-	h.ServeDNS(w, request)
-}
-
-// Handle registers the handler with the given pattern
-// in the DefaultServeMux. The documentation for
-// ServeMux explains how patterns are matched.
-func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
-
-// HandleRemove deregisters the handle with the given pattern
-// in the DefaultServeMux.
-func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
-
-// HandleFunc registers the handler function with the given pattern
-// in the DefaultServeMux.
-func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
-	DefaultServeMux.HandleFunc(pattern, handler)
-}
-
 // Writer writes raw DNS messages; each call to Write should send an entire message.
 type Writer interface {
 	io.Writer
@@ -253,11 +145,11 @@ type defaultReader struct {
 	*Server
 }
 
-func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
+func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
 	return dr.readTCP(conn, timeout)
 }
 
-func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
 	return dr.readUDP(conn, timeout)
 }
 
@@ -294,9 +186,6 @@ type Server struct {
 	IdleTimeout func() time.Duration
 	// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
 	TsigSecret map[string]string
-	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
-	// the handler. It will specifically not check if the query has the QR bit not set.
-	Unsafe bool
 	// If NotifyStartedFunc is set it is called once the server has started listening.
 	NotifyStartedFunc func()
 	// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
@@ -305,65 +194,64 @@ type Server struct {
 	DecorateWriter DecorateWriter
 	// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1).
 	MaxTCPQueries int
+	// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address.
+	// It is only supported on go1.11+ and when using ListenAndServe.
+	ReusePort bool
+	// AcceptMsgFunc will check the incoming message and will reject it early in the process.
+	// By default DefaultMsgAcceptFunc will be used.
+	MsgAcceptFunc MsgAcceptFunc
 
-	// UDP packet or TCP connection queue
-	queue chan *response
-	// Workers count
-	workersCount int32
 	// Shutdown handling
-	lock    sync.RWMutex
-	started bool
+	lock     sync.RWMutex
+	started  bool
+	shutdown chan struct{}
+	conns    map[net.Conn]struct{}
+
+	// A pool for UDP message buffers.
+	udpPool sync.Pool
 }
 
-func (srv *Server) worker(w *response) {
-	srv.serve(w)
+func (srv *Server) isStarted() bool {
+	srv.lock.RLock()
+	started := srv.started
+	srv.lock.RUnlock()
+	return started
+}
 
-	for {
-		count := atomic.LoadInt32(&srv.workersCount)
-		if count > maxWorkersCount {
-			return
-		}
-		if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) {
-			break
-		}
+func makeUDPBuffer(size int) func() interface{} {
+	return func() interface{} {
+		return make([]byte, size)
 	}
+}
 
-	defer atomic.AddInt32(&srv.workersCount, -1)
+func (srv *Server) init() {
+	srv.shutdown = make(chan struct{})
+	srv.conns = make(map[net.Conn]struct{})
 
-	inUse := false
-	timeout := time.NewTimer(idleWorkerTimeout)
-	defer timeout.Stop()
-LOOP:
-	for {
-		select {
-		case w, ok := <-srv.queue:
-			if !ok {
-				break LOOP
-			}
-			inUse = true
-			srv.serve(w)
-		case <-timeout.C:
-			if !inUse {
-				break LOOP
-			}
-			inUse = false
-			timeout.Reset(idleWorkerTimeout)
-		}
+	if srv.UDPSize == 0 {
+		srv.UDPSize = MinMsgSize
+	}
+	if srv.MsgAcceptFunc == nil {
+		srv.MsgAcceptFunc = DefaultMsgAcceptFunc
 	}
+	if srv.Handler == nil {
+		srv.Handler = DefaultServeMux
+	}
+
+	srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
 }
 
-func (srv *Server) spawnWorker(w *response) {
-	select {
-	case srv.queue <- w:
-	default:
-		go srv.worker(w)
-	}
+func unlockOnce(l sync.Locker) func() {
+	var once sync.Once
+	return func() { once.Do(l.Unlock) }
 }
 
 // ListenAndServe starts a nameserver on the configured address in *Server.
 func (srv *Server) ListenAndServe() error {
+	unlock := unlockOnce(&srv.lock)
 	srv.lock.Lock()
-	defer srv.lock.Unlock()
+	defer unlock()
+
 	if srv.started {
 		return &Error{err: "server already started"}
 	}
@@ -372,63 +260,46 @@ func (srv *Server) ListenAndServe() error {
 	if addr == "" {
 		addr = ":domain"
 	}
-	if srv.UDPSize == 0 {
-		srv.UDPSize = MinMsgSize
-	}
-	srv.queue = make(chan *response)
-	defer close(srv.queue)
+
+	srv.init()
+
 	switch srv.Net {
 	case "tcp", "tcp4", "tcp6":
-		a, err := net.ResolveTCPAddr(srv.Net, addr)
-		if err != nil {
-			return err
-		}
-		l, err := net.ListenTCP(srv.Net, a)
+		l, err := listenTCP(srv.Net, addr, srv.ReusePort)
 		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
+		unlock()
+		return srv.serveTCP(l)
 	case "tcp-tls", "tcp4-tls", "tcp6-tls":
-		network := "tcp"
-		if srv.Net == "tcp4-tls" {
-			network = "tcp4"
-		} else if srv.Net == "tcp6-tls" {
-			network = "tcp6"
+		if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) {
+			return errors.New("dns: neither Certificates nor GetCertificate set in Config")
 		}
-
-		l, err := tls.Listen(network, addr, srv.TLSConfig)
+		network := strings.TrimSuffix(srv.Net, "-tls")
+		l, err := listenTCP(network, addr, srv.ReusePort)
 		if err != nil {
 			return err
 		}
+		l = tls.NewListener(l, srv.TLSConfig)
 		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
+		unlock()
+		return srv.serveTCP(l)
 	case "udp", "udp4", "udp6":
-		a, err := net.ResolveUDPAddr(srv.Net, addr)
-		if err != nil {
-			return err
-		}
-		l, err := net.ListenUDP(srv.Net, a)
+		l, err := listenUDP(srv.Net, addr, srv.ReusePort)
 		if err != nil {
 			return err
 		}
-		if e := setUDPSocketOptions(l); e != nil {
+		u := l.(*net.UDPConn)
+		if e := setUDPSocketOptions(u); e != nil {
 			return e
 		}
 		srv.PacketConn = l
 		srv.started = true
-		srv.lock.Unlock()
-		err = srv.serveUDP(l)
-		srv.lock.Lock() // to satisfy the defer at the top
-		return err
+		unlock()
+		return srv.serveUDP(u)
 	}
 	return &Error{err: "bad network"}
 }
@@ -436,20 +307,19 @@ func (srv *Server) ListenAndServe() error {
 // ActivateAndServe starts a nameserver with the PacketConn or Listener
 // configured in *Server. Its main use is to start a server from systemd.
 func (srv *Server) ActivateAndServe() error {
+	unlock := unlockOnce(&srv.lock)
 	srv.lock.Lock()
-	defer srv.lock.Unlock()
+	defer unlock()
+
 	if srv.started {
 		return &Error{err: "server already started"}
 	}
 
+	srv.init()
+
 	pConn := srv.PacketConn
 	l := srv.Listener
-	srv.queue = make(chan *response)
-	defer close(srv.queue)
 	if pConn != nil {
-		if srv.UDPSize == 0 {
-			srv.UDPSize = MinMsgSize
-		}
 		// Check PacketConn interface's type is valid and value
 		// is not nil
 		if t, ok := pConn.(*net.UDPConn); ok && t != nil {
@@ -457,18 +327,14 @@ func (srv *Server) ActivateAndServe() error {
 				return e
 			}
 			srv.started = true
-			srv.lock.Unlock()
-			e := srv.serveUDP(t)
-			srv.lock.Lock() // to satisfy the defer at the top
-			return e
+			unlock()
+			return srv.serveUDP(t)
 		}
 	}
 	if l != nil {
 		srv.started = true
-		srv.lock.Unlock()
-		e := srv.serveTCP(l)
-		srv.lock.Lock() // to satisfy the defer at the top
-		return e
+		unlock()
+		return srv.serveTCP(l)
 	}
 	return &Error{err: "bad listeners"}
 }
@@ -476,30 +342,63 @@ func (srv *Server) ActivateAndServe() error {
 // Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and
 // ActivateAndServe will return.
 func (srv *Server) Shutdown() error {
+	return srv.ShutdownContext(context.Background())
+}
+
+// ShutdownContext shuts down a server. After a call to ShutdownContext,
+// ListenAndServe and ActivateAndServe will return.
+//
+// A context.Context may be passed to limit how long to wait for connections
+// to terminate.
+func (srv *Server) ShutdownContext(ctx context.Context) error {
 	srv.lock.Lock()
 	if !srv.started {
 		srv.lock.Unlock()
 		return &Error{err: "server not started"}
 	}
+
 	srv.started = false
-	srv.lock.Unlock()
 
 	if srv.PacketConn != nil {
-		srv.PacketConn.Close()
+		srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads
 	}
+
 	if srv.Listener != nil {
 		srv.Listener.Close()
 	}
-	return nil
+
+	for rw := range srv.conns {
+		rw.SetReadDeadline(aLongTimeAgo) // Unblock reads
+	}
+
+	srv.lock.Unlock()
+
+	if testShutdownNotify != nil {
+		testShutdownNotify.Broadcast()
+	}
+
+	var ctxErr error
+	select {
+	case <-srv.shutdown:
+	case <-ctx.Done():
+		ctxErr = ctx.Err()
+	}
+
+	if srv.PacketConn != nil {
+		srv.PacketConn.Close()
+	}
+
+	return ctxErr
 }
 
+var testShutdownNotify *sync.Cond
+
 // getReadTimeout is a helper func to use system timeout if server did not intend to change it.
 func (srv *Server) getReadTimeout() time.Duration {
-	rtimeout := dnsTimeout
 	if srv.ReadTimeout != 0 {
-		rtimeout = srv.ReadTimeout
+		return srv.ReadTimeout
 	}
-	return rtimeout
+	return dnsTimeout
 }
 
 // serveTCP starts a TCP listener for the server.
@@ -510,22 +409,32 @@ func (srv *Server) serveTCP(l net.Listener) error {
 		srv.NotifyStartedFunc()
 	}
 
-	for {
+	var wg sync.WaitGroup
+	defer func() {
+		wg.Wait()
+		close(srv.shutdown)
+	}()
+
+	for srv.isStarted() {
 		rw, err := l.Accept()
-		srv.lock.RLock()
-		if !srv.started {
-			srv.lock.RUnlock()
-			return nil
-		}
-		srv.lock.RUnlock()
 		if err != nil {
+			if !srv.isStarted() {
+				return nil
+			}
 			if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
 				continue
 			}
 			return err
 		}
-		srv.spawnWorker(&response{tsigSecret: srv.TsigSecret, tcp: rw})
+		srv.lock.Lock()
+		// Track the connection to allow unblocking reads on shutdown.
+		srv.conns[rw] = struct{}{}
+		srv.lock.Unlock()
+		wg.Add(1)
+		go srv.serveTCPConn(&wg, rw)
 	}
+
+	return nil
 }
 
 // serveUDP starts a UDP listener for the server.
@@ -536,58 +445,57 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 		srv.NotifyStartedFunc()
 	}
 
-	reader := Reader(&defaultReader{srv})
+	reader := Reader(defaultReader{srv})
 	if srv.DecorateReader != nil {
 		reader = srv.DecorateReader(reader)
 	}
 
+	var wg sync.WaitGroup
+	defer func() {
+		wg.Wait()
+		close(srv.shutdown)
+	}()
+
 	rtimeout := srv.getReadTimeout()
 	// deadline is not used here
-	for {
+	for srv.isStarted() {
 		m, s, err := reader.ReadUDP(l, rtimeout)
-		srv.lock.RLock()
-		if !srv.started {
-			srv.lock.RUnlock()
-			return nil
-		}
-		srv.lock.RUnlock()
 		if err != nil {
+			if !srv.isStarted() {
+				return nil
+			}
 			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
 				continue
 			}
 			return err
 		}
 		if len(m) < headerSize {
+			if cap(m) == srv.UDPSize {
+				srv.udpPool.Put(m[:srv.UDPSize])
+			}
 			continue
 		}
-		srv.spawnWorker(&response{msg: m, tsigSecret: srv.TsigSecret, udp: l, udpSession: s})
+		wg.Add(1)
+		go srv.serveUDPPacket(&wg, m, l, s)
 	}
+
+	return nil
 }
 
-func (srv *Server) serve(w *response) {
+// Serve a new TCP connection.
+func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
+	w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 	} else {
 		w.writer = w
 	}
 
-	if w.udp != nil {
-		// serve UDP
-		srv.serveDNS(w)
-		return
-	}
-
-	reader := Reader(&defaultReader{srv})
+	reader := Reader(defaultReader{srv})
 	if srv.DecorateReader != nil {
 		reader = srv.DecorateReader(reader)
 	}
 
-	defer func() {
-		if !w.hijacked {
-			w.Close()
-		}
-	}()
-
 	idleTimeout := tcpIdleTimeout
 	if srv.IdleTimeout != nil {
 		idleTimeout = srv.IdleTimeout()
@@ -600,15 +508,14 @@ func (srv *Server) serve(w *response) {
 		limit = maxTCPQueries
 	}
 
-	for q := 0; q < limit || limit == -1; q++ {
-		var err error
-		w.msg, err = reader.ReadTCP(w.tcp, timeout)
+	for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
+		m, err := reader.ReadTCP(w.tcp, timeout)
 		if err != nil {
 			// TODO(tmthrgd): handle error
 			break
 		}
-		srv.serveDNS(w)
-		if w.tcp == nil {
+		srv.serveDNS(m, w)
+		if w.closed {
 			break // Close() was called
 		}
 		if w.hijacked {
@@ -618,18 +525,67 @@ func (srv *Server) serve(w *response) {
 		// idle timeout.
 		timeout = idleTimeout
 	}
+
+	if !w.hijacked {
+		w.Close()
+	}
+
+	srv.lock.Lock()
+	delete(srv.conns, w.tcp)
+	srv.lock.Unlock()
+
+	wg.Done()
 }
 
-func (srv *Server) serveDNS(w *response) {
-	req := new(Msg)
-	err := req.Unpack(w.msg)
-	if err != nil { // Send a FormatError back
-		x := new(Msg)
-		x.SetRcodeFormatError(req)
-		w.WriteMsg(x)
+// Serve a new UDP request.
+func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u *net.UDPConn, s *SessionUDP) {
+	w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: s}
+	if srv.DecorateWriter != nil {
+		w.writer = srv.DecorateWriter(w)
+	} else {
+		w.writer = w
+	}
+
+	srv.serveDNS(m, w)
+	wg.Done()
+}
+
+func (srv *Server) serveDNS(m []byte, w *response) {
+	dh, off, err := unpackMsgHdr(m, 0)
+	if err != nil {
+		// Let client hang, they are sending crap; any reply can be used to amplify.
 		return
 	}
-	if !srv.Unsafe && req.Response {
+
+	req := new(Msg)
+	req.setHdr(dh)
+
+	switch action := srv.MsgAcceptFunc(dh); action {
+	case MsgAccept:
+		if req.unpack(dh, m, off) == nil {
+			break
+		}
+
+		fallthrough
+	case MsgReject, MsgRejectNotImplemented:
+		opcode := req.Opcode
+		req.SetRcodeFormatError(req)
+		req.Zero = false
+		if action == MsgRejectNotImplemented {
+			req.Opcode = opcode
+			req.Rcode = RcodeNotImplemented
+		}
+
+		// Are we allowed to delete any OPT records here?
+		req.Ns, req.Answer, req.Extra = nil, nil, nil
+
+		w.WriteMsg(req)
+		fallthrough
+	case MsgIgnore:
+		if w.udp != nil && cap(m) == srv.UDPSize {
+			srv.udpPool.Put(m[:srv.UDPSize])
+		}
+
 		return
 	}
 
@@ -637,7 +593,7 @@ func (srv *Server) serveDNS(w *response) {
 	if w.tsigSecret != nil {
 		if t := req.IsTsig(); t != nil {
 			if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
-				w.tsigStatus = TsigVerify(w.msg, secret, "", false)
+				w.tsigStatus = TsigVerify(m, secret, "", false)
 			} else {
 				w.tsigStatus = ErrSecret
 			}
@@ -646,54 +602,49 @@ func (srv *Server) serveDNS(w *response) {
 		}
 	}
 
-	handler := srv.Handler
-	if handler == nil {
-		handler = DefaultServeMux
+	if w.udp != nil && cap(m) == srv.UDPSize {
+		srv.udpPool.Put(m[:srv.UDPSize])
 	}
 
-	handler.ServeDNS(w, req) // Writes back to the client
+	srv.Handler.ServeDNS(w, req) // Writes back to the client
 }
 
 func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
-	conn.SetReadDeadline(time.Now().Add(timeout))
-	l := make([]byte, 2)
-	n, err := conn.Read(l)
-	if err != nil || n != 2 {
-		if err != nil {
-			return nil, err
-		}
-		return nil, ErrShortRead
-	}
-	length := binary.BigEndian.Uint16(l)
-	if length == 0 {
-		return nil, ErrShortRead
+	// If we race with ShutdownContext, the read deadline may
+	// have been set in the distant past to unblock the read
+	// below. We must not override it, otherwise we may block
+	// ShutdownContext.
+	srv.lock.RLock()
+	if srv.started {
+		conn.SetReadDeadline(time.Now().Add(timeout))
 	}
-	m := make([]byte, int(length))
-	n, err = conn.Read(m[:int(length)])
-	if err != nil || n == 0 {
-		if err != nil {
-			return nil, err
-		}
-		return nil, ErrShortRead
+	srv.lock.RUnlock()
+
+	var length uint16
+	if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
+		return nil, err
 	}
-	i := n
-	for i < int(length) {
-		j, err := conn.Read(m[i:int(length)])
-		if err != nil {
-			return nil, err
-		}
-		i += j
+
+	m := make([]byte, length)
+	if _, err := io.ReadFull(conn, m); err != nil {
+		return nil, err
 	}
-	n = i
-	m = m[:n]
+
 	return m, nil
 }
 
 func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
-	conn.SetReadDeadline(time.Now().Add(timeout))
-	m := make([]byte, srv.UDPSize)
+	srv.lock.RLock()
+	if srv.started {
+		// See the comment in readTCP above.
+		conn.SetReadDeadline(time.Now().Add(timeout))
+	}
+	srv.lock.RUnlock()
+
+	m := srv.udpPool.Get().([]byte)
 	n, s, err := ReadFromSessionUDP(conn, m)
 	if err != nil {
+		srv.udpPool.Put(m)
 		return nil, nil, err
 	}
 	m = m[:n]
@@ -702,6 +653,10 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
 
 // WriteMsg implements the ResponseWriter.WriteMsg method.
 func (w *response) WriteMsg(m *Msg) (err error) {
+	if w.closed {
+		return &Error{err: "WriteMsg called after Close"}
+	}
+
 	var data []byte
 	if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
 		if t := m.IsTsig(); t != nil {
@@ -723,42 +678,50 @@ func (w *response) WriteMsg(m *Msg) (err error) {
 
 // Write implements the ResponseWriter.Write method.
 func (w *response) Write(m []byte) (int, error) {
+	if w.closed {
+		return 0, &Error{err: "Write called after Close"}
+	}
+
 	switch {
 	case w.udp != nil:
-		n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
-		return n, err
+		return WriteToSessionUDP(w.udp, m, w.udpSession)
 	case w.tcp != nil:
-		lm := len(m)
-		if lm < 2 {
-			return 0, io.ErrShortBuffer
-		}
-		if lm > MaxMsgSize {
+		if len(m) > MaxMsgSize {
 			return 0, &Error{err: "message too large"}
 		}
-		l := make([]byte, 2, 2+lm)
-		binary.BigEndian.PutUint16(l, uint16(lm))
-		m = append(l, m...)
 
-		n, err := io.Copy(w.tcp, bytes.NewReader(m))
+		l := make([]byte, 2)
+		binary.BigEndian.PutUint16(l, uint16(len(m)))
+
+		n, err := (&net.Buffers{l, m}).WriteTo(w.tcp)
 		return int(n), err
+	default:
+		panic("dns: internal error: udp and tcp both nil")
 	}
-	panic("not reached")
 }
 
 // LocalAddr implements the ResponseWriter.LocalAddr method.
 func (w *response) LocalAddr() net.Addr {
-	if w.tcp != nil {
+	switch {
+	case w.udp != nil:
+		return w.udp.LocalAddr()
+	case w.tcp != nil:
 		return w.tcp.LocalAddr()
+	default:
+		panic("dns: internal error: udp and tcp both nil")
 	}
-	return w.udp.LocalAddr()
 }
 
 // RemoteAddr implements the ResponseWriter.RemoteAddr method.
 func (w *response) RemoteAddr() net.Addr {
-	if w.tcp != nil {
+	switch {
+	case w.udpSession != nil:
+		return w.udpSession.RemoteAddr()
+	case w.tcp != nil:
 		return w.tcp.RemoteAddr()
+	default:
+		panic("dns: internal error: udpSession and tcp both nil")
 	}
-	return w.udpSession.RemoteAddr()
 }
 
 // TsigStatus implements the ResponseWriter.TsigStatus method.
@@ -772,11 +735,30 @@ func (w *response) Hijack() { w.hijacked = true }
 
 // Close implements the ResponseWriter.Close method
 func (w *response) Close() error {
-	// Can't close the udp conn, as that is actually the listener.
-	if w.tcp != nil {
-		e := w.tcp.Close()
-		w.tcp = nil
-		return e
+	if w.closed {
+		return &Error{err: "connection already closed"}
+	}
+	w.closed = true
+
+	switch {
+	case w.udp != nil:
+		// Can't close the udp conn, as that is actually the listener.
+		return nil
+	case w.tcp != nil:
+		return w.tcp.Close()
+	default:
+		panic("dns: internal error: udp and tcp both nil")
+	}
+}
+
+// ConnectionState() implements the ConnectionStater.ConnectionState() interface.
+func (w *response) ConnectionState() *tls.ConnectionState {
+	type tlsConnectionStater interface {
+		ConnectionState() tls.ConnectionState
+	}
+	if v, ok := w.tcp.(tlsConnectionStater); ok {
+		t := v.ConnectionState()
+		return &t
 	}
 	return nil
 }

+ 11 - 20
libnetwork/vendor/github.com/miekg/dns/sig0.go

@@ -21,15 +21,11 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
 	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
 		return nil, ErrKey
 	}
-	rr.Header().Rrtype = TypeSIG
-	rr.Header().Class = ClassANY
-	rr.Header().Ttl = 0
-	rr.Header().Name = "."
-	rr.OrigTtl = 0
-	rr.TypeCovered = 0
-	rr.Labels = 0
 
-	buf := make([]byte, m.Len()+rr.len())
+	rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0}
+	rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0
+
+	buf := make([]byte, m.Len()+Len(rr))
 	mbuf, err := m.PackBuffer(buf)
 	if err != nil {
 		return nil, err
@@ -107,7 +103,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	anc := binary.BigEndian.Uint16(buf[6:])
 	auc := binary.BigEndian.Uint16(buf[8:])
 	adc := binary.BigEndian.Uint16(buf[10:])
-	offset := 12
+	offset := headerSize
 	var err error
 	for i := uint16(0); i < qdc && offset < buflen; i++ {
 		_, offset, err = UnpackDomainName(buf, offset)
@@ -127,8 +123,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 		if offset+1 >= buflen {
 			continue
 		}
-		var rdlen uint16
-		rdlen = binary.BigEndian.Uint16(buf[offset:])
+		rdlen := binary.BigEndian.Uint16(buf[offset:])
 		offset += 2
 		offset += int(rdlen)
 	}
@@ -168,7 +163,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	}
 	// If key has come from the DNS name compression might
 	// have mangled the case of the name
-	if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
+	if !strings.EqualFold(signername, k.Header().Name) {
 		return &Error{err: "signer name doesn't match key name"}
 	}
 	sigend := offset
@@ -186,10 +181,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	case DSA:
 		pk := k.publicKeyDSA()
 		sig = sig[1:]
-		r := big.NewInt(0)
-		r.SetBytes(sig[:len(sig)/2])
-		s := big.NewInt(0)
-		s.SetBytes(sig[len(sig)/2:])
+		r := new(big.Int).SetBytes(sig[:len(sig)/2])
+		s := new(big.Int).SetBytes(sig[len(sig)/2:])
 		if pk != nil {
 			if dsa.Verify(pk, hashed, r, s) {
 				return nil
@@ -203,10 +196,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 		}
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		pk := k.publicKeyECDSA()
-		r := big.NewInt(0)
-		r.SetBytes(sig[:len(sig)/2])
-		s := big.NewInt(0)
-		s.SetBytes(sig[len(sig)/2:])
+		r := new(big.Int).SetBytes(sig[:len(sig)/2])
+		s := new(big.Int).SetBytes(sig[len(sig)/2:])
 		if pk != nil {
 			if ecdsa.Verify(pk, hashed, r, s) {
 				return nil

+ 7 - 3
libnetwork/vendor/github.com/miekg/dns/singleinflight.go

@@ -23,6 +23,8 @@ type call struct {
 type singleflight struct {
 	sync.Mutex                  // protects m
 	m          map[string]*call // lazily initialized
+
+	dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
 }
 
 // Do executes and returns the results of the given function, making
@@ -49,9 +51,11 @@ func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v
 	c.val, c.rtt, c.err = fn()
 	c.wg.Done()
 
-	g.Lock()
-	delete(g.m, key)
-	g.Unlock()
+	if !g.dontDeleteForTesting {
+		g.Lock()
+		delete(g.m, key)
+		g.Unlock()
+	}
 
 	return c.val, c.rtt, c.err, c.dups > 0
 }

+ 1 - 4
libnetwork/vendor/github.com/miekg/dns/smimea.go

@@ -14,10 +14,7 @@ func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate)
 	r.MatchingType = uint8(matchingType)
 
 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 // Verify verifies a SMIMEA record against an SSL certificate. If it is OK

+ 1 - 4
libnetwork/vendor/github.com/miekg/dns/tlsa.go

@@ -14,10 +14,7 @@ func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (
 	r.MatchingType = uint8(matchingType)
 
 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 // Verify verifies a TLSA record against an SSL certificate. If it is OK

+ 13 - 10
libnetwork/vendor/github.com/miekg/dns/tsig.go

@@ -40,7 +40,7 @@ type TSIG struct {
 // TSIG has no official presentation format, but this will suffice.
 
 func (rr *TSIG) String() string {
-	s := "\n;; TSIG PSEUDOSECTION:\n"
+	s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format
 	s += rr.Hdr.String() +
 		" " + rr.Algorithm +
 		" " + tsigTimeToString(rr.TimeSigned) +
@@ -54,6 +54,10 @@ func (rr *TSIG) String() string {
 	return s
 }
 
+func (rr *TSIG) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on TSIG")
+}
+
 // The following values must be put in wireformat, so that the MAC can be calculated.
 // RFC 2845, section 3.4.2. TSIG Variables.
 type tsigWireFmt struct {
@@ -113,13 +117,13 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
 	var h hash.Hash
 	switch strings.ToLower(rr.Algorithm) {
 	case HmacMD5:
-		h = hmac.New(md5.New, []byte(rawsecret))
+		h = hmac.New(md5.New, rawsecret)
 	case HmacSHA1:
-		h = hmac.New(sha1.New, []byte(rawsecret))
+		h = hmac.New(sha1.New, rawsecret)
 	case HmacSHA256:
-		h = hmac.New(sha256.New, []byte(rawsecret))
+		h = hmac.New(sha256.New, rawsecret)
 	case HmacSHA512:
-		h = hmac.New(sha512.New, []byte(rawsecret))
+		h = hmac.New(sha512.New, rawsecret)
 	default:
 		return nil, "", ErrKeyAlg
 	}
@@ -133,13 +137,12 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
 	t.Algorithm = rr.Algorithm
 	t.OrigId = m.Id
 
-	tbuf := make([]byte, t.len())
-	if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
-		tbuf = tbuf[:off] // reset to actual size used
-	} else {
+	tbuf := make([]byte, Len(t))
+	off, err := PackRR(t, tbuf, 0, nil, false)
+	if err != nil {
 		return nil, "", err
 	}
-	mbuf = append(mbuf, tbuf...)
+	mbuf = append(mbuf, tbuf[:off]...)
 	// Update the ArCount directly in the buffer.
 	binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
 

+ 282 - 136
libnetwork/vendor/github.com/miekg/dns/types.go

@@ -1,6 +1,7 @@
 package dns
 
 import (
+	"bytes"
 	"fmt"
 	"net"
 	"strconv"
@@ -61,6 +62,7 @@ const (
 	TypeCERT       uint16 = 37
 	TypeDNAME      uint16 = 39
 	TypeOPT        uint16 = 41 // EDNS
+	TypeAPL        uint16 = 42
 	TypeDS         uint16 = 43
 	TypeSSHFP      uint16 = 44
 	TypeRRSIG      uint16 = 46
@@ -205,9 +207,6 @@ var CertTypeToString = map[uint16]string{
 	CertOID:     "OID",
 }
 
-// StringToCertType is the reverseof CertTypeToString.
-var StringToCertType = reverseInt16(CertTypeToString)
-
 //go:generate go run types_generate.go
 
 // Question holds a DNS question. There can be multiple questions in the
@@ -218,8 +217,10 @@ type Question struct {
 	Qclass uint16
 }
 
-func (q *Question) len() int {
-	return len(q.Name) + 1 + 2 + 2
+func (q *Question) len(off int, compression map[string]struct{}) int {
+	l := domainNameLen(q.Name, off, compression, true)
+	l += 2 + 2
+	return l
 }
 
 func (q *Question) String() (s string) {
@@ -239,6 +240,25 @@ type ANY struct {
 
 func (rr *ANY) String() string { return rr.Hdr.String() }
 
+func (rr *ANY) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on ANY")
+}
+
+// NULL RR. See RFC 1035.
+type NULL struct {
+	Hdr  RR_Header
+	Data string `dns:"any"`
+}
+
+func (rr *NULL) String() string {
+	// There is no presentation format; prefix string with a comment.
+	return ";" + rr.Hdr.String() + rr.Data
+}
+
+func (rr *NULL) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on NULL")
+}
+
 // CNAME RR. See RFC 1034.
 type CNAME struct {
 	Hdr    RR_Header
@@ -330,7 +350,7 @@ func (rr *MX) String() string {
 type AFSDB struct {
 	Hdr      RR_Header
 	Subtype  uint16
-	Hostname string `dns:"cdomain-name"`
+	Hostname string `dns:"domain-name"`
 }
 
 func (rr *AFSDB) String() string {
@@ -351,7 +371,7 @@ func (rr *X25) String() string {
 type RT struct {
 	Hdr        RR_Header
 	Preference uint16
-	Host       string `dns:"cdomain-name"`
+	Host       string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
 }
 
 func (rr *RT) String() string {
@@ -386,7 +406,7 @@ type RP struct {
 }
 
 func (rr *RP) String() string {
-	return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
+	return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
 }
 
 // SOA RR. See RFC 1035.
@@ -419,128 +439,173 @@ type TXT struct {
 func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
 
 func sprintName(s string) string {
-	src := []byte(s)
-	dst := make([]byte, 0, len(src))
-	for i := 0; i < len(src); {
-		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
-			dst = append(dst, src[i:i+2]...)
+	var dst strings.Builder
+
+	for i := 0; i < len(s); {
+		if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
+			if dst.Len() != 0 {
+				dst.WriteString(s[i : i+2])
+			}
 			i += 2
-		} else {
-			b, n := nextByte(src, i)
-			if n == 0 {
-				i++ // dangling back slash
-			} else if b == '.' {
-				dst = append(dst, b)
-			} else {
-				dst = appendDomainNameByte(dst, b)
+			continue
+		}
+
+		b, n := nextByte(s, i)
+		if n == 0 {
+			i++
+			continue
+		}
+		if b == '.' {
+			if dst.Len() != 0 {
+				dst.WriteByte('.')
 			}
 			i += n
+			continue
 		}
+		switch b {
+		case ' ', '\'', '@', ';', '(', ')', '"', '\\': // additional chars to escape
+			if dst.Len() == 0 {
+				dst.Grow(len(s) * 2)
+				dst.WriteString(s[:i])
+			}
+			dst.WriteByte('\\')
+			dst.WriteByte(b)
+		default:
+			if ' ' <= b && b <= '~' {
+				if dst.Len() != 0 {
+					dst.WriteByte(b)
+				}
+			} else {
+				if dst.Len() == 0 {
+					dst.Grow(len(s) * 2)
+					dst.WriteString(s[:i])
+				}
+				dst.WriteString(escapeByte(b))
+			}
+		}
+		i += n
+	}
+	if dst.Len() == 0 {
+		return s
 	}
-	return string(dst)
+	return dst.String()
 }
 
 func sprintTxtOctet(s string) string {
-	src := []byte(s)
-	dst := make([]byte, 0, len(src))
-	dst = append(dst, '"')
-	for i := 0; i < len(src); {
-		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
-			dst = append(dst, src[i:i+2]...)
+	var dst strings.Builder
+	dst.Grow(2 + len(s))
+	dst.WriteByte('"')
+	for i := 0; i < len(s); {
+		if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
+			dst.WriteString(s[i : i+2])
 			i += 2
-		} else {
-			b, n := nextByte(src, i)
-			if n == 0 {
-				i++ // dangling back slash
-			} else if b == '.' {
-				dst = append(dst, b)
-			} else {
-				if b < ' ' || b > '~' {
-					dst = appendByte(dst, b)
-				} else {
-					dst = append(dst, b)
-				}
-			}
-			i += n
+			continue
+		}
+
+		b, n := nextByte(s, i)
+		switch {
+		case n == 0:
+			i++ // dangling back slash
+		case b == '.':
+			dst.WriteByte('.')
+		case b < ' ' || b > '~':
+			dst.WriteString(escapeByte(b))
+		default:
+			dst.WriteByte(b)
 		}
+		i += n
 	}
-	dst = append(dst, '"')
-	return string(dst)
+	dst.WriteByte('"')
+	return dst.String()
 }
 
 func sprintTxt(txt []string) string {
-	var out []byte
+	var out strings.Builder
 	for i, s := range txt {
+		out.Grow(3 + len(s))
 		if i > 0 {
-			out = append(out, ` "`...)
+			out.WriteString(` "`)
 		} else {
-			out = append(out, '"')
+			out.WriteByte('"')
 		}
-		bs := []byte(s)
-		for j := 0; j < len(bs); {
-			b, n := nextByte(bs, j)
+		for j := 0; j < len(s); {
+			b, n := nextByte(s, j)
 			if n == 0 {
 				break
 			}
-			out = appendTXTStringByte(out, b)
+			writeTXTStringByte(&out, b)
 			j += n
 		}
-		out = append(out, '"')
+		out.WriteByte('"')
 	}
-	return string(out)
-}
-
-func appendDomainNameByte(s []byte, b byte) []byte {
-	switch b {
-	case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
-		return append(s, '\\', b)
+	return out.String()
+}
+
+func writeTXTStringByte(s *strings.Builder, b byte) {
+	switch {
+	case b == '"' || b == '\\':
+		s.WriteByte('\\')
+		s.WriteByte(b)
+	case b < ' ' || b > '~':
+		s.WriteString(escapeByte(b))
+	default:
+		s.WriteByte(b)
 	}
-	return appendTXTStringByte(s, b)
 }
 
-func appendTXTStringByte(s []byte, b byte) []byte {
-	switch b {
-	case '"', '\\':
-		return append(s, '\\', b)
-	}
-	if b < ' ' || b > '~' {
-		return appendByte(s, b)
-	}
-	return append(s, b)
-}
+const (
+	escapedByteSmall = "" +
+		`\000\001\002\003\004\005\006\007\008\009` +
+		`\010\011\012\013\014\015\016\017\018\019` +
+		`\020\021\022\023\024\025\026\027\028\029` +
+		`\030\031`
+	escapedByteLarge = `\127\128\129` +
+		`\130\131\132\133\134\135\136\137\138\139` +
+		`\140\141\142\143\144\145\146\147\148\149` +
+		`\150\151\152\153\154\155\156\157\158\159` +
+		`\160\161\162\163\164\165\166\167\168\169` +
+		`\170\171\172\173\174\175\176\177\178\179` +
+		`\180\181\182\183\184\185\186\187\188\189` +
+		`\190\191\192\193\194\195\196\197\198\199` +
+		`\200\201\202\203\204\205\206\207\208\209` +
+		`\210\211\212\213\214\215\216\217\218\219` +
+		`\220\221\222\223\224\225\226\227\228\229` +
+		`\230\231\232\233\234\235\236\237\238\239` +
+		`\240\241\242\243\244\245\246\247\248\249` +
+		`\250\251\252\253\254\255`
+)
 
-func appendByte(s []byte, b byte) []byte {
-	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)
+// escapeByte returns the \DDD escaping of b which must
+// satisfy b < ' ' || b > '~'.
+func escapeByte(b byte) string {
+	if b < ' ' {
+		return escapedByteSmall[b*4 : b*4+4]
 	}
-	return s
+
+	b -= '~' + 1
+	// The cast here is needed as b*4 may overflow byte.
+	return escapedByteLarge[int(b)*4 : int(b)*4+4]
 }
 
-func nextByte(b []byte, offset int) (byte, int) {
-	if offset >= len(b) {
+func nextByte(s string, offset int) (byte, int) {
+	if offset >= len(s) {
 		return 0, 0
 	}
-	if b[offset] != '\\' {
+	if s[offset] != '\\' {
 		// not an escape sequence
-		return b[offset], 1
+		return s[offset], 1
 	}
-	switch len(b) - offset {
+	switch len(s) - offset {
 	case 1: // dangling escape
 		return 0, 0
 	case 2, 3: // too short to be \ddd
 	default: // maybe \ddd
-		if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
-			return dddToByte(b[offset+1:]), 4
+		if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
+			return dddStringToByte(s[offset+1:]), 4
 		}
 	}
 	// not \ddd, just an RFC 1035 "quoted" character
-	return b[offset+1], 2
+	return s[offset+1], 2
 }
 
 // SPF RR. See RFC 4408, Section 3.1.1.
@@ -728,7 +793,7 @@ func (rr *LOC) String() string {
 	lat = lat % LOC_DEGREES
 	m := lat / LOC_HOURS
 	lat = lat % LOC_HOURS
-	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
+	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns)
 
 	lon := rr.Longitude
 	ew := "E"
@@ -742,7 +807,7 @@ func (rr *LOC) String() string {
 	lon = lon % LOC_DEGREES
 	m = lon / LOC_HOURS
 	lon = lon % LOC_HOURS
-	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
+	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
 
 	var alt = float64(rr.Altitude) / 100
 	alt -= LOC_ALTITUDEBASE
@@ -752,9 +817,9 @@ func (rr *LOC) String() string {
 		s += fmt.Sprintf("%.0fm ", alt)
 	}
 
-	s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
-	s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
-	s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
+	s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m "
+	s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m "
+	s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m"
 
 	return s
 }
@@ -801,22 +866,16 @@ type NSEC struct {
 
 func (rr *NSEC) String() string {
 	s := rr.Hdr.String() + sprintName(rr.NextDomain)
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *NSEC) len() int {
-	l := rr.Hdr.len() + len(rr.NextDomain) + 1
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
-		}
-		lastwindow = uint32(window)
-	}
+func (rr *NSEC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.NextDomain, off+l, compression, false)
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -966,22 +1025,16 @@ func (rr *NSEC3) String() string {
 		" " + strconv.Itoa(int(rr.Iterations)) +
 		" " + saltToString(rr.Salt) +
 		" " + rr.NextDomain
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *NSEC3) len() int {
-	l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
-		}
-		lastwindow = uint32(window)
-	}
+func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -1020,10 +1073,16 @@ type TKEY struct {
 
 // TKEY has no official presentation format, but this will suffice.
 func (rr *TKEY) String() string {
-	s := "\n;; TKEY PSEUDOSECTION:\n"
-	s += rr.Hdr.String() + " " + rr.Algorithm + " " +
-		strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
-		strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
+	s := ";" + rr.Hdr.String() +
+		" " + rr.Algorithm +
+		" " + TimeToString(rr.Inception) +
+		" " + TimeToString(rr.Expiration) +
+		" " + strconv.Itoa(int(rr.Mode)) +
+		" " + strconv.Itoa(int(rr.Error)) +
+		" " + strconv.Itoa(int(rr.KeySize)) +
+		" " + rr.Key +
+		" " + strconv.Itoa(int(rr.OtherLen)) +
+		" " + rr.OtherData
 	return s
 }
 
@@ -1283,34 +1342,110 @@ type CSYNC struct {
 func (rr *CSYNC) String() string {
 	s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
 
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *CSYNC) len() int {
-	l := rr.Hdr.len() + 4 + 2
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
+func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 4 + 2
+	l += typeBitMapLen(rr.TypeBitMap)
+	return l
+}
+
+// APL RR. See RFC 3123.
+type APL struct {
+	Hdr      RR_Header
+	Prefixes []APLPrefix `dns:"apl"`
+}
+
+// APLPrefix is an address prefix hold by an APL record.
+type APLPrefix struct {
+	Negation bool
+	Network  net.IPNet
+}
+
+// String returns presentation form of the APL record.
+func (rr *APL) String() string {
+	var sb strings.Builder
+	sb.WriteString(rr.Hdr.String())
+	for i, p := range rr.Prefixes {
+		if i > 0 {
+			sb.WriteByte(' ')
 		}
-		lastwindow = uint32(window)
+		sb.WriteString(p.str())
 	}
-	return l
+	return sb.String()
+}
+
+// str returns presentation form of the APL prefix.
+func (p *APLPrefix) str() string {
+	var sb strings.Builder
+	if p.Negation {
+		sb.WriteByte('!')
+	}
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		sb.WriteByte('1')
+	case net.IPv6len:
+		sb.WriteByte('2')
+	}
+
+	sb.WriteByte(':')
+
+	switch len(p.Network.IP) {
+	case net.IPv4len:
+		sb.WriteString(p.Network.IP.String())
+	case net.IPv6len:
+		// add prefix for IPv4-mapped IPv6
+		if v4 := p.Network.IP.To4(); v4 != nil {
+			sb.WriteString("::ffff:")
+		}
+		sb.WriteString(p.Network.IP.String())
+	}
+
+	sb.WriteByte('/')
+
+	prefix, _ := p.Network.Mask.Size()
+	sb.WriteString(strconv.Itoa(prefix))
+
+	return sb.String()
+}
+
+// equals reports whether two APL prefixes are identical.
+func (a *APLPrefix) equals(b *APLPrefix) bool {
+	return a.Negation == b.Negation &&
+		bytes.Equal(a.Network.IP, b.Network.IP) &&
+		bytes.Equal(a.Network.Mask, b.Network.Mask)
+}
+
+// copy returns a copy of the APL prefix.
+func (p *APLPrefix) copy() APLPrefix {
+	return APLPrefix{
+		Negation: p.Negation,
+		Network:  copyNet(p.Network),
+	}
+}
+
+// len returns size of the prefix in wire format.
+func (p *APLPrefix) len() int {
+	// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
+	prefix, _ := p.Network.Mask.Size()
+	return 4 + (prefix+7)/8
 }
 
 // TimeToString translates the RRSIG's incep. and expir. times to the
 // string representation used when printing the record.
 // It takes serial arithmetic (RFC 1982) into account.
 func TimeToString(t uint32) string {
-	mod := ((int64(t) - time.Now().Unix()) / year68) - 1
+	mod := (int64(t)-time.Now().Unix())/year68 - 1
 	if mod < 0 {
 		mod = 0
 	}
-	ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
+	ti := time.Unix(int64(t)-mod*year68, 0).UTC()
 	return ti.Format("20060102150405")
 }
 
@@ -1322,11 +1457,11 @@ func StringToTime(s string) (uint32, error) {
 	if err != nil {
 		return 0, err
 	}
-	mod := (t.Unix() / year68) - 1
+	mod := t.Unix()/year68 - 1
 	if mod < 0 {
 		mod = 0
 	}
-	return uint32(t.Unix() - (mod * year68)), nil
+	return uint32(t.Unix() - mod*year68), nil
 }
 
 // saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
@@ -1358,6 +1493,17 @@ func copyIP(ip net.IP) net.IP {
 	return p
 }
 
+// copyNet returns a copy of a subnet.
+func copyNet(n net.IPNet) net.IPNet {
+	m := make(net.IPMask, len(n.Mask))
+	copy(m, n.Mask)
+
+	return net.IPNet{
+		IP:   copyIP(n.IP),
+		Mask: m,
+	}
+}
+
 // SplitN splits a string into N sized string chunks.
 // This might become an exported function once.
 func splitN(s string, n int) []string {

+ 2 - 4
libnetwork/vendor/github.com/miekg/dns/udp_windows.go

@@ -20,15 +20,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
 	if err != nil {
 		return n, nil, err
 	}
-	session := &SessionUDP{raddr.(*net.UDPAddr)}
-	return n, session, err
+	return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
 }
 
 // WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
 // TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
 func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
-	n, err := conn.WriteTo(b, session.raddr)
-	return n, err
+	return conn.WriteTo(b, session.raddr)
 }
 
 // TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods

+ 9 - 5
libnetwork/vendor/github.com/miekg/dns/update.go

@@ -44,7 +44,8 @@ func (u *Msg) RRsetUsed(rr []RR) {
 		u.Answer = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+		h := r.Header()
+		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
 	}
 }
 
@@ -55,7 +56,8 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
 		u.Answer = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
+		h := r.Header()
+		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassNONE}})
 	}
 }
 
@@ -79,7 +81,8 @@ func (u *Msg) RemoveRRset(rr []RR) {
 		u.Ns = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+		h := r.Header()
+		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
 	}
 }
 
@@ -99,8 +102,9 @@ func (u *Msg) Remove(rr []RR) {
 		u.Ns = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		r.Header().Class = ClassNONE
-		r.Header().Ttl = 0
+		h := r.Header()
+		h.Class = ClassNONE
+		h.Ttl = 0
 		u.Ns = append(u.Ns, r)
 	}
 }

+ 1 - 1
libnetwork/vendor/github.com/miekg/dns/version.go

@@ -3,7 +3,7 @@ package dns
 import "fmt"
 
 // Version is current version of this library.
-var Version = V{1, 0, 7}
+var Version = V{1, 1, 27}
 
 // V holds the version of this library.
 type V struct {

+ 35 - 29
libnetwork/vendor/github.com/miekg/dns/xfr.go

@@ -35,30 +35,36 @@ type Transfer struct {
 //	channel, err := transfer.In(message, master)
 //
 func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
+	switch q.Question[0].Qtype {
+	case TypeAXFR, TypeIXFR:
+	default:
+		return nil, &Error{"unsupported question type"}
+	}
+
 	timeout := dnsTimeout
 	if t.DialTimeout != 0 {
 		timeout = t.DialTimeout
 	}
+
 	if t.Conn == nil {
 		t.Conn, err = DialTimeout("tcp", a, timeout)
 		if err != nil {
 			return nil, err
 		}
 	}
+
 	if err := t.WriteMsg(q); err != nil {
 		return nil, err
 	}
+
 	env = make(chan *Envelope)
-	go func() {
-		if q.Question[0].Qtype == TypeAXFR {
-			go t.inAxfr(q, env)
-			return
-		}
-		if q.Question[0].Qtype == TypeIXFR {
-			go t.inIxfr(q, env)
-			return
-		}
-	}()
+	switch q.Question[0].Qtype {
+	case TypeAXFR:
+		go t.inAxfr(q, env)
+	case TypeIXFR:
+		go t.inIxfr(q, env)
+	}
+
 	return env, nil
 }
 
@@ -111,7 +117,7 @@ func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
 }
 
 func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
-	serial := uint32(0) // The first serial seen is the current server serial
+	var serial uint32 // The first serial seen is the current server serial
 	axfr := true
 	n := 0
 	qser := q.Ns[0].(*SOA).Serial
@@ -176,14 +182,17 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
 //
 //	ch := make(chan *dns.Envelope)
 //	tr := new(dns.Transfer)
-//	go tr.Out(w, r, ch)
+//	var wg sync.WaitGroup
+//	go func() {
+//		tr.Out(w, r, ch)
+//		wg.Done()
+//	}()
 //	ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
 //	close(ch)
-//	w.Hijack()
-//	// w.Close() // Client closes connection
+//	wg.Wait() // wait until everything is written out
+//	w.Close() // close connection
 //
-// The server is responsible for sending the correct sequence of RRs through the
-// channel ch.
+// The server is responsible for sending the correct sequence of RRs through the channel ch.
 func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
 	for x := range ch {
 		r := new(Msg)
@@ -192,11 +201,14 @@ func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
 		r.Authoritative = true
 		// assume it fits TODO(miek): fix
 		r.Answer = append(r.Answer, x.RR...)
+		if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
+			r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
+		}
 		if err := w.WriteMsg(r); err != nil {
 			return err
 		}
+		w.TsigTimersOnly(true)
 	}
-	w.TsigTimersOnly(true)
 	return nil
 }
 
@@ -237,24 +249,18 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
 	if err != nil {
 		return err
 	}
-	if _, err = t.Write(out); err != nil {
-		return err
-	}
-	return nil
+	_, err = t.Write(out)
+	return err
 }
 
 func isSOAFirst(in *Msg) bool {
-	if len(in.Answer) > 0 {
-		return in.Answer[0].Header().Rrtype == TypeSOA
-	}
-	return false
+	return len(in.Answer) > 0 &&
+		in.Answer[0].Header().Rrtype == TypeSOA
 }
 
 func isSOALast(in *Msg) bool {
-	if len(in.Answer) > 0 {
-		return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
-	}
-	return false
+	return len(in.Answer) > 0 &&
+		in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
 }
 
 const errXFR = "bad xfr rcode: %d"

+ 0 - 155
libnetwork/vendor/github.com/miekg/dns/zcompress.go

@@ -1,155 +0,0 @@
-// Code generated by "go run compress_generate.go"; DO NOT EDIT.
-
-package dns
-
-func compressionLenHelperType(c map[string]int, r RR, initLen int) int {
-	currentLen := initLen
-	switch x := r.(type) {
-	case *AFSDB:
-		currentLen -= len(x.Hostname) + 1
-		currentLen += compressionLenHelper(c, x.Hostname, currentLen)
-	case *CNAME:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *DNAME:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *HIP:
-		for i := range x.RendezvousServers {
-			currentLen -= len(x.RendezvousServers[i]) + 1
-		}
-		for i := range x.RendezvousServers {
-			currentLen += compressionLenHelper(c, x.RendezvousServers[i], currentLen)
-		}
-	case *KX:
-		currentLen -= len(x.Exchanger) + 1
-		currentLen += compressionLenHelper(c, x.Exchanger, currentLen)
-	case *LP:
-		currentLen -= len(x.Fqdn) + 1
-		currentLen += compressionLenHelper(c, x.Fqdn, currentLen)
-	case *MB:
-		currentLen -= len(x.Mb) + 1
-		currentLen += compressionLenHelper(c, x.Mb, currentLen)
-	case *MD:
-		currentLen -= len(x.Md) + 1
-		currentLen += compressionLenHelper(c, x.Md, currentLen)
-	case *MF:
-		currentLen -= len(x.Mf) + 1
-		currentLen += compressionLenHelper(c, x.Mf, currentLen)
-	case *MG:
-		currentLen -= len(x.Mg) + 1
-		currentLen += compressionLenHelper(c, x.Mg, currentLen)
-	case *MINFO:
-		currentLen -= len(x.Rmail) + 1
-		currentLen += compressionLenHelper(c, x.Rmail, currentLen)
-		currentLen -= len(x.Email) + 1
-		currentLen += compressionLenHelper(c, x.Email, currentLen)
-	case *MR:
-		currentLen -= len(x.Mr) + 1
-		currentLen += compressionLenHelper(c, x.Mr, currentLen)
-	case *MX:
-		currentLen -= len(x.Mx) + 1
-		currentLen += compressionLenHelper(c, x.Mx, currentLen)
-	case *NAPTR:
-		currentLen -= len(x.Replacement) + 1
-		currentLen += compressionLenHelper(c, x.Replacement, currentLen)
-	case *NS:
-		currentLen -= len(x.Ns) + 1
-		currentLen += compressionLenHelper(c, x.Ns, currentLen)
-	case *NSAPPTR:
-		currentLen -= len(x.Ptr) + 1
-		currentLen += compressionLenHelper(c, x.Ptr, currentLen)
-	case *NSEC:
-		currentLen -= len(x.NextDomain) + 1
-		currentLen += compressionLenHelper(c, x.NextDomain, currentLen)
-	case *PTR:
-		currentLen -= len(x.Ptr) + 1
-		currentLen += compressionLenHelper(c, x.Ptr, currentLen)
-	case *PX:
-		currentLen -= len(x.Map822) + 1
-		currentLen += compressionLenHelper(c, x.Map822, currentLen)
-		currentLen -= len(x.Mapx400) + 1
-		currentLen += compressionLenHelper(c, x.Mapx400, currentLen)
-	case *RP:
-		currentLen -= len(x.Mbox) + 1
-		currentLen += compressionLenHelper(c, x.Mbox, currentLen)
-		currentLen -= len(x.Txt) + 1
-		currentLen += compressionLenHelper(c, x.Txt, currentLen)
-	case *RRSIG:
-		currentLen -= len(x.SignerName) + 1
-		currentLen += compressionLenHelper(c, x.SignerName, currentLen)
-	case *RT:
-		currentLen -= len(x.Host) + 1
-		currentLen += compressionLenHelper(c, x.Host, currentLen)
-	case *SIG:
-		currentLen -= len(x.SignerName) + 1
-		currentLen += compressionLenHelper(c, x.SignerName, currentLen)
-	case *SOA:
-		currentLen -= len(x.Ns) + 1
-		currentLen += compressionLenHelper(c, x.Ns, currentLen)
-		currentLen -= len(x.Mbox) + 1
-		currentLen += compressionLenHelper(c, x.Mbox, currentLen)
-	case *SRV:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *TALINK:
-		currentLen -= len(x.PreviousName) + 1
-		currentLen += compressionLenHelper(c, x.PreviousName, currentLen)
-		currentLen -= len(x.NextName) + 1
-		currentLen += compressionLenHelper(c, x.NextName, currentLen)
-	case *TKEY:
-		currentLen -= len(x.Algorithm) + 1
-		currentLen += compressionLenHelper(c, x.Algorithm, currentLen)
-	case *TSIG:
-		currentLen -= len(x.Algorithm) + 1
-		currentLen += compressionLenHelper(c, x.Algorithm, currentLen)
-	}
-	return currentLen - initLen
-}
-
-func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {
-	switch x := r.(type) {
-	case *AFSDB:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Hostname)
-		return k1, ok1, sz1
-	case *CNAME:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Target)
-		return k1, ok1, sz1
-	case *MB:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mb)
-		return k1, ok1, sz1
-	case *MD:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Md)
-		return k1, ok1, sz1
-	case *MF:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mf)
-		return k1, ok1, sz1
-	case *MG:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mg)
-		return k1, ok1, sz1
-	case *MINFO:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Rmail)
-		k2, ok2, sz2 := compressionLenSearch(c, x.Email)
-		return k1 + k2, ok1 && ok2, sz1 + sz2
-	case *MR:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mr)
-		return k1, ok1, sz1
-	case *MX:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mx)
-		return k1, ok1, sz1
-	case *NS:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ns)
-		return k1, ok1, sz1
-	case *PTR:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ptr)
-		return k1, ok1, sz1
-	case *RT:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Host)
-		return k1, ok1, sz1
-	case *SOA:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ns)
-		k2, ok2, sz2 := compressionLenSearch(c, x.Mbox)
-		return k1 + k2, ok1 && ok2, sz1 + sz2
-	}
-	return 0, false, 0
-}

+ 1157 - 0
libnetwork/vendor/github.com/miekg/dns/zduplicate.go

@@ -0,0 +1,1157 @@
+// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
+
+package dns
+
+// isDuplicate() functions
+
+func (r1 *A) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*A)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !r1.A.Equal(r2.A) {
+		return false
+	}
+	return true
+}
+
+func (r1 *AAAA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AAAA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !r1.AAAA.Equal(r2.AAAA) {
+		return false
+	}
+	return true
+}
+
+func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AFSDB)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Subtype != r2.Subtype {
+		return false
+	}
+	if !isDuplicateName(r1.Hostname, r2.Hostname) {
+		return false
+	}
+	return true
+}
+
+func (r1 *ANY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*ANY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	return true
+}
+
+func (r1 *APL) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*APL)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Prefixes) != len(r2.Prefixes) {
+		return false
+	}
+	for i := 0; i < len(r1.Prefixes); i++ {
+		if !r1.Prefixes[i].equals(&r2.Prefixes[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *AVC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AVC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Txt) != len(r2.Txt) {
+		return false
+	}
+	for i := 0; i < len(r1.Txt); i++ {
+		if r1.Txt[i] != r2.Txt[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *CAA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CAA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Flag != r2.Flag {
+		return false
+	}
+	if r1.Tag != r2.Tag {
+		return false
+	}
+	if r1.Value != r2.Value {
+		return false
+	}
+	return true
+}
+
+func (r1 *CERT) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CERT)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Type != r2.Type {
+		return false
+	}
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.Certificate != r2.Certificate {
+		return false
+	}
+	return true
+}
+
+func (r1 *CNAME) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CNAME)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Target, r2.Target) {
+		return false
+	}
+	return true
+}
+
+func (r1 *CSYNC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CSYNC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Serial != r2.Serial {
+		return false
+	}
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
+		return false
+	}
+	for i := 0; i < len(r1.TypeBitMap); i++ {
+		if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *DHCID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DHCID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	return true
+}
+
+func (r1 *DNAME) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DNAME)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Target, r2.Target) {
+		return false
+	}
+	return true
+}
+
+func (r1 *DNSKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DNSKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Protocol != r2.Protocol {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
+func (r1 *DS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.DigestType != r2.DigestType {
+		return false
+	}
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	return true
+}
+
+func (r1 *EID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Endpoint != r2.Endpoint {
+		return false
+	}
+	return true
+}
+
+func (r1 *EUI48) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EUI48)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Address != r2.Address {
+		return false
+	}
+	return true
+}
+
+func (r1 *EUI64) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EUI64)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Address != r2.Address {
+		return false
+	}
+	return true
+}
+
+func (r1 *GID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*GID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Gid != r2.Gid {
+		return false
+	}
+	return true
+}
+
+func (r1 *GPOS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*GPOS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Longitude != r2.Longitude {
+		return false
+	}
+	if r1.Latitude != r2.Latitude {
+		return false
+	}
+	if r1.Altitude != r2.Altitude {
+		return false
+	}
+	return true
+}
+
+func (r1 *HINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*HINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Cpu != r2.Cpu {
+		return false
+	}
+	if r1.Os != r2.Os {
+		return false
+	}
+	return true
+}
+
+func (r1 *HIP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*HIP)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.HitLength != r2.HitLength {
+		return false
+	}
+	if r1.PublicKeyAlgorithm != r2.PublicKeyAlgorithm {
+		return false
+	}
+	if r1.PublicKeyLength != r2.PublicKeyLength {
+		return false
+	}
+	if r1.Hit != r2.Hit {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	if len(r1.RendezvousServers) != len(r2.RendezvousServers) {
+		return false
+	}
+	for i := 0; i < len(r1.RendezvousServers); i++ {
+		if !isDuplicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *KX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*KX)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !isDuplicateName(r1.Exchanger, r2.Exchanger) {
+		return false
+	}
+	return true
+}
+
+func (r1 *L32) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*L32)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !r1.Locator32.Equal(r2.Locator32) {
+		return false
+	}
+	return true
+}
+
+func (r1 *L64) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*L64)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if r1.Locator64 != r2.Locator64 {
+		return false
+	}
+	return true
+}
+
+func (r1 *LOC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*LOC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Version != r2.Version {
+		return false
+	}
+	if r1.Size != r2.Size {
+		return false
+	}
+	if r1.HorizPre != r2.HorizPre {
+		return false
+	}
+	if r1.VertPre != r2.VertPre {
+		return false
+	}
+	if r1.Latitude != r2.Latitude {
+		return false
+	}
+	if r1.Longitude != r2.Longitude {
+		return false
+	}
+	if r1.Altitude != r2.Altitude {
+		return false
+	}
+	return true
+}
+
+func (r1 *LP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*LP)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !isDuplicateName(r1.Fqdn, r2.Fqdn) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MB) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MB)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mb, r2.Mb) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MD) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MD)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Md, r2.Md) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MF) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MF)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mf, r2.Mf) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mg, r2.Mg) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Rmail, r2.Rmail) {
+		return false
+	}
+	if !isDuplicateName(r1.Email, r2.Email) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mr, r2.Mr) {
+		return false
+	}
+	return true
+}
+
+func (r1 *MX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MX)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !isDuplicateName(r1.Mx, r2.Mx) {
+		return false
+	}
+	return true
+}
+
+func (r1 *NAPTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NAPTR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Order != r2.Order {
+		return false
+	}
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Service != r2.Service {
+		return false
+	}
+	if r1.Regexp != r2.Regexp {
+		return false
+	}
+	if !isDuplicateName(r1.Replacement, r2.Replacement) {
+		return false
+	}
+	return true
+}
+
+func (r1 *NID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if r1.NodeID != r2.NodeID {
+		return false
+	}
+	return true
+}
+
+func (r1 *NIMLOC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NIMLOC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Locator != r2.Locator {
+		return false
+	}
+	return true
+}
+
+func (r1 *NINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.ZSData) != len(r2.ZSData) {
+		return false
+	}
+	for i := 0; i < len(r1.ZSData); i++ {
+		if r1.ZSData[i] != r2.ZSData[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *NS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ns, r2.Ns) {
+		return false
+	}
+	return true
+}
+
+func (r1 *NSAPPTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSAPPTR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ptr, r2.Ptr) {
+		return false
+	}
+	return true
+}
+
+func (r1 *NSEC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
+		return false
+	}
+	if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
+		return false
+	}
+	for i := 0; i < len(r1.TypeBitMap); i++ {
+		if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *NSEC3) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC3)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Hash != r2.Hash {
+		return false
+	}
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Iterations != r2.Iterations {
+		return false
+	}
+	if r1.SaltLength != r2.SaltLength {
+		return false
+	}
+	if r1.Salt != r2.Salt {
+		return false
+	}
+	if r1.HashLength != r2.HashLength {
+		return false
+	}
+	if r1.NextDomain != r2.NextDomain {
+		return false
+	}
+	if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
+		return false
+	}
+	for i := 0; i < len(r1.TypeBitMap); i++ {
+		if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *NSEC3PARAM) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC3PARAM)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Hash != r2.Hash {
+		return false
+	}
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Iterations != r2.Iterations {
+		return false
+	}
+	if r1.SaltLength != r2.SaltLength {
+		return false
+	}
+	if r1.Salt != r2.Salt {
+		return false
+	}
+	return true
+}
+
+func (r1 *NULL) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NULL)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Data != r2.Data {
+		return false
+	}
+	return true
+}
+
+func (r1 *OPENPGPKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*OPENPGPKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
+func (r1 *PTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*PTR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ptr, r2.Ptr) {
+		return false
+	}
+	return true
+}
+
+func (r1 *PX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*PX)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !isDuplicateName(r1.Map822, r2.Map822) {
+		return false
+	}
+	if !isDuplicateName(r1.Mapx400, r2.Mapx400) {
+		return false
+	}
+	return true
+}
+
+func (r1 *RFC3597) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RFC3597)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Rdata != r2.Rdata {
+		return false
+	}
+	return true
+}
+
+func (r1 *RKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Flags != r2.Flags {
+		return false
+	}
+	if r1.Protocol != r2.Protocol {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
+		return false
+	}
+	return true
+}
+
+func (r1 *RP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RP)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mbox, r2.Mbox) {
+		return false
+	}
+	if !isDuplicateName(r1.Txt, r2.Txt) {
+		return false
+	}
+	return true
+}
+
+func (r1 *RRSIG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RRSIG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.TypeCovered != r2.TypeCovered {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.Labels != r2.Labels {
+		return false
+	}
+	if r1.OrigTtl != r2.OrigTtl {
+		return false
+	}
+	if r1.Expiration != r2.Expiration {
+		return false
+	}
+	if r1.Inception != r2.Inception {
+		return false
+	}
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if !isDuplicateName(r1.SignerName, r2.SignerName) {
+		return false
+	}
+	if r1.Signature != r2.Signature {
+		return false
+	}
+	return true
+}
+
+func (r1 *RT) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RT)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !isDuplicateName(r1.Host, r2.Host) {
+		return false
+	}
+	return true
+}
+
+func (r1 *SMIMEA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SMIMEA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Usage != r2.Usage {
+		return false
+	}
+	if r1.Selector != r2.Selector {
+		return false
+	}
+	if r1.MatchingType != r2.MatchingType {
+		return false
+	}
+	if r1.Certificate != r2.Certificate {
+		return false
+	}
+	return true
+}
+
+func (r1 *SOA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SOA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ns, r2.Ns) {
+		return false
+	}
+	if !isDuplicateName(r1.Mbox, r2.Mbox) {
+		return false
+	}
+	if r1.Serial != r2.Serial {
+		return false
+	}
+	if r1.Refresh != r2.Refresh {
+		return false
+	}
+	if r1.Retry != r2.Retry {
+		return false
+	}
+	if r1.Expire != r2.Expire {
+		return false
+	}
+	if r1.Minttl != r2.Minttl {
+		return false
+	}
+	return true
+}
+
+func (r1 *SPF) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SPF)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Txt) != len(r2.Txt) {
+		return false
+	}
+	for i := 0; i < len(r1.Txt); i++ {
+		if r1.Txt[i] != r2.Txt[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *SRV) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SRV)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Priority != r2.Priority {
+		return false
+	}
+	if r1.Weight != r2.Weight {
+		return false
+	}
+	if r1.Port != r2.Port {
+		return false
+	}
+	if !isDuplicateName(r1.Target, r2.Target) {
+		return false
+	}
+	return true
+}
+
+func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SSHFP)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.Type != r2.Type {
+		return false
+	}
+	if r1.FingerPrint != r2.FingerPrint {
+		return false
+	}
+	return true
+}
+
+func (r1 *TA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.KeyTag != r2.KeyTag {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.DigestType != r2.DigestType {
+		return false
+	}
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	return true
+}
+
+func (r1 *TALINK) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TALINK)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.PreviousName, r2.PreviousName) {
+		return false
+	}
+	if !isDuplicateName(r1.NextName, r2.NextName) {
+		return false
+	}
+	return true
+}
+
+func (r1 *TKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
+		return false
+	}
+	if r1.Inception != r2.Inception {
+		return false
+	}
+	if r1.Expiration != r2.Expiration {
+		return false
+	}
+	if r1.Mode != r2.Mode {
+		return false
+	}
+	if r1.Error != r2.Error {
+		return false
+	}
+	if r1.KeySize != r2.KeySize {
+		return false
+	}
+	if r1.Key != r2.Key {
+		return false
+	}
+	if r1.OtherLen != r2.OtherLen {
+		return false
+	}
+	if r1.OtherData != r2.OtherData {
+		return false
+	}
+	return true
+}
+
+func (r1 *TLSA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TLSA)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Usage != r2.Usage {
+		return false
+	}
+	if r1.Selector != r2.Selector {
+		return false
+	}
+	if r1.MatchingType != r2.MatchingType {
+		return false
+	}
+	if r1.Certificate != r2.Certificate {
+		return false
+	}
+	return true
+}
+
+func (r1 *TSIG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TSIG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
+		return false
+	}
+	if r1.TimeSigned != r2.TimeSigned {
+		return false
+	}
+	if r1.Fudge != r2.Fudge {
+		return false
+	}
+	if r1.MACSize != r2.MACSize {
+		return false
+	}
+	if r1.MAC != r2.MAC {
+		return false
+	}
+	if r1.OrigId != r2.OrigId {
+		return false
+	}
+	if r1.Error != r2.Error {
+		return false
+	}
+	if r1.OtherLen != r2.OtherLen {
+		return false
+	}
+	if r1.OtherData != r2.OtherData {
+		return false
+	}
+	return true
+}
+
+func (r1 *TXT) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TXT)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if len(r1.Txt) != len(r2.Txt) {
+		return false
+	}
+	for i := 0; i < len(r1.Txt); i++ {
+		if r1.Txt[i] != r2.Txt[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (r1 *UID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*UID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Uid != r2.Uid {
+		return false
+	}
+	return true
+}
+
+func (r1 *UINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*UINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Uinfo != r2.Uinfo {
+		return false
+	}
+	return true
+}
+
+func (r1 *URI) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*URI)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Priority != r2.Priority {
+		return false
+	}
+	if r1.Weight != r2.Weight {
+		return false
+	}
+	if r1.Target != r2.Target {
+		return false
+	}
+	return true
+}
+
+func (r1 *X25) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*X25)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.PSDNAddress != r2.PSDNAddress {
+		return false
+	}
+	return true
+}

ファイルの差分が大きいため隠しています
+ 92 - 411
libnetwork/vendor/github.com/miekg/dns/zmsg.go


+ 201 - 166
libnetwork/vendor/github.com/miekg/dns/ztypes.go

@@ -13,6 +13,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeAAAA:       func() RR { return new(AAAA) },
 	TypeAFSDB:      func() RR { return new(AFSDB) },
 	TypeANY:        func() RR { return new(ANY) },
+	TypeAPL:        func() RR { return new(APL) },
 	TypeAVC:        func() RR { return new(AVC) },
 	TypeCAA:        func() RR { return new(CAA) },
 	TypeCDNSKEY:    func() RR { return new(CDNSKEY) },
@@ -54,6 +55,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeNSEC:       func() RR { return new(NSEC) },
 	TypeNSEC3:      func() RR { return new(NSEC3) },
 	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
+	TypeNULL:       func() RR { return new(NULL) },
 	TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
 	TypeOPT:        func() RR { return new(OPT) },
 	TypePTR:        func() RR { return new(PTR) },
@@ -86,6 +88,7 @@ var TypeToString = map[uint16]string{
 	TypeAAAA:       "AAAA",
 	TypeAFSDB:      "AFSDB",
 	TypeANY:        "ANY",
+	TypeAPL:        "APL",
 	TypeATMA:       "ATMA",
 	TypeAVC:        "AVC",
 	TypeAXFR:       "AXFR",
@@ -168,6 +171,7 @@ func (rr *A) Header() *RR_Header          { return &rr.Hdr }
 func (rr *AAAA) Header() *RR_Header       { return &rr.Hdr }
 func (rr *AFSDB) Header() *RR_Header      { return &rr.Hdr }
 func (rr *ANY) Header() *RR_Header        { return &rr.Hdr }
+func (rr *APL) Header() *RR_Header        { return &rr.Hdr }
 func (rr *AVC) Header() *RR_Header        { return &rr.Hdr }
 func (rr *CAA) Header() *RR_Header        { return &rr.Hdr }
 func (rr *CDNSKEY) Header() *RR_Header    { return &rr.Hdr }
@@ -209,6 +213,7 @@ func (rr *NSAPPTR) Header() *RR_Header    { return &rr.Hdr }
 func (rr *NSEC) Header() *RR_Header       { return &rr.Hdr }
 func (rr *NSEC3) Header() *RR_Header      { return &rr.Hdr }
 func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
+func (rr *NULL) Header() *RR_Header       { return &rr.Hdr }
 func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
 func (rr *OPT) Header() *RR_Header        { return &rr.Hdr }
 func (rr *PTR) Header() *RR_Header        { return &rr.Hdr }
@@ -236,144 +241,157 @@ 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
+func (rr *A) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	if len(rr.A) != 0 {
+		l += net.IPv4len
+	}
 	return l
 }
-func (rr *AAAA) len() int {
-	l := rr.Hdr.len()
-	l += net.IPv6len // AAAA
+func (rr *AAAA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	if len(rr.AAAA) != 0 {
+		l += net.IPv6len
+	}
 	return l
 }
-func (rr *AFSDB) len() int {
-	l := rr.Hdr.len()
+func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Subtype
-	l += len(rr.Hostname) + 1
+	l += domainNameLen(rr.Hostname, off+l, compression, false)
 	return l
 }
-func (rr *ANY) len() int {
-	l := rr.Hdr.len()
+func (rr *ANY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	return l
 }
-func (rr *AVC) len() int {
-	l := rr.Hdr.len()
+func (rr *APL) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	for _, x := range rr.Prefixes {
+		l += x.len()
+	}
+	return l
+}
+func (rr *AVC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *CAA) len() int {
-	l := rr.Hdr.len()
+func (rr *CAA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Flag
 	l += len(rr.Tag) + 1
 	l += len(rr.Value)
 	return l
 }
-func (rr *CERT) len() int {
-	l := rr.Hdr.len()
+func (rr *CERT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Type
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
 	return l
 }
-func (rr *CNAME) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Target) + 1
+func (rr *CNAME) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Target, off+l, compression, true)
 	return l
 }
-func (rr *DHCID) len() int {
-	l := rr.Hdr.len()
+func (rr *DHCID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.Digest))
 	return l
 }
-func (rr *DNAME) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Target) + 1
+func (rr *DNAME) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 }
-func (rr *DNSKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l++    // Protocol
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *DS) len() int {
-	l := rr.Hdr.len()
+func (rr *DS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
-func (rr *EID) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Endpoint)/2 + 1
+func (rr *EID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Endpoint) / 2
 	return l
 }
-func (rr *EUI48) len() int {
-	l := rr.Hdr.len()
+func (rr *EUI48) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 6 // Address
 	return l
 }
-func (rr *EUI64) len() int {
-	l := rr.Hdr.len()
+func (rr *EUI64) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 8 // Address
 	return l
 }
-func (rr *GID) len() int {
-	l := rr.Hdr.len()
+func (rr *GID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 4 // Gid
 	return l
 }
-func (rr *GPOS) len() int {
-	l := rr.Hdr.len()
+func (rr *GPOS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Longitude) + 1
 	l += len(rr.Latitude) + 1
 	l += len(rr.Altitude) + 1
 	return l
 }
-func (rr *HINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *HINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Cpu) + 1
 	l += len(rr.Os) + 1
 	return l
 }
-func (rr *HIP) len() int {
-	l := rr.Hdr.len()
+func (rr *HIP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // HitLength
 	l++    // PublicKeyAlgorithm
 	l += 2 // PublicKeyLength
 	l += len(rr.Hit) / 2
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	for _, x := range rr.RendezvousServers {
-		l += len(x) + 1
+		l += domainNameLen(x, off+l, compression, false)
 	}
 	return l
 }
-func (rr *KX) len() int {
-	l := rr.Hdr.len()
+func (rr *KX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Exchanger) + 1
+	l += domainNameLen(rr.Exchanger, off+l, compression, false)
 	return l
 }
-func (rr *L32) len() int {
-	l := rr.Hdr.len()
-	l += 2           // Preference
-	l += net.IPv4len // Locator32
+func (rr *L32) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 2 // Preference
+	if len(rr.Locator32) != 0 {
+		l += net.IPv4len
+	}
 	return l
 }
-func (rr *L64) len() int {
-	l := rr.Hdr.len()
+func (rr *L64) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 8 // Locator64
 	return l
 }
-func (rr *LOC) len() int {
-	l := rr.Hdr.len()
+func (rr *LOC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // Version
 	l++    // Size
 	l++    // HorizPre
@@ -383,89 +401,89 @@ func (rr *LOC) len() int {
 	l += 4 // Altitude
 	return l
 }
-func (rr *LP) len() int {
-	l := rr.Hdr.len()
+func (rr *LP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Fqdn) + 1
+	l += domainNameLen(rr.Fqdn, off+l, compression, false)
 	return l
 }
-func (rr *MB) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mb) + 1
+func (rr *MB) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mb, off+l, compression, true)
 	return l
 }
-func (rr *MD) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Md) + 1
+func (rr *MD) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Md, off+l, compression, true)
 	return l
 }
-func (rr *MF) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mf) + 1
+func (rr *MF) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mf, off+l, compression, true)
 	return l
 }
-func (rr *MG) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mg) + 1
+func (rr *MG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mg, off+l, compression, true)
 	return l
 }
-func (rr *MINFO) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Rmail) + 1
-	l += len(rr.Email) + 1
+func (rr *MINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Rmail, off+l, compression, true)
+	l += domainNameLen(rr.Email, off+l, compression, true)
 	return l
 }
-func (rr *MR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mr) + 1
+func (rr *MR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mr, off+l, compression, true)
 	return l
 }
-func (rr *MX) len() int {
-	l := rr.Hdr.len()
+func (rr *MX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Mx) + 1
+	l += domainNameLen(rr.Mx, off+l, compression, true)
 	return l
 }
-func (rr *NAPTR) len() int {
-	l := rr.Hdr.len()
+func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Order
 	l += 2 // Preference
 	l += len(rr.Flags) + 1
 	l += len(rr.Service) + 1
 	l += len(rr.Regexp) + 1
-	l += len(rr.Replacement) + 1
+	l += domainNameLen(rr.Replacement, off+l, compression, false)
 	return l
 }
-func (rr *NID) len() int {
-	l := rr.Hdr.len()
+func (rr *NID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 8 // NodeID
 	return l
 }
-func (rr *NIMLOC) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Locator)/2 + 1
+func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Locator) / 2
 	return l
 }
-func (rr *NINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *NINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.ZSData {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *NS) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ns) + 1
+func (rr *NS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ns, off+l, compression, true)
 	return l
 }
-func (rr *NSAPPTR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ptr) + 1
+func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ptr, off+l, compression, false)
 	return l
 }
-func (rr *NSEC3PARAM) len() int {
-	l := rr.Hdr.len()
+func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // Hash
 	l++    // Flags
 	l += 2 // Iterations
@@ -473,44 +491,49 @@ func (rr *NSEC3PARAM) len() int {
 	l += len(rr.Salt) / 2
 	return l
 }
-func (rr *OPENPGPKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *NULL) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Data)
+	return l
+}
+func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *PTR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ptr) + 1
+func (rr *PTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ptr, off+l, compression, true)
 	return l
 }
-func (rr *PX) len() int {
-	l := rr.Hdr.len()
+func (rr *PX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Map822) + 1
-	l += len(rr.Mapx400) + 1
+	l += domainNameLen(rr.Map822, off+l, compression, false)
+	l += domainNameLen(rr.Mapx400, off+l, compression, false)
 	return l
 }
-func (rr *RFC3597) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Rdata)/2 + 1
+func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Rdata) / 2
 	return l
 }
-func (rr *RKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *RKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l++    // Protocol
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *RP) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mbox) + 1
-	l += len(rr.Txt) + 1
+func (rr *RP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mbox, off+l, compression, false)
+	l += domainNameLen(rr.Txt, off+l, compression, false)
 	return l
 }
-func (rr *RRSIG) len() int {
-	l := rr.Hdr.len()
+func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // TypeCovered
 	l++    // Algorithm
 	l++    // Labels
@@ -518,28 +541,28 @@ func (rr *RRSIG) len() int {
 	l += 4 // Expiration
 	l += 4 // Inception
 	l += 2 // KeyTag
-	l += len(rr.SignerName) + 1
+	l += domainNameLen(rr.SignerName, off+l, compression, false)
 	l += base64.StdEncoding.DecodedLen(len(rr.Signature))
 	return l
 }
-func (rr *RT) len() int {
-	l := rr.Hdr.len()
+func (rr *RT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Host) + 1
+	l += domainNameLen(rr.Host, off+l, compression, false)
 	return l
 }
-func (rr *SMIMEA) len() int {
-	l := rr.Hdr.len()
+func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
-func (rr *SOA) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ns) + 1
-	l += len(rr.Mbox) + 1
+func (rr *SOA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ns, off+l, compression, true)
+	l += domainNameLen(rr.Mbox, off+l, compression, true)
 	l += 4 // Serial
 	l += 4 // Refresh
 	l += 4 // Retry
@@ -547,45 +570,45 @@ func (rr *SOA) len() int {
 	l += 4 // Minttl
 	return l
 }
-func (rr *SPF) len() int {
-	l := rr.Hdr.len()
+func (rr *SPF) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *SRV) len() int {
-	l := rr.Hdr.len()
+func (rr *SRV) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Weight
 	l += 2 // Port
-	l += len(rr.Target) + 1
+	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 }
-func (rr *SSHFP) len() int {
-	l := rr.Hdr.len()
+func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Algorithm
 	l++ // Type
-	l += len(rr.FingerPrint)/2 + 1
+	l += len(rr.FingerPrint) / 2
 	return l
 }
-func (rr *TA) len() int {
-	l := rr.Hdr.len()
+func (rr *TA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
-func (rr *TALINK) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.PreviousName) + 1
-	l += len(rr.NextName) + 1
+func (rr *TALINK) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.PreviousName, off+l, compression, false)
+	l += domainNameLen(rr.NextName, off+l, compression, false)
 	return l
 }
-func (rr *TKEY) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Algorithm) + 1
+func (rr *TKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += 4 // Inception
 	l += 4 // Expiration
 	l += 2 // Mode
@@ -596,17 +619,17 @@ func (rr *TKEY) len() int {
 	l += len(rr.OtherData) / 2
 	return l
 }
-func (rr *TLSA) len() int {
-	l := rr.Hdr.len()
+func (rr *TLSA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
-func (rr *TSIG) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Algorithm) + 1
+func (rr *TSIG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += 6 // TimeSigned
 	l += 2 // Fudge
 	l += 2 // MACSize
@@ -617,32 +640,32 @@ func (rr *TSIG) len() int {
 	l += len(rr.OtherData) / 2
 	return l
 }
-func (rr *TXT) len() int {
-	l := rr.Hdr.len()
+func (rr *TXT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *UID) len() int {
-	l := rr.Hdr.len()
+func (rr *UID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 4 // Uid
 	return l
 }
-func (rr *UINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *UINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Uinfo) + 1
 	return l
 }
-func (rr *URI) len() int {
-	l := rr.Hdr.len()
+func (rr *URI) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Weight
 	l += len(rr.Target)
 	return l
 }
-func (rr *X25) len() int {
-	l := rr.Hdr.len()
+func (rr *X25) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.PSDNAddress) + 1
 	return l
 }
@@ -660,6 +683,13 @@ func (rr *AFSDB) copy() RR {
 func (rr *ANY) copy() RR {
 	return &ANY{rr.Hdr}
 }
+func (rr *APL) copy() RR {
+	Prefixes := make([]APLPrefix, len(rr.Prefixes))
+	for i := range rr.Prefixes {
+		Prefixes[i] = rr.Prefixes[i].copy()
+	}
+	return &APL{rr.Hdr, Prefixes}
+}
 func (rr *AVC) copy() RR {
 	Txt := make([]string, len(rr.Txt))
 	copy(Txt, rr.Txt)
@@ -783,12 +813,17 @@ func (rr *NSEC3) copy() RR {
 func (rr *NSEC3PARAM) copy() RR {
 	return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
 }
+func (rr *NULL) copy() RR {
+	return &NULL{rr.Hdr, rr.Data}
+}
 func (rr *OPENPGPKEY) copy() RR {
 	return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
 }
 func (rr *OPT) copy() RR {
 	Option := make([]EDNS0, len(rr.Option))
-	copy(Option, rr.Option)
+	for i, e := range rr.Option {
+		Option[i] = e.copy()
+	}
 	return &OPT{rr.Hdr, Option}
 }
 func (rr *PTR) copy() RR {

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません