mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge pull request #2511 from SamWhited/bump_dns
Bump the DNS library and revendor
This commit is contained in:
		
						commit
						429f9b64fa
					
				
					 58 changed files with 6069 additions and 6654 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								libnetwork/vendor/github.com/miekg/dns/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								libnetwork/vendor/github.com/miekg/dns/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										69
									
								
								libnetwork/vendor/github.com/miekg/dns/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								libnetwork/vendor/github.com/miekg/dns/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/acceptfunc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libnetwork/vendor/github.com/miekg/dns/acceptfunc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										301
									
								
								libnetwork/vendor/github.com/miekg/dns/client.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										301
									
								
								libnetwork/vendor/github.com/miekg/dns/client.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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 = *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
 | 
			
		||||
		}
 | 
			
		||||
	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 {
 | 
			
		||||
 | 
			
		||||
	if _, ok := co.Conn.(net.PacketConn); ok {
 | 
			
		||||
		// UDP connection
 | 
			
		||||
		return co.Conn.Read(p)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var length uint16
 | 
			
		||||
	if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if int(length) > len(p) {
 | 
			
		||||
		return 0, io.ErrShortBuffer
 | 
			
		||||
	}
 | 
			
		||||
	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])
 | 
			
		||||
	}
 | 
			
		||||
	// UDP connection
 | 
			
		||||
	n, err = co.Conn.Read(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return n, err
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
func (co *Conn) Write(p []byte) (int, error) {
 | 
			
		||||
	if len(p) > MaxMsgSize {
 | 
			
		||||
		return 0, &Error{err: "message too large"}
 | 
			
		||||
	}
 | 
			
		||||
	n, err = co.Conn.Write(p)
 | 
			
		||||
	return n, err
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/clientconfig.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/clientconfig.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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:])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										122
									
								
								libnetwork/vendor/github.com/miekg/dns/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										122
									
								
								libnetwork/vendor/github.com/miekg/dns/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										61
									
								
								libnetwork/vendor/github.com/miekg/dns/dns.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								libnetwork/vendor/github.com/miekg/dns/dns.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										109
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
	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")
 | 
			
		||||
	if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
 | 
			
		||||
		// Exponent larger than supported by the crypto package,
 | 
			
		||||
		// empty, or contains prohibited leading zero.
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	pubkey.E = int(expo)
 | 
			
		||||
 | 
			
		||||
	pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
	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 = 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										46
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_keygen.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_keygen.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										241
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_keyscan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										241
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_keyscan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_privkey.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								libnetwork/vendor/github.com/miekg/dns/dnssec_privkey.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										106
									
								
								libnetwork/vendor/github.com/miekg/dns/doc.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										106
									
								
								libnetwork/vendor/github.com/miekg/dns/doc.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/duplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								libnetwork/vendor/github.com/miekg/dns/duplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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) }
 | 
			
		||||
							
								
								
									
										132
									
								
								libnetwork/vendor/github.com/miekg/dns/edns.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										132
									
								
								libnetwork/vendor/github.com/miekg/dns/edns.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/format.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/format.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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()),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								libnetwork/vendor/github.com/miekg/dns/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								libnetwork/vendor/github.com/miekg/dns/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										316
									
								
								libnetwork/vendor/github.com/miekg/dns/generate.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										316
									
								
								libnetwork/vendor/github.com/miekg/dns/generate.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
		return "bad range in $GENERATE range"
 | 
			
		||||
	if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
 | 
			
		||||
		return zp.setParseError("bad range in $GENERATE range", l)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// _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 {
 | 
			
		||||
		s += l.token
 | 
			
		||||
		goto BuildRR
 | 
			
		||||
	}
 | 
			
		||||
	for i := start; i <= end; i += step {
 | 
			
		||||
		var (
 | 
			
		||||
			escape bool
 | 
			
		||||
			dom    bytes.Buffer
 | 
			
		||||
			mod    string
 | 
			
		||||
			err    error
 | 
			
		||||
			offset int
 | 
			
		||||
		)
 | 
			
		||||
	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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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])
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// 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()
 | 
			
		||||
		}
 | 
			
		||||
		t <- &Token{RR: rx}
 | 
			
		||||
		// Its more efficient to first built the rrlist and then parse it in
 | 
			
		||||
		// one go! But is this a problem?
 | 
			
		||||
		s += l.token
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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")
 | 
			
		||||
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"
 | 
			
		||||
	}
 | 
			
		||||
	// 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")
 | 
			
		||||
 | 
			
		||||
	switch base {
 | 
			
		||||
	case "o", "d", "x", "X":
 | 
			
		||||
	default:
 | 
			
		||||
		return "", 0, "bad base in $GENERATE"
 | 
			
		||||
	}
 | 
			
		||||
	offset, err := strconv.Atoi(xs[0])
 | 
			
		||||
	if err != nil || offset > 255 {
 | 
			
		||||
		return "", 0, errors.New("bad offset in $GENERATE")
 | 
			
		||||
 | 
			
		||||
	offset, err := strconv.Atoi(offStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", 0, "bad offset in $GENERATE"
 | 
			
		||||
	}
 | 
			
		||||
	width, err := strconv.Atoi(xs[1])
 | 
			
		||||
	if err != nil || width > 255 {
 | 
			
		||||
		return "", offset, errors.New("bad width in $GENERATE")
 | 
			
		||||
 | 
			
		||||
	width, err := strconv.Atoi(widthStr)
 | 
			
		||||
	if err != nil || width < 0 || width > 255 {
 | 
			
		||||
		return "", 0, "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
 | 
			
		||||
 | 
			
		||||
	if width == 0 {
 | 
			
		||||
		return "%" + base, offset, ""
 | 
			
		||||
	}
 | 
			
		||||
	return "%0" + xs[1] + xs[2], offset, nil
 | 
			
		||||
 | 
			
		||||
	return "%0" + widthStr + base, offset, ""
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								libnetwork/vendor/github.com/miekg/dns/go.mod
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libnetwork/vendor/github.com/miekg/dns/go.mod
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										73
									
								
								libnetwork/vendor/github.com/miekg/dns/labels.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								libnetwork/vendor/github.com/miekg/dns/labels.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/listen_go111.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								libnetwork/vendor/github.com/miekg/dns/listen_go111.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/listen_go_not111.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libnetwork/vendor/github.com/miekg/dns/listen_go_not111.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										824
									
								
								libnetwork/vendor/github.com/miekg/dns/msg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										824
									
								
								libnetwork/vendor/github.com/miekg/dns/msg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										277
									
								
								libnetwork/vendor/github.com/miekg/dns/msg_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										277
									
								
								libnetwork/vendor/github.com/miekg/dns/msg_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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 j := 0; j < len(names); j++ {
 | 
			
		||||
		off, err = PackDomainName(names[j], msg, off, compression, false && compress)
 | 
			
		||||
	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 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
									
								
								libnetwork/vendor/github.com/miekg/dns/msg_truncate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								libnetwork/vendor/github.com/miekg/dns/msg_truncate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								libnetwork/vendor/github.com/miekg/dns/nsecx.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								libnetwork/vendor/github.com/miekg/dns/nsecx.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										130
									
								
								libnetwork/vendor/github.com/miekg/dns/privaterr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								libnetwork/vendor/github.com/miekg/dns/privaterr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
 | 
			
		||||
	off1, err := r.Data.Unpack(msg[off:])
 | 
			
		||||
	off += off1
 | 
			
		||||
	return off, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := r.Data.Parse(text)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &ParseError{"", err.Error(), l}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
 | 
			
		||||
 | 
			
		||||
// 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()} }
 | 
			
		||||
	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
 | 
			
		||||
	TypeToString[rtype] = rtypestr
 | 
			
		||||
	StringToType[rtypestr] = rtype
 | 
			
		||||
 | 
			
		||||
	typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
 | 
			
		||||
		if noRdata(h) {
 | 
			
		||||
			return &h, off, nil
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
 | 
			
		||||
		rr := mkPrivateRR(h.Rrtype)
 | 
			
		||||
		rr.Hdr = h
 | 
			
		||||
 | 
			
		||||
		off1, err := rr.Data.Unpack(msg[off:])
 | 
			
		||||
		off += off1
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return rr, off, err
 | 
			
		||||
		}
 | 
			
		||||
		return rr, off, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
 | 
			
		||||
		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)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err := rr.Data.Parse(text)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, &ParseError{f, err.Error(), l}, ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return rr, nil, ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										49
									
								
								libnetwork/vendor/github.com/miekg/dns/rawmsg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										49
									
								
								libnetwork/vendor/github.com/miekg/dns/rawmsg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/reverse.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								libnetwork/vendor/github.com/miekg/dns/reverse.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/sanitize.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								libnetwork/vendor/github.com/miekg/dns/sanitize.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1131
									
								
								libnetwork/vendor/github.com/miekg/dns/scan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1131
									
								
								libnetwork/vendor/github.com/miekg/dns/scan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1791
									
								
								libnetwork/vendor/github.com/miekg/dns/scan_rr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1791
									
								
								libnetwork/vendor/github.com/miekg/dns/scan_rr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										56
									
								
								libnetwork/vendor/github.com/miekg/dns/scanner.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								libnetwork/vendor/github.com/miekg/dns/scanner.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/serve_mux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								libnetwork/vendor/github.com/miekg/dns/serve_mux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										660
									
								
								libnetwork/vendor/github.com/miekg/dns/server.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										660
									
								
								libnetwork/vendor/github.com/miekg/dns/server.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer atomic.AddInt32(&srv.workersCount, -1)
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
		}
 | 
			
		||||
func makeUDPBuffer(size int) func() interface{} {
 | 
			
		||||
	return func() interface{} {
 | 
			
		||||
		return make([]byte, size)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (srv *Server) spawnWorker(w *response) {
 | 
			
		||||
	select {
 | 
			
		||||
	case srv.queue <- w:
 | 
			
		||||
	default:
 | 
			
		||||
		go srv.worker(w)
 | 
			
		||||
func (srv *Server) init() {
 | 
			
		||||
	srv.shutdown = make(chan struct{})
 | 
			
		||||
	srv.conns = make(map[net.Conn]struct{})
 | 
			
		||||
 | 
			
		||||
	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 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)
 | 
			
		||||
		l, err := listenUDP(srv.Net, addr, srv.ReusePort)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		l, err := net.ListenUDP(srv.Net, a)
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
	if srv.PacketConn != nil {
 | 
			
		||||
		srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if srv.Listener != nil {
 | 
			
		||||
		srv.Listener.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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()
 | 
			
		||||
	}
 | 
			
		||||
	if srv.Listener != nil {
 | 
			
		||||
		srv.Listener.Close()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
	// 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))
 | 
			
		||||
	}
 | 
			
		||||
	length := binary.BigEndian.Uint16(l)
 | 
			
		||||
	if length == 0 {
 | 
			
		||||
		return nil, ErrShortRead
 | 
			
		||||
	srv.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	var length uint16
 | 
			
		||||
	if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	m := make([]byte, length)
 | 
			
		||||
	if _, err := io.ReadFull(conn, m); 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
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								libnetwork/vendor/github.com/miekg/dns/sig0.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								libnetwork/vendor/github.com/miekg/dns/sig0.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								libnetwork/vendor/github.com/miekg/dns/singleinflight.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								libnetwork/vendor/github.com/miekg/dns/singleinflight.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								libnetwork/vendor/github.com/miekg/dns/smimea.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								libnetwork/vendor/github.com/miekg/dns/smimea.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								libnetwork/vendor/github.com/miekg/dns/tlsa.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								libnetwork/vendor/github.com/miekg/dns/tlsa.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								libnetwork/vendor/github.com/miekg/dns/tsig.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								libnetwork/vendor/github.com/miekg/dns/tsig.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										418
									
								
								libnetwork/vendor/github.com/miekg/dns/types.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										418
									
								
								libnetwork/vendor/github.com/miekg/dns/types.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
	return string(dst)
 | 
			
		||||
	if dst.Len() == 0 {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
	return out.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appendDomainNameByte(s []byte, b byte) []byte {
 | 
			
		||||
	switch b {
 | 
			
		||||
	case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
 | 
			
		||||
		return append(s, '\\', b)
 | 
			
		||||
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)
 | 
			
		||||
const (
 | 
			
		||||
	escapedByteSmall = "" +
 | 
			
		||||
		`\000\001\002\003\004\005\006\007\008\009` +
 | 
			
		||||
		`\010\011\012\013\014\015\016\017\018\019` +
 | 
			
		||||
		`\020\021\022\023\024\025\026\027\028\029` +
 | 
			
		||||
		`\030\031`
 | 
			
		||||
	escapedByteLarge = `\127\128\129` +
 | 
			
		||||
		`\130\131\132\133\134\135\136\137\138\139` +
 | 
			
		||||
		`\140\141\142\143\144\145\146\147\148\149` +
 | 
			
		||||
		`\150\151\152\153\154\155\156\157\158\159` +
 | 
			
		||||
		`\160\161\162\163\164\165\166\167\168\169` +
 | 
			
		||||
		`\170\171\172\173\174\175\176\177\178\179` +
 | 
			
		||||
		`\180\181\182\183\184\185\186\187\188\189` +
 | 
			
		||||
		`\190\191\192\193\194\195\196\197\198\199` +
 | 
			
		||||
		`\200\201\202\203\204\205\206\207\208\209` +
 | 
			
		||||
		`\210\211\212\213\214\215\216\217\218\219` +
 | 
			
		||||
		`\220\221\222\223\224\225\226\227\228\229` +
 | 
			
		||||
		`\230\231\232\233\234\235\236\237\238\239` +
 | 
			
		||||
		`\240\241\242\243\244\245\246\247\248\249` +
 | 
			
		||||
		`\250\251\252\253\254\255`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// escapeByte returns the \DDD escaping of b which must
 | 
			
		||||
// satisfy b < ' ' || b > '~'.
 | 
			
		||||
func escapeByte(b byte) string {
 | 
			
		||||
	if b < ' ' {
 | 
			
		||||
		return escapedByteSmall[b*4 : b*4+4]
 | 
			
		||||
	}
 | 
			
		||||
	if b < ' ' || b > '~' {
 | 
			
		||||
		return appendByte(s, b)
 | 
			
		||||
	}
 | 
			
		||||
	return append(s, b)
 | 
			
		||||
 | 
			
		||||
	b -= '~' + 1
 | 
			
		||||
	// The cast here is needed as b*4 may overflow byte.
 | 
			
		||||
	return escapedByteLarge[int(b)*4 : int(b)*4+4]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
		}
 | 
			
		||||
		lastwindow = uint32(window)
 | 
			
		||||
	}
 | 
			
		||||
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(' ')
 | 
			
		||||
		}
 | 
			
		||||
		sb.WriteString(p.str())
 | 
			
		||||
	}
 | 
			
		||||
	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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								libnetwork/vendor/github.com/miekg/dns/udp_windows.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								libnetwork/vendor/github.com/miekg/dns/udp_windows.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								libnetwork/vendor/github.com/miekg/dns/update.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								libnetwork/vendor/github.com/miekg/dns/update.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								libnetwork/vendor/github.com/miekg/dns/version.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								libnetwork/vendor/github.com/miekg/dns/version.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								libnetwork/vendor/github.com/miekg/dns/xfr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								libnetwork/vendor/github.com/miekg/dns/xfr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										155
									
								
								libnetwork/vendor/github.com/miekg/dns/zcompress.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										155
									
								
								libnetwork/vendor/github.com/miekg/dns/zcompress.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
									
								
								libnetwork/vendor/github.com/miekg/dns/zduplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1157
									
								
								libnetwork/vendor/github.com/miekg/dns/zduplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2050
									
								
								libnetwork/vendor/github.com/miekg/dns/zmsg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2050
									
								
								libnetwork/vendor/github.com/miekg/dns/zmsg.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										367
									
								
								libnetwork/vendor/github.com/miekg/dns/ztypes.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										367
									
								
								libnetwork/vendor/github.com/miekg/dns/ztypes.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										955
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										955
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,955 +0,0 @@
 | 
			
		|||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EscapeCodes contains escape sequences that can be written to the terminal in
 | 
			
		||||
// order to achieve different styles of text.
 | 
			
		||||
type EscapeCodes struct {
 | 
			
		||||
	// Foreground colors
 | 
			
		||||
	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
 | 
			
		||||
 | 
			
		||||
	// Reset all attributes
 | 
			
		||||
	Reset []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var vt100EscapeCodes = EscapeCodes{
 | 
			
		||||
	Black:   []byte{keyEscape, '[', '3', '0', 'm'},
 | 
			
		||||
	Red:     []byte{keyEscape, '[', '3', '1', 'm'},
 | 
			
		||||
	Green:   []byte{keyEscape, '[', '3', '2', 'm'},
 | 
			
		||||
	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'},
 | 
			
		||||
	Blue:    []byte{keyEscape, '[', '3', '4', 'm'},
 | 
			
		||||
	Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
 | 
			
		||||
	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'},
 | 
			
		||||
	White:   []byte{keyEscape, '[', '3', '7', 'm'},
 | 
			
		||||
 | 
			
		||||
	Reset: []byte{keyEscape, '[', '0', 'm'},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Terminal contains the state for running a VT100 terminal that is capable of
 | 
			
		||||
// reading lines of input.
 | 
			
		||||
type Terminal struct {
 | 
			
		||||
	// AutoCompleteCallback, if non-null, is called for each keypress with
 | 
			
		||||
	// the full input line and the current position of the cursor (in
 | 
			
		||||
	// bytes, as an index into |line|). If it returns ok=false, the key
 | 
			
		||||
	// press is processed normally. Otherwise it returns a replacement line
 | 
			
		||||
	// and the new cursor position.
 | 
			
		||||
	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
 | 
			
		||||
 | 
			
		||||
	// Escape contains a pointer to the escape codes for this terminal.
 | 
			
		||||
	// It's always a valid pointer, although the escape codes themselves
 | 
			
		||||
	// may be empty if the terminal doesn't support them.
 | 
			
		||||
	Escape *EscapeCodes
 | 
			
		||||
 | 
			
		||||
	// lock protects the terminal and the state in this object from
 | 
			
		||||
	// concurrent processing of a key press and a Write() call.
 | 
			
		||||
	lock sync.Mutex
 | 
			
		||||
 | 
			
		||||
	c      io.ReadWriter
 | 
			
		||||
	prompt []rune
 | 
			
		||||
 | 
			
		||||
	// line is the current line being entered.
 | 
			
		||||
	line []rune
 | 
			
		||||
	// pos is the logical position of the cursor in line
 | 
			
		||||
	pos int
 | 
			
		||||
	// echo is true if local echo is enabled
 | 
			
		||||
	echo bool
 | 
			
		||||
	// pasteActive is true iff there is a bracketed paste operation in
 | 
			
		||||
	// progress.
 | 
			
		||||
	pasteActive bool
 | 
			
		||||
 | 
			
		||||
	// cursorX contains the current X value of the cursor where the left
 | 
			
		||||
	// edge is 0. cursorY contains the row number where the first row of
 | 
			
		||||
	// the current line is 0.
 | 
			
		||||
	cursorX, cursorY int
 | 
			
		||||
	// maxLine is the greatest value of cursorY so far.
 | 
			
		||||
	maxLine int
 | 
			
		||||
 | 
			
		||||
	termWidth, termHeight int
 | 
			
		||||
 | 
			
		||||
	// outBuf contains the terminal data to be sent.
 | 
			
		||||
	outBuf []byte
 | 
			
		||||
	// remainder contains the remainder of any partial key sequences after
 | 
			
		||||
	// a read. It aliases into inBuf.
 | 
			
		||||
	remainder []byte
 | 
			
		||||
	inBuf     [256]byte
 | 
			
		||||
 | 
			
		||||
	// history contains previously entered commands so that they can be
 | 
			
		||||
	// accessed with the up and down keys.
 | 
			
		||||
	history stRingBuffer
 | 
			
		||||
	// historyIndex stores the currently accessed history entry, where zero
 | 
			
		||||
	// means the immediately previous entry.
 | 
			
		||||
	historyIndex int
 | 
			
		||||
	// When navigating up and down the history it's possible to return to
 | 
			
		||||
	// the incomplete, initial line. That value is stored in
 | 
			
		||||
	// historyPending.
 | 
			
		||||
	historyPending string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
 | 
			
		||||
// a local terminal, that terminal must first have been put into raw mode.
 | 
			
		||||
// prompt is a string that is written at the start of each input line (i.e.
 | 
			
		||||
// "> ").
 | 
			
		||||
func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
 | 
			
		||||
	return &Terminal{
 | 
			
		||||
		Escape:       &vt100EscapeCodes,
 | 
			
		||||
		c:            c,
 | 
			
		||||
		prompt:       []rune(prompt),
 | 
			
		||||
		termWidth:    80,
 | 
			
		||||
		termHeight:   24,
 | 
			
		||||
		echo:         true,
 | 
			
		||||
		historyIndex: -1,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	keyCtrlD     = 4
 | 
			
		||||
	keyCtrlU     = 21
 | 
			
		||||
	keyEnter     = '\r'
 | 
			
		||||
	keyEscape    = 27
 | 
			
		||||
	keyBackspace = 127
 | 
			
		||||
	keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota
 | 
			
		||||
	keyUp
 | 
			
		||||
	keyDown
 | 
			
		||||
	keyLeft
 | 
			
		||||
	keyRight
 | 
			
		||||
	keyAltLeft
 | 
			
		||||
	keyAltRight
 | 
			
		||||
	keyHome
 | 
			
		||||
	keyEnd
 | 
			
		||||
	keyDeleteWord
 | 
			
		||||
	keyDeleteLine
 | 
			
		||||
	keyClearScreen
 | 
			
		||||
	keyPasteStart
 | 
			
		||||
	keyPasteEnd
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	crlf       = []byte{'\r', '\n'}
 | 
			
		||||
	pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
 | 
			
		||||
	pasteEnd   = []byte{keyEscape, '[', '2', '0', '1', '~'}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// bytesToKey tries to parse a key sequence from b. If successful, it returns
 | 
			
		||||
// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
 | 
			
		||||
func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
 | 
			
		||||
	if len(b) == 0 {
 | 
			
		||||
		return utf8.RuneError, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !pasteActive {
 | 
			
		||||
		switch b[0] {
 | 
			
		||||
		case 1: // ^A
 | 
			
		||||
			return keyHome, b[1:]
 | 
			
		||||
		case 5: // ^E
 | 
			
		||||
			return keyEnd, b[1:]
 | 
			
		||||
		case 8: // ^H
 | 
			
		||||
			return keyBackspace, b[1:]
 | 
			
		||||
		case 11: // ^K
 | 
			
		||||
			return keyDeleteLine, b[1:]
 | 
			
		||||
		case 12: // ^L
 | 
			
		||||
			return keyClearScreen, b[1:]
 | 
			
		||||
		case 23: // ^W
 | 
			
		||||
			return keyDeleteWord, b[1:]
 | 
			
		||||
		case 14: // ^N
 | 
			
		||||
			return keyDown, b[1:]
 | 
			
		||||
		case 16: // ^P
 | 
			
		||||
			return keyUp, b[1:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b[0] != keyEscape {
 | 
			
		||||
		if !utf8.FullRune(b) {
 | 
			
		||||
			return utf8.RuneError, b
 | 
			
		||||
		}
 | 
			
		||||
		r, l := utf8.DecodeRune(b)
 | 
			
		||||
		return r, b[l:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
 | 
			
		||||
		switch b[2] {
 | 
			
		||||
		case 'A':
 | 
			
		||||
			return keyUp, b[3:]
 | 
			
		||||
		case 'B':
 | 
			
		||||
			return keyDown, b[3:]
 | 
			
		||||
		case 'C':
 | 
			
		||||
			return keyRight, b[3:]
 | 
			
		||||
		case 'D':
 | 
			
		||||
			return keyLeft, b[3:]
 | 
			
		||||
		case 'H':
 | 
			
		||||
			return keyHome, b[3:]
 | 
			
		||||
		case 'F':
 | 
			
		||||
			return keyEnd, b[3:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
 | 
			
		||||
		switch b[5] {
 | 
			
		||||
		case 'C':
 | 
			
		||||
			return keyAltRight, b[6:]
 | 
			
		||||
		case 'D':
 | 
			
		||||
			return keyAltLeft, b[6:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
 | 
			
		||||
		return keyPasteStart, b[6:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
 | 
			
		||||
		return keyPasteEnd, b[6:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we get here then we have a key that we don't recognise, or a
 | 
			
		||||
	// partial sequence. It's not clear how one should find the end of a
 | 
			
		||||
	// sequence without knowing them all, but it seems that [a-zA-Z~] only
 | 
			
		||||
	// appears at the end of a sequence.
 | 
			
		||||
	for i, c := range b[0:] {
 | 
			
		||||
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
 | 
			
		||||
			return keyUnknown, b[i+1:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return utf8.RuneError, b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// queue appends data to the end of t.outBuf
 | 
			
		||||
func (t *Terminal) queue(data []rune) {
 | 
			
		||||
	t.outBuf = append(t.outBuf, []byte(string(data))...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
 | 
			
		||||
var space = []rune{' '}
 | 
			
		||||
 | 
			
		||||
func isPrintable(key rune) bool {
 | 
			
		||||
	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
 | 
			
		||||
	return key >= 32 && !isInSurrogateArea
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// moveCursorToPos appends data to t.outBuf which will move the cursor to the
 | 
			
		||||
// given, logical position in the text.
 | 
			
		||||
func (t *Terminal) moveCursorToPos(pos int) {
 | 
			
		||||
	if !t.echo {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x := visualLength(t.prompt) + pos
 | 
			
		||||
	y := x / t.termWidth
 | 
			
		||||
	x = x % t.termWidth
 | 
			
		||||
 | 
			
		||||
	up := 0
 | 
			
		||||
	if y < t.cursorY {
 | 
			
		||||
		up = t.cursorY - y
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	down := 0
 | 
			
		||||
	if y > t.cursorY {
 | 
			
		||||
		down = y - t.cursorY
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	left := 0
 | 
			
		||||
	if x < t.cursorX {
 | 
			
		||||
		left = t.cursorX - x
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	right := 0
 | 
			
		||||
	if x > t.cursorX {
 | 
			
		||||
		right = x - t.cursorX
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.cursorX = x
 | 
			
		||||
	t.cursorY = y
 | 
			
		||||
	t.move(up, down, left, right)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) move(up, down, left, right int) {
 | 
			
		||||
	movement := make([]rune, 3*(up+down+left+right))
 | 
			
		||||
	m := movement
 | 
			
		||||
	for i := 0; i < up; i++ {
 | 
			
		||||
		m[0] = keyEscape
 | 
			
		||||
		m[1] = '['
 | 
			
		||||
		m[2] = 'A'
 | 
			
		||||
		m = m[3:]
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < down; i++ {
 | 
			
		||||
		m[0] = keyEscape
 | 
			
		||||
		m[1] = '['
 | 
			
		||||
		m[2] = 'B'
 | 
			
		||||
		m = m[3:]
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < left; i++ {
 | 
			
		||||
		m[0] = keyEscape
 | 
			
		||||
		m[1] = '['
 | 
			
		||||
		m[2] = 'D'
 | 
			
		||||
		m = m[3:]
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < right; i++ {
 | 
			
		||||
		m[0] = keyEscape
 | 
			
		||||
		m[1] = '['
 | 
			
		||||
		m[2] = 'C'
 | 
			
		||||
		m = m[3:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.queue(movement)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) clearLineToRight() {
 | 
			
		||||
	op := []rune{keyEscape, '[', 'K'}
 | 
			
		||||
	t.queue(op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const maxLineLength = 4096
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) setLine(newLine []rune, newPos int) {
 | 
			
		||||
	if t.echo {
 | 
			
		||||
		t.moveCursorToPos(0)
 | 
			
		||||
		t.writeLine(newLine)
 | 
			
		||||
		for i := len(newLine); i < len(t.line); i++ {
 | 
			
		||||
			t.writeLine(space)
 | 
			
		||||
		}
 | 
			
		||||
		t.moveCursorToPos(newPos)
 | 
			
		||||
	}
 | 
			
		||||
	t.line = newLine
 | 
			
		||||
	t.pos = newPos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) advanceCursor(places int) {
 | 
			
		||||
	t.cursorX += places
 | 
			
		||||
	t.cursorY += t.cursorX / t.termWidth
 | 
			
		||||
	if t.cursorY > t.maxLine {
 | 
			
		||||
		t.maxLine = t.cursorY
 | 
			
		||||
	}
 | 
			
		||||
	t.cursorX = t.cursorX % t.termWidth
 | 
			
		||||
 | 
			
		||||
	if places > 0 && t.cursorX == 0 {
 | 
			
		||||
		// Normally terminals will advance the current position
 | 
			
		||||
		// when writing a character. But that doesn't happen
 | 
			
		||||
		// for the last character in a line. However, when
 | 
			
		||||
		// writing a character (except a new line) that causes
 | 
			
		||||
		// a line wrap, the position will be advanced two
 | 
			
		||||
		// places.
 | 
			
		||||
		//
 | 
			
		||||
		// So, if we are stopping at the end of a line, we
 | 
			
		||||
		// need to write a newline so that our cursor can be
 | 
			
		||||
		// advanced to the next line.
 | 
			
		||||
		t.outBuf = append(t.outBuf, '\r', '\n')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) eraseNPreviousChars(n int) {
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t.pos < n {
 | 
			
		||||
		n = t.pos
 | 
			
		||||
	}
 | 
			
		||||
	t.pos -= n
 | 
			
		||||
	t.moveCursorToPos(t.pos)
 | 
			
		||||
 | 
			
		||||
	copy(t.line[t.pos:], t.line[n+t.pos:])
 | 
			
		||||
	t.line = t.line[:len(t.line)-n]
 | 
			
		||||
	if t.echo {
 | 
			
		||||
		t.writeLine(t.line[t.pos:])
 | 
			
		||||
		for i := 0; i < n; i++ {
 | 
			
		||||
			t.queue(space)
 | 
			
		||||
		}
 | 
			
		||||
		t.advanceCursor(n)
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// countToLeftWord returns then number of characters from the cursor to the
 | 
			
		||||
// start of the previous word.
 | 
			
		||||
func (t *Terminal) countToLeftWord() int {
 | 
			
		||||
	if t.pos == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pos := t.pos - 1
 | 
			
		||||
	for pos > 0 {
 | 
			
		||||
		if t.line[pos] != ' ' {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		pos--
 | 
			
		||||
	}
 | 
			
		||||
	for pos > 0 {
 | 
			
		||||
		if t.line[pos] == ' ' {
 | 
			
		||||
			pos++
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		pos--
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return t.pos - pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// countToRightWord returns then number of characters from the cursor to the
 | 
			
		||||
// start of the next word.
 | 
			
		||||
func (t *Terminal) countToRightWord() int {
 | 
			
		||||
	pos := t.pos
 | 
			
		||||
	for pos < len(t.line) {
 | 
			
		||||
		if t.line[pos] == ' ' {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		pos++
 | 
			
		||||
	}
 | 
			
		||||
	for pos < len(t.line) {
 | 
			
		||||
		if t.line[pos] != ' ' {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		pos++
 | 
			
		||||
	}
 | 
			
		||||
	return pos - t.pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// visualLength returns the number of visible glyphs in s.
 | 
			
		||||
func visualLength(runes []rune) int {
 | 
			
		||||
	inEscapeSeq := false
 | 
			
		||||
	length := 0
 | 
			
		||||
 | 
			
		||||
	for _, r := range runes {
 | 
			
		||||
		switch {
 | 
			
		||||
		case inEscapeSeq:
 | 
			
		||||
			if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
 | 
			
		||||
				inEscapeSeq = false
 | 
			
		||||
			}
 | 
			
		||||
		case r == '\x1b':
 | 
			
		||||
			inEscapeSeq = true
 | 
			
		||||
		default:
 | 
			
		||||
			length++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return length
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleKey processes the given key and, optionally, returns a line of text
 | 
			
		||||
// that the user has entered.
 | 
			
		||||
func (t *Terminal) handleKey(key rune) (line string, ok bool) {
 | 
			
		||||
	if t.pasteActive && key != keyEnter {
 | 
			
		||||
		t.addKeyToLine(key)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch key {
 | 
			
		||||
	case keyBackspace:
 | 
			
		||||
		if t.pos == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.eraseNPreviousChars(1)
 | 
			
		||||
	case keyAltLeft:
 | 
			
		||||
		// move left by a word.
 | 
			
		||||
		t.pos -= t.countToLeftWord()
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyAltRight:
 | 
			
		||||
		// move right by a word.
 | 
			
		||||
		t.pos += t.countToRightWord()
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyLeft:
 | 
			
		||||
		if t.pos == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.pos--
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyRight:
 | 
			
		||||
		if t.pos == len(t.line) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.pos++
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyHome:
 | 
			
		||||
		if t.pos == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.pos = 0
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyEnd:
 | 
			
		||||
		if t.pos == len(t.line) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.pos = len(t.line)
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyUp:
 | 
			
		||||
		entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return "", false
 | 
			
		||||
		}
 | 
			
		||||
		if t.historyIndex == -1 {
 | 
			
		||||
			t.historyPending = string(t.line)
 | 
			
		||||
		}
 | 
			
		||||
		t.historyIndex++
 | 
			
		||||
		runes := []rune(entry)
 | 
			
		||||
		t.setLine(runes, len(runes))
 | 
			
		||||
	case keyDown:
 | 
			
		||||
		switch t.historyIndex {
 | 
			
		||||
		case -1:
 | 
			
		||||
			return
 | 
			
		||||
		case 0:
 | 
			
		||||
			runes := []rune(t.historyPending)
 | 
			
		||||
			t.setLine(runes, len(runes))
 | 
			
		||||
			t.historyIndex--
 | 
			
		||||
		default:
 | 
			
		||||
			entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
 | 
			
		||||
			if ok {
 | 
			
		||||
				t.historyIndex--
 | 
			
		||||
				runes := []rune(entry)
 | 
			
		||||
				t.setLine(runes, len(runes))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case keyEnter:
 | 
			
		||||
		t.moveCursorToPos(len(t.line))
 | 
			
		||||
		t.queue([]rune("\r\n"))
 | 
			
		||||
		line = string(t.line)
 | 
			
		||||
		ok = true
 | 
			
		||||
		t.line = t.line[:0]
 | 
			
		||||
		t.pos = 0
 | 
			
		||||
		t.cursorX = 0
 | 
			
		||||
		t.cursorY = 0
 | 
			
		||||
		t.maxLine = 0
 | 
			
		||||
	case keyDeleteWord:
 | 
			
		||||
		// Delete zero or more spaces and then one or more characters.
 | 
			
		||||
		t.eraseNPreviousChars(t.countToLeftWord())
 | 
			
		||||
	case keyDeleteLine:
 | 
			
		||||
		// Delete everything from the current cursor position to the
 | 
			
		||||
		// end of line.
 | 
			
		||||
		for i := t.pos; i < len(t.line); i++ {
 | 
			
		||||
			t.queue(space)
 | 
			
		||||
			t.advanceCursor(1)
 | 
			
		||||
		}
 | 
			
		||||
		t.line = t.line[:t.pos]
 | 
			
		||||
		t.moveCursorToPos(t.pos)
 | 
			
		||||
	case keyCtrlD:
 | 
			
		||||
		// Erase the character under the current position.
 | 
			
		||||
		// The EOF case when the line is empty is handled in
 | 
			
		||||
		// readLine().
 | 
			
		||||
		if t.pos < len(t.line) {
 | 
			
		||||
			t.pos++
 | 
			
		||||
			t.eraseNPreviousChars(1)
 | 
			
		||||
		}
 | 
			
		||||
	case keyCtrlU:
 | 
			
		||||
		t.eraseNPreviousChars(t.pos)
 | 
			
		||||
	case keyClearScreen:
 | 
			
		||||
		// Erases the screen and moves the cursor to the home position.
 | 
			
		||||
		t.queue([]rune("\x1b[2J\x1b[H"))
 | 
			
		||||
		t.queue(t.prompt)
 | 
			
		||||
		t.cursorX, t.cursorY = 0, 0
 | 
			
		||||
		t.advanceCursor(visualLength(t.prompt))
 | 
			
		||||
		t.setLine(t.line, t.pos)
 | 
			
		||||
	default:
 | 
			
		||||
		if t.AutoCompleteCallback != nil {
 | 
			
		||||
			prefix := string(t.line[:t.pos])
 | 
			
		||||
			suffix := string(t.line[t.pos:])
 | 
			
		||||
 | 
			
		||||
			t.lock.Unlock()
 | 
			
		||||
			newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
 | 
			
		||||
			t.lock.Lock()
 | 
			
		||||
 | 
			
		||||
			if completeOk {
 | 
			
		||||
				t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !isPrintable(key) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if len(t.line) == maxLineLength {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.addKeyToLine(key)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addKeyToLine inserts the given key at the current position in the current
 | 
			
		||||
// line.
 | 
			
		||||
func (t *Terminal) addKeyToLine(key rune) {
 | 
			
		||||
	if len(t.line) == cap(t.line) {
 | 
			
		||||
		newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
 | 
			
		||||
		copy(newLine, t.line)
 | 
			
		||||
		t.line = newLine
 | 
			
		||||
	}
 | 
			
		||||
	t.line = t.line[:len(t.line)+1]
 | 
			
		||||
	copy(t.line[t.pos+1:], t.line[t.pos:])
 | 
			
		||||
	t.line[t.pos] = key
 | 
			
		||||
	if t.echo {
 | 
			
		||||
		t.writeLine(t.line[t.pos:])
 | 
			
		||||
	}
 | 
			
		||||
	t.pos++
 | 
			
		||||
	t.moveCursorToPos(t.pos)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) writeLine(line []rune) {
 | 
			
		||||
	for len(line) != 0 {
 | 
			
		||||
		remainingOnLine := t.termWidth - t.cursorX
 | 
			
		||||
		todo := len(line)
 | 
			
		||||
		if todo > remainingOnLine {
 | 
			
		||||
			todo = remainingOnLine
 | 
			
		||||
		}
 | 
			
		||||
		t.queue(line[:todo])
 | 
			
		||||
		t.advanceCursor(visualLength(line[:todo]))
 | 
			
		||||
		line = line[todo:]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
 | 
			
		||||
func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
 | 
			
		||||
	for len(buf) > 0 {
 | 
			
		||||
		i := bytes.IndexByte(buf, '\n')
 | 
			
		||||
		todo := len(buf)
 | 
			
		||||
		if i >= 0 {
 | 
			
		||||
			todo = i
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var nn int
 | 
			
		||||
		nn, err = w.Write(buf[:todo])
 | 
			
		||||
		n += nn
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return n, err
 | 
			
		||||
		}
 | 
			
		||||
		buf = buf[todo:]
 | 
			
		||||
 | 
			
		||||
		if i >= 0 {
 | 
			
		||||
			if _, err = w.Write(crlf); err != nil {
 | 
			
		||||
				return n, err
 | 
			
		||||
			}
 | 
			
		||||
			n++
 | 
			
		||||
			buf = buf[1:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return n, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) Write(buf []byte) (n int, err error) {
 | 
			
		||||
	t.lock.Lock()
 | 
			
		||||
	defer t.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	if t.cursorX == 0 && t.cursorY == 0 {
 | 
			
		||||
		// This is the easy case: there's nothing on the screen that we
 | 
			
		||||
		// have to move out of the way.
 | 
			
		||||
		return writeWithCRLF(t.c, buf)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We have a prompt and possibly user input on the screen. We
 | 
			
		||||
	// have to clear it first.
 | 
			
		||||
	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
 | 
			
		||||
	t.cursorX = 0
 | 
			
		||||
	t.clearLineToRight()
 | 
			
		||||
 | 
			
		||||
	for t.cursorY > 0 {
 | 
			
		||||
		t.move(1 /* up */, 0, 0, 0)
 | 
			
		||||
		t.cursorY--
 | 
			
		||||
		t.clearLineToRight()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err = t.c.Write(t.outBuf); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t.outBuf = t.outBuf[:0]
 | 
			
		||||
 | 
			
		||||
	if n, err = writeWithCRLF(t.c, buf); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.writeLine(t.prompt)
 | 
			
		||||
	if t.echo {
 | 
			
		||||
		t.writeLine(t.line)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.moveCursorToPos(t.pos)
 | 
			
		||||
 | 
			
		||||
	if _, err = t.c.Write(t.outBuf); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t.outBuf = t.outBuf[:0]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPassword temporarily changes the prompt and reads a password, without
 | 
			
		||||
// echo, from the terminal.
 | 
			
		||||
func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
 | 
			
		||||
	t.lock.Lock()
 | 
			
		||||
	defer t.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	oldPrompt := t.prompt
 | 
			
		||||
	t.prompt = []rune(prompt)
 | 
			
		||||
	t.echo = false
 | 
			
		||||
 | 
			
		||||
	line, err = t.readLine()
 | 
			
		||||
 | 
			
		||||
	t.prompt = oldPrompt
 | 
			
		||||
	t.echo = true
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadLine returns a line of input from the terminal.
 | 
			
		||||
func (t *Terminal) ReadLine() (line string, err error) {
 | 
			
		||||
	t.lock.Lock()
 | 
			
		||||
	defer t.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	return t.readLine()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) readLine() (line string, err error) {
 | 
			
		||||
	// t.lock must be held at this point
 | 
			
		||||
 | 
			
		||||
	if t.cursorX == 0 && t.cursorY == 0 {
 | 
			
		||||
		t.writeLine(t.prompt)
 | 
			
		||||
		t.c.Write(t.outBuf)
 | 
			
		||||
		t.outBuf = t.outBuf[:0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lineIsPasted := t.pasteActive
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		rest := t.remainder
 | 
			
		||||
		lineOk := false
 | 
			
		||||
		for !lineOk {
 | 
			
		||||
			var key rune
 | 
			
		||||
			key, rest = bytesToKey(rest, t.pasteActive)
 | 
			
		||||
			if key == utf8.RuneError {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			if !t.pasteActive {
 | 
			
		||||
				if key == keyCtrlD {
 | 
			
		||||
					if len(t.line) == 0 {
 | 
			
		||||
						return "", io.EOF
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if key == keyPasteStart {
 | 
			
		||||
					t.pasteActive = true
 | 
			
		||||
					if len(t.line) == 0 {
 | 
			
		||||
						lineIsPasted = true
 | 
			
		||||
					}
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			} else if key == keyPasteEnd {
 | 
			
		||||
				t.pasteActive = false
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !t.pasteActive {
 | 
			
		||||
				lineIsPasted = false
 | 
			
		||||
			}
 | 
			
		||||
			line, lineOk = t.handleKey(key)
 | 
			
		||||
		}
 | 
			
		||||
		if len(rest) > 0 {
 | 
			
		||||
			n := copy(t.inBuf[:], rest)
 | 
			
		||||
			t.remainder = t.inBuf[:n]
 | 
			
		||||
		} else {
 | 
			
		||||
			t.remainder = nil
 | 
			
		||||
		}
 | 
			
		||||
		t.c.Write(t.outBuf)
 | 
			
		||||
		t.outBuf = t.outBuf[:0]
 | 
			
		||||
		if lineOk {
 | 
			
		||||
			if t.echo {
 | 
			
		||||
				t.historyIndex = -1
 | 
			
		||||
				t.history.Add(line)
 | 
			
		||||
			}
 | 
			
		||||
			if lineIsPasted {
 | 
			
		||||
				err = ErrPasteIndicator
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// t.remainder is a slice at the beginning of t.inBuf
 | 
			
		||||
		// containing a partial key sequence
 | 
			
		||||
		readBuf := t.inBuf[len(t.remainder):]
 | 
			
		||||
		var n int
 | 
			
		||||
 | 
			
		||||
		t.lock.Unlock()
 | 
			
		||||
		n, err = t.c.Read(readBuf)
 | 
			
		||||
		t.lock.Lock()
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t.remainder = t.inBuf[:n+len(t.remainder)]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetPrompt sets the prompt to be used when reading subsequent lines.
 | 
			
		||||
func (t *Terminal) SetPrompt(prompt string) {
 | 
			
		||||
	t.lock.Lock()
 | 
			
		||||
	defer t.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	t.prompt = []rune(prompt)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
 | 
			
		||||
	// Move cursor to column zero at the start of the line.
 | 
			
		||||
	t.move(t.cursorY, 0, t.cursorX, 0)
 | 
			
		||||
	t.cursorX, t.cursorY = 0, 0
 | 
			
		||||
	t.clearLineToRight()
 | 
			
		||||
	for t.cursorY < numPrevLines {
 | 
			
		||||
		// Move down a line
 | 
			
		||||
		t.move(0, 1, 0, 0)
 | 
			
		||||
		t.cursorY++
 | 
			
		||||
		t.clearLineToRight()
 | 
			
		||||
	}
 | 
			
		||||
	// Move back to beginning.
 | 
			
		||||
	t.move(t.cursorY, 0, 0, 0)
 | 
			
		||||
	t.cursorX, t.cursorY = 0, 0
 | 
			
		||||
 | 
			
		||||
	t.queue(t.prompt)
 | 
			
		||||
	t.advanceCursor(visualLength(t.prompt))
 | 
			
		||||
	t.writeLine(t.line)
 | 
			
		||||
	t.moveCursorToPos(t.pos)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Terminal) SetSize(width, height int) error {
 | 
			
		||||
	t.lock.Lock()
 | 
			
		||||
	defer t.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	if width == 0 {
 | 
			
		||||
		width = 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldWidth := t.termWidth
 | 
			
		||||
	t.termWidth, t.termHeight = width, height
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case width == oldWidth:
 | 
			
		||||
		// If the width didn't change then nothing else needs to be
 | 
			
		||||
		// done.
 | 
			
		||||
		return nil
 | 
			
		||||
	case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
 | 
			
		||||
		// If there is nothing on current line and no prompt printed,
 | 
			
		||||
		// just do nothing
 | 
			
		||||
		return nil
 | 
			
		||||
	case width < oldWidth:
 | 
			
		||||
		// Some terminals (e.g. xterm) will truncate lines that were
 | 
			
		||||
		// too long when shinking. Others, (e.g. gnome-terminal) will
 | 
			
		||||
		// attempt to wrap them. For the former, repainting t.maxLine
 | 
			
		||||
		// works great, but that behaviour goes badly wrong in the case
 | 
			
		||||
		// of the latter because they have doubled every full line.
 | 
			
		||||
 | 
			
		||||
		// We assume that we are working on a terminal that wraps lines
 | 
			
		||||
		// and adjust the cursor position based on every previous line
 | 
			
		||||
		// wrapping and turning into two. This causes the prompt on
 | 
			
		||||
		// xterms to move upwards, which isn't great, but it avoids a
 | 
			
		||||
		// huge mess with gnome-terminal.
 | 
			
		||||
		if t.cursorX >= t.termWidth {
 | 
			
		||||
			t.cursorX = t.termWidth - 1
 | 
			
		||||
		}
 | 
			
		||||
		t.cursorY *= 2
 | 
			
		||||
		t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
 | 
			
		||||
	case width > oldWidth:
 | 
			
		||||
		// If the terminal expands then our position calculations will
 | 
			
		||||
		// be wrong in the future because we think the cursor is
 | 
			
		||||
		// |t.pos| chars into the string, but there will be a gap at
 | 
			
		||||
		// the end of any wrapped line.
 | 
			
		||||
		//
 | 
			
		||||
		// But the position will actually be correct until we move, so
 | 
			
		||||
		// we can move back to the beginning and repaint everything.
 | 
			
		||||
		t.clearAndRepaintLinePlusNPrevious(t.maxLine)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := t.c.Write(t.outBuf)
 | 
			
		||||
	t.outBuf = t.outBuf[:0]
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pasteIndicatorError struct{}
 | 
			
		||||
 | 
			
		||||
func (pasteIndicatorError) Error() string {
 | 
			
		||||
	return "terminal: ErrPasteIndicator not correctly handled"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrPasteIndicator may be returned from ReadLine as the error, in addition
 | 
			
		||||
// to valid line data. It indicates that bracketed paste mode is enabled and
 | 
			
		||||
// that the returned line consists only of pasted data. Programs may wish to
 | 
			
		||||
// interpret pasted data more literally than typed data.
 | 
			
		||||
var ErrPasteIndicator = pasteIndicatorError{}
 | 
			
		||||
 | 
			
		||||
// SetBracketedPasteMode requests that the terminal bracket paste operations
 | 
			
		||||
// with markers. Not all terminals support this but, if it is supported, then
 | 
			
		||||
// enabling this mode will stop any autocomplete callback from running due to
 | 
			
		||||
// pastes. Additionally, any lines that are completely pasted will be returned
 | 
			
		||||
// from ReadLine with the error set to ErrPasteIndicator.
 | 
			
		||||
func (t *Terminal) SetBracketedPasteMode(on bool) {
 | 
			
		||||
	if on {
 | 
			
		||||
		io.WriteString(t.c, "\x1b[?2004h")
 | 
			
		||||
	} else {
 | 
			
		||||
		io.WriteString(t.c, "\x1b[?2004l")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stRingBuffer is a ring buffer of strings.
 | 
			
		||||
type stRingBuffer struct {
 | 
			
		||||
	// entries contains max elements.
 | 
			
		||||
	entries []string
 | 
			
		||||
	max     int
 | 
			
		||||
	// head contains the index of the element most recently added to the ring.
 | 
			
		||||
	head int
 | 
			
		||||
	// size contains the number of elements in the ring.
 | 
			
		||||
	size int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stRingBuffer) Add(a string) {
 | 
			
		||||
	if s.entries == nil {
 | 
			
		||||
		const defaultNumEntries = 100
 | 
			
		||||
		s.entries = make([]string, defaultNumEntries)
 | 
			
		||||
		s.max = defaultNumEntries
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.head = (s.head + 1) % s.max
 | 
			
		||||
	s.entries[s.head] = a
 | 
			
		||||
	if s.size < s.max {
 | 
			
		||||
		s.size++
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NthPreviousEntry returns the value passed to the nth previous call to Add.
 | 
			
		||||
// If n is zero then the immediately prior value is returned, if one, then the
 | 
			
		||||
// next most recent, and so on. If such an element doesn't exist then ok is
 | 
			
		||||
// false.
 | 
			
		||||
func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
 | 
			
		||||
	if n >= s.size {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	index := s.head - n
 | 
			
		||||
	if index < 0 {
 | 
			
		||||
		index += s.max
 | 
			
		||||
	}
 | 
			
		||||
	return s.entries[index], true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readPasswordLine reads from reader until it finds \n or io.EOF.
 | 
			
		||||
// The slice returned does not include the \n.
 | 
			
		||||
// readPasswordLine also ignores any \r it finds.
 | 
			
		||||
func readPasswordLine(reader io.Reader) ([]byte, error) {
 | 
			
		||||
	var buf [1]byte
 | 
			
		||||
	var ret []byte
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		n, err := reader.Read(buf[:])
 | 
			
		||||
		if n > 0 {
 | 
			
		||||
			switch buf[0] {
 | 
			
		||||
			case '\n':
 | 
			
		||||
				return ret, nil
 | 
			
		||||
			case '\r':
 | 
			
		||||
				// remove \r from passwords on Windows
 | 
			
		||||
			default:
 | 
			
		||||
				ret = append(ret, buf[0])
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF && len(ret) > 0 {
 | 
			
		||||
				return ret, nil
 | 
			
		||||
			}
 | 
			
		||||
			return ret, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,114 +0,0 @@
 | 
			
		|||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd
 | 
			
		||||
 | 
			
		||||
// Package terminal provides support functions for dealing with terminals, as
 | 
			
		||||
// commonly found on UNIX systems.
 | 
			
		||||
//
 | 
			
		||||
// Putting a terminal into raw mode is the most common requirement:
 | 
			
		||||
//
 | 
			
		||||
// 	oldState, err := terminal.MakeRaw(0)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 	        panic(err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	defer terminal.Restore(0, oldState)
 | 
			
		||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// State contains the state of a terminal.
 | 
			
		||||
type State struct {
 | 
			
		||||
	termios unix.Termios
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns whether the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(fd int) bool {
 | 
			
		||||
	_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
			
		||||
// mode and returns the previous state of the terminal so that it can be
 | 
			
		||||
// restored.
 | 
			
		||||
func MakeRaw(fd int) (*State, error) {
 | 
			
		||||
	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldState := State{termios: *termios}
 | 
			
		||||
 | 
			
		||||
	// This attempts to replicate the behaviour documented for cfmakeraw in
 | 
			
		||||
	// the termios(3) manpage.
 | 
			
		||||
	termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
 | 
			
		||||
	termios.Oflag &^= unix.OPOST
 | 
			
		||||
	termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
 | 
			
		||||
	termios.Cflag &^= unix.CSIZE | unix.PARENB
 | 
			
		||||
	termios.Cflag |= unix.CS8
 | 
			
		||||
	termios.Cc[unix.VMIN] = 1
 | 
			
		||||
	termios.Cc[unix.VTIME] = 0
 | 
			
		||||
	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &oldState, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetState returns the current state of a terminal which may be useful to
 | 
			
		||||
// restore the terminal after a signal.
 | 
			
		||||
func GetState(fd int) (*State, error) {
 | 
			
		||||
	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &State{termios: *termios}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
func Restore(fd int, state *State) error {
 | 
			
		||||
	return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSize returns the dimensions of the given terminal.
 | 
			
		||||
func GetSize(fd int) (width, height int, err error) {
 | 
			
		||||
	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, -1, err
 | 
			
		||||
	}
 | 
			
		||||
	return int(ws.Col), int(ws.Row), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
 | 
			
		||||
type passwordReader int
 | 
			
		||||
 | 
			
		||||
func (r passwordReader) Read(buf []byte) (int, error) {
 | 
			
		||||
	return unix.Read(int(r), buf)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
			
		||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
			
		||||
// returned does not include the \n.
 | 
			
		||||
func ReadPassword(fd int) ([]byte, error) {
 | 
			
		||||
	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newState := *termios
 | 
			
		||||
	newState.Lflag &^= unix.ECHO
 | 
			
		||||
	newState.Lflag |= unix.ICANON | unix.ISIG
 | 
			
		||||
	newState.Iflag |= unix.ICRNL
 | 
			
		||||
	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
 | 
			
		||||
 | 
			
		||||
	return readPasswordLine(passwordReader(fd))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_aix.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_aix.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
// Copyright 2018 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build aix
 | 
			
		||||
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
const ioctlReadTermios = unix.TCGETS
 | 
			
		||||
const ioctlWriteTermios = unix.TCSETS
 | 
			
		||||
							
								
								
									
										12
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
// Copyright 2013 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build darwin dragonfly freebsd netbsd openbsd
 | 
			
		||||
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
const ioctlReadTermios = unix.TIOCGETA
 | 
			
		||||
const ioctlWriteTermios = unix.TIOCSETA
 | 
			
		||||
							
								
								
									
										10
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
// Copyright 2013 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
const ioctlReadTermios = unix.TCGETS
 | 
			
		||||
const ioctlWriteTermios = unix.TCSETS
 | 
			
		||||
							
								
								
									
										58
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,58 +0,0 @@
 | 
			
		|||
// Copyright 2016 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package terminal provides support functions for dealing with terminals, as
 | 
			
		||||
// commonly found on UNIX systems.
 | 
			
		||||
//
 | 
			
		||||
// Putting a terminal into raw mode is the most common requirement:
 | 
			
		||||
//
 | 
			
		||||
// 	oldState, err := terminal.MakeRaw(0)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 	        panic(err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	defer terminal.Restore(0, oldState)
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type State struct{}
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns whether the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(fd int) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
			
		||||
// mode and returns the previous state of the terminal so that it can be
 | 
			
		||||
// restored.
 | 
			
		||||
func MakeRaw(fd int) (*State, error) {
 | 
			
		||||
	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetState returns the current state of a terminal which may be useful to
 | 
			
		||||
// restore the terminal after a signal.
 | 
			
		||||
func GetState(fd int) (*State, error) {
 | 
			
		||||
	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
func Restore(fd int, state *State) error {
 | 
			
		||||
	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSize returns the dimensions of the given terminal.
 | 
			
		||||
func GetSize(fd int) (width, height int, err error) {
 | 
			
		||||
	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
			
		||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
			
		||||
// returned does not include the \n.
 | 
			
		||||
func ReadPassword(fd int) ([]byte, error) {
 | 
			
		||||
	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										124
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,124 +0,0 @@
 | 
			
		|||
// Copyright 2015 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build solaris
 | 
			
		||||
 | 
			
		||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
	"io"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// State contains the state of a terminal.
 | 
			
		||||
type State struct {
 | 
			
		||||
	termios unix.Termios
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns whether the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(fd int) bool {
 | 
			
		||||
	_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
			
		||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
			
		||||
// returned does not include the \n.
 | 
			
		||||
func ReadPassword(fd int) ([]byte, error) {
 | 
			
		||||
	// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
 | 
			
		||||
	val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	oldState := *val
 | 
			
		||||
 | 
			
		||||
	newState := oldState
 | 
			
		||||
	newState.Lflag &^= syscall.ECHO
 | 
			
		||||
	newState.Lflag |= syscall.ICANON | syscall.ISIG
 | 
			
		||||
	newState.Iflag |= syscall.ICRNL
 | 
			
		||||
	err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
 | 
			
		||||
 | 
			
		||||
	var buf [16]byte
 | 
			
		||||
	var ret []byte
 | 
			
		||||
	for {
 | 
			
		||||
		n, err := syscall.Read(fd, buf[:])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			if len(ret) == 0 {
 | 
			
		||||
				return nil, io.EOF
 | 
			
		||||
			}
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if buf[n-1] == '\n' {
 | 
			
		||||
			n--
 | 
			
		||||
		}
 | 
			
		||||
		ret = append(ret, buf[:n]...)
 | 
			
		||||
		if n < len(buf) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRaw puts the terminal connected to the given file descriptor into raw
 | 
			
		||||
// mode and returns the previous state of the terminal so that it can be
 | 
			
		||||
// restored.
 | 
			
		||||
// see http://cr.illumos.org/~webrev/andy_js/1060/
 | 
			
		||||
func MakeRaw(fd int) (*State, error) {
 | 
			
		||||
	termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldState := State{termios: *termios}
 | 
			
		||||
 | 
			
		||||
	termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
 | 
			
		||||
	termios.Oflag &^= unix.OPOST
 | 
			
		||||
	termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
 | 
			
		||||
	termios.Cflag &^= unix.CSIZE | unix.PARENB
 | 
			
		||||
	termios.Cflag |= unix.CS8
 | 
			
		||||
	termios.Cc[unix.VMIN] = 1
 | 
			
		||||
	termios.Cc[unix.VTIME] = 0
 | 
			
		||||
 | 
			
		||||
	if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &oldState, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
func Restore(fd int, oldState *State) error {
 | 
			
		||||
	return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetState returns the current state of a terminal which may be useful to
 | 
			
		||||
// restore the terminal after a signal.
 | 
			
		||||
func GetState(fd int) (*State, error) {
 | 
			
		||||
	termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &State{termios: *termios}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSize returns the dimensions of the given terminal.
 | 
			
		||||
func GetSize(fd int) (width, height int, err error) {
 | 
			
		||||
	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return int(ws.Col), int(ws.Row), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										105
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										105
									
								
								libnetwork/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,105 +0,0 @@
 | 
			
		|||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
// Package terminal provides support functions for dealing with terminals, as
 | 
			
		||||
// commonly found on UNIX systems.
 | 
			
		||||
//
 | 
			
		||||
// Putting a terminal into raw mode is the most common requirement:
 | 
			
		||||
//
 | 
			
		||||
// 	oldState, err := terminal.MakeRaw(0)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 	        panic(err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	defer terminal.Restore(0, oldState)
 | 
			
		||||
package terminal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type State struct {
 | 
			
		||||
	mode uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns whether the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(fd int) bool {
 | 
			
		||||
	var st uint32
 | 
			
		||||
	err := windows.GetConsoleMode(windows.Handle(fd), &st)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
			
		||||
// mode and returns the previous state of the terminal so that it can be
 | 
			
		||||
// restored.
 | 
			
		||||
func MakeRaw(fd int) (*State, error) {
 | 
			
		||||
	var st uint32
 | 
			
		||||
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
 | 
			
		||||
	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &State{st}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetState returns the current state of a terminal which may be useful to
 | 
			
		||||
// restore the terminal after a signal.
 | 
			
		||||
func GetState(fd int) (*State, error) {
 | 
			
		||||
	var st uint32
 | 
			
		||||
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &State{st}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
func Restore(fd int, state *State) error {
 | 
			
		||||
	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSize returns the visible dimensions of the given terminal.
 | 
			
		||||
//
 | 
			
		||||
// These dimensions don't include any scrollback buffer height.
 | 
			
		||||
func GetSize(fd int) (width, height int, err error) {
 | 
			
		||||
	var info windows.ConsoleScreenBufferInfo
 | 
			
		||||
	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
 | 
			
		||||
		return 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
			
		||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
			
		||||
// returned does not include the \n.
 | 
			
		||||
func ReadPassword(fd int) ([]byte, error) {
 | 
			
		||||
	var st uint32
 | 
			
		||||
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	old := st
 | 
			
		||||
 | 
			
		||||
	st &^= (windows.ENABLE_ECHO_INPUT)
 | 
			
		||||
	st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
 | 
			
		||||
	if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer windows.SetConsoleMode(windows.Handle(fd), old)
 | 
			
		||||
 | 
			
		||||
	var h windows.Handle
 | 
			
		||||
	p, _ := windows.GetCurrentProcess()
 | 
			
		||||
	if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f := os.NewFile(uintptr(h), "stdin")
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	return readPasswordLine(f)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue