Этот коммит содержится в:
Christopher Speller
2017-09-29 12:46:30 -07:00
коммит произвёл GitHub
родитель 8b9dbb8613
Коммит b84736e9b6
422 изменённых файлов: 39231 добавлений и 28592 удалений

1
vendor/github.com/miekg/dns/CONTRIBUTORS сгенерированный поставляемый
Просмотреть файл

@@ -7,3 +7,4 @@ Marek Majkowski
Peter van Dijk
Omri Bahumi
Alex Sergeyev
James Hartig

340
vendor/github.com/miekg/dns/client.go сгенерированный поставляемый
Просмотреть файл

@@ -9,6 +9,7 @@ import (
"encoding/binary"
"io"
"net"
"strings"
"time"
)
@@ -27,11 +28,15 @@ type Conn struct {
// A Client defines parameters for a DNS client.
type Client struct {
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
UDPSize uint16 // minimum receive buffer for UDP messages
TLSConfig *tls.Config // TLS connection configuration
Timeout time.Duration // a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout and WriteTimeout when non-zero
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds - overridden by Timeout when that value is non-zero
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
UDPSize uint16 // minimum receive buffer for UDP messages
TLSConfig *tls.Config // TLS connection configuration
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
Timeout time.Duration
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
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
@@ -44,140 +49,11 @@ type Client struct {
// will it fall back to TCP in case of truncation.
// See client.Exchange for more information on setting larger buffer sizes.
func Exchange(m *Msg, a string) (r *Msg, err error) {
var co *Conn
co, err = DialTimeout("udp", a, dnsTimeout)
if err != nil {
return nil, err
}
defer co.Close()
opt := m.IsEdns0()
// If EDNS0 is used use that for size.
if opt != nil && opt.UDPSize() >= MinMsgSize {
co.UDPSize = opt.UDPSize()
}
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
if err = co.WriteMsg(m); err != nil {
return nil, err
}
co.SetReadDeadline(time.Now().Add(dnsTimeout))
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
}
client := Client{Net: "udp"}
r, _, err = client.Exchange(m, a)
return r, err
}
// ExchangeContext performs a synchronous UDP query, like Exchange. It
// additionally obeys deadlines from the passed Context.
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
// Combine context deadline with built-in timeout. Context chooses whichever
// is sooner.
timeoutCtx, cancel := context.WithTimeout(ctx, dnsTimeout)
defer cancel()
deadline, _ := timeoutCtx.Deadline()
co := new(Conn)
dialer := net.Dialer{}
co.Conn, err = dialer.DialContext(timeoutCtx, "udp", a)
if err != nil {
return nil, err
}
defer co.Conn.Close()
opt := m.IsEdns0()
// If EDNS0 is used use that for size.
if opt != nil && opt.UDPSize() >= MinMsgSize {
co.UDPSize = opt.UDPSize()
}
co.SetWriteDeadline(deadline)
if err = co.WriteMsg(m); err != nil {
return nil, err
}
co.SetReadDeadline(deadline)
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
}
return r, err
}
// 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:
//
// co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m)
// in, _ := co.ReadMsg()
// co.Close()
//
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
println("dns: this function is deprecated")
co := new(Conn)
co.Conn = c
if err = co.WriteMsg(m); err != nil {
return nil, err
}
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
}
return r, err
}
// Exchange performs a synchronous query. It sends the message m to the address
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
//
// c := new(dns.Client)
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
//
// Exchange does not retry a failed query, nor will it fall back to TCP in
// case of truncation.
// It is up to the caller to create a message that allows for larger responses to be
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
// of 512 bytes.
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
return c.ExchangeContext(context.Background(), m, a)
}
// 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 {
return c.exchange(ctx, m, a)
}
// This adds a bunch of garbage, TODO(miek).
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) {
return c.exchange(ctx, m, a)
})
if r != nil && shared {
r = r.Copy()
}
if err != nil {
return r, rtt, err
}
return r, rtt, nil
}
func (c *Client) dialTimeout() time.Duration {
if c.Timeout != 0 {
return c.Timeout
@@ -202,40 +78,87 @@ func (c *Client) writeTimeout() time.Duration {
return dnsTimeout
}
func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
var co *Conn
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{}
} else {
d = net.Dialer(*c.Dialer)
}
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
network := "udp"
tls := false
useTLS := false
switch c.Net {
case "tcp-tls":
network = "tcp"
tls = true
useTLS = true
case "tcp4-tls":
network = "tcp4"
tls = true
useTLS = true
case "tcp6-tls":
network = "tcp6"
tls = true
useTLS = true
default:
if c.Net != "" {
network = c.Net
}
}
var deadline time.Time
if c.Timeout != 0 {
deadline = time.Now().Add(c.Timeout)
}
dialDeadline := deadlineOrTimeoutOrCtx(ctx, deadline, c.dialTimeout())
dialTimeout := dialDeadline.Sub(time.Now())
if tls {
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, dialTimeout)
conn = new(Conn)
if useTLS {
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
} else {
co, err = DialTimeout(network, a, dialTimeout)
conn.Conn, err = d.Dial(network, address)
}
if err != nil {
return nil, err
}
return conn, nil
}
// Exchange performs a synchronous query. It sends the message m to the address
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
//
// c := new(dns.Client)
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
//
// Exchange does not retry a failed query, nor will it fall back to TCP in
// case of truncation.
// It is up to the caller to create a message that allows for larger responses to be
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
// of 512 bytes
// To specify a local address or a timeout, the caller has to set the `Client.Dialer`
// attribute appropriately
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight {
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) {
return c.exchange(m, address)
})
if r != nil && shared {
r = r.Copy()
}
return r, rtt, err
}
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
var co *Conn
co, err = c.Dial(a)
if err != nil {
return nil, 0, err
@@ -253,12 +176,13 @@ func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt ti
}
co.TsigSecret = c.TsigSecret
co.SetWriteDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.writeTimeout()))
// write with the appropriate write timeout
co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
if err = co.WriteMsg(m); err != nil {
return nil, 0, err
}
co.SetReadDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.readTimeout()))
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
@@ -352,7 +276,7 @@ func tcpMsgLen(t io.Reader) (int, error) {
return 0, err
}
// As seen with my local router/switch, retursn 1 byte on the above read,
// 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 {
@@ -467,6 +391,24 @@ func (co *Conn) Write(p []byte) (n int, err error) {
return n, err
}
// Return the appropriate timeout for a specific request
func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration {
var requestTimeout time.Duration
if c.Timeout != 0 {
requestTimeout = c.Timeout
} else {
requestTimeout = timeout
}
// net.Dialer.Timeout has priority if smaller than the timeouts computed so
// far
if c.Dialer != nil && c.Dialer.Timeout != 0 {
if c.Dialer.Timeout < requestTimeout {
requestTimeout = c.Dialer.Timeout
}
}
return requestTimeout
}
// Dial connects to the address on the named network.
func Dial(network, address string) (conn *Conn, err error) {
conn = new(Conn)
@@ -477,10 +419,44 @@ func Dial(network, address string) (conn *Conn, err error) {
return conn, nil
}
// ExchangeContext performs a synchronous UDP query, like Exchange. It
// additionally obeys deadlines from the passed Context.
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
client := Client{Net: "udp"}
r, _, err = client.ExchangeContext(ctx, m, a)
// ignorint rtt to leave the original ExchangeContext API unchanged, but
// this function will go away
return r, err
}
// 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:
//
// co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m)
// in, _ := co.ReadMsg()
// co.Close()
//
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
println("dns: ExchangeConn: this function is deprecated")
co := new(Conn)
co.Conn = c
if err = co.WriteMsg(m); err != nil {
return nil, err
}
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
}
return r, err
}
// DialTimeout acts like Dial but takes a timeout.
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
conn = new(Conn)
conn.Conn, err = net.DialTimeout(network, address, timeout)
client := Client{Net: "udp", Dialer: &net.Dialer{Timeout: timeout}}
conn, err = client.Dial(address)
if err != nil {
return nil, err
}
@@ -489,8 +465,12 @@ func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, er
// DialWithTLS connects to the address on the named network with TLS.
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
conn = new(Conn)
conn.Conn, err = tls.Dial(network, address, tlsConfig)
if !strings.HasSuffix(network, "-tls") {
network += "-tls"
}
client := Client{Net: network, TLSConfig: tlsConfig}
conn, err = client.Dial(address)
if err != nil {
return nil, err
}
@@ -499,33 +479,29 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
var dialer net.Dialer
dialer.Timeout = timeout
conn = new(Conn)
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
if !strings.HasSuffix(network, "-tls") {
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
}
// deadlineOrTimeout chooses between the provided deadline and timeout
// by always preferring the deadline so long as it's non-zero (regardless
// of which is bigger), and returns the equivalent deadline value.
func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
if deadline.IsZero() {
return time.Now().Add(timeout)
// 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) {
var timeout time.Duration
if deadline, ok := ctx.Deadline(); !ok {
timeout = 0
} else {
timeout = deadline.Sub(time.Now())
}
return deadline
}
// deadlineOrTimeoutOrCtx returns the earliest of: a context deadline, or the
// output of deadlineOrtimeout.
func deadlineOrTimeoutOrCtx(ctx context.Context, deadline time.Time, timeout time.Duration) time.Time {
result := deadlineOrTimeout(deadline, timeout)
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(result) {
result = ctxDeadline
}
return result
// 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.
c.Dialer = &net.Dialer{Timeout: timeout}
return c.Exchange(m, a)
}

168
vendor/github.com/miekg/dns/client_test.go сгенерированный поставляемый
Просмотреть файл

@@ -11,6 +11,29 @@ import (
"time"
)
func TestDialUDP(t *testing.T) {
HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("[::1]:0")
if err != nil {
t.Fatalf("unable to run test server: %v", err)
}
defer s.Shutdown()
m := new(Msg)
m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client)
conn, err := c.Dial(addrstr)
if err != nil {
t.Fatalf("failed to dial: %v", err)
}
if conn == nil {
t.Fatalf("conn is nil")
}
}
func TestClientSync(t *testing.T) {
HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.")
@@ -27,9 +50,12 @@ func TestClientSync(t *testing.T) {
c := new(Client)
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Errorf("failed to exchange: %v", err)
t.Fatalf("failed to exchange: %v", err)
}
if r != nil && r.Rcode != RcodeSuccess {
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
// And now with plain Exchange().
@@ -42,7 +68,42 @@ func TestClientSync(t *testing.T) {
}
}
func TestClientTLSSync(t *testing.T) {
func TestClientLocalAddress(t *testing.T) {
HandleFunc("miek.nl.", HelloServerEchoAddrPort)
defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
if err != nil {
t.Fatalf("unable to run test server: %v", err)
}
defer s.Shutdown()
m := new(Msg)
m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client)
laddr := net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345, Zone: ""}
c.Dialer = &net.Dialer{LocalAddr: &laddr}
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Errorf("failed to exchange: %v", err)
}
if r != nil && r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
if len(r.Extra) != 1 {
t.Errorf("failed to get additional answers\n%v", r)
}
txt := r.Extra[0].(*TXT)
if txt == nil {
t.Errorf("invalid TXT response\n%v", txt)
}
if len(txt.Txt) != 1 || txt.Txt[0] != "127.0.0.1:12345" {
t.Errorf("invalid TXT response\n%v", txt.Txt)
}
}
func TestClientTLSSyncV4(t *testing.T) {
HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.")
@@ -65,6 +126,8 @@ func TestClientTLSSync(t *testing.T) {
m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client)
// test tcp-tls
c.Net = "tcp-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
@@ -72,9 +135,88 @@ func TestClientTLSSync(t *testing.T) {
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Errorf("failed to exchange: %v", err)
t.Fatalf("failed to exchange: %v", err)
}
if r != nil && r.Rcode != RcodeSuccess {
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
// test tcp4-tls
c.Net = "tcp4-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
r, _, err = c.Exchange(m, addrstr)
if err != nil {
t.Fatalf("failed to exchange: %v", err)
}
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
}
func TestClientTLSSyncV6(t *testing.T) {
HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.")
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
if err != nil {
t.Fatalf("unable to build certificate: %v", err)
}
config := tls.Config{
Certificates: []tls.Certificate{cert},
}
s, addrstr, err := RunLocalTLSServer("[::1]:0", &config)
if err != nil {
t.Fatalf("unable to run test server: %v", err)
}
defer s.Shutdown()
m := new(Msg)
m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client)
// test tcp-tls
c.Net = "tcp-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Fatalf("failed to exchange: %v", err)
}
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
// test tcp6-tls
c.Net = "tcp6-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
r, _, err = c.Exchange(m, addrstr)
if err != nil {
t.Fatalf("failed to exchange: %v", err)
}
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
}
@@ -120,11 +262,11 @@ func TestClientEDNS0(t *testing.T) {
c := new(Client)
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Errorf("failed to exchange: %v", err)
t.Fatalf("failed to exchange: %v", err)
}
if r != nil && r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
t.Errorf("failed to get a valid answer\n%v", r)
}
}
@@ -171,11 +313,14 @@ func TestClientEDNS0Local(t *testing.T) {
c := new(Client)
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Errorf("failed to exchange: %s", err)
t.Fatalf("failed to exchange: %s", err)
}
if r != nil && r.Rcode != RcodeSuccess {
t.Error("failed to get a valid answer")
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Fatal("failed to get a valid answer")
t.Logf("%v\n", r)
}
@@ -513,6 +658,9 @@ func TestConcurrentExchanges(t *testing.T) {
for i := 0; i < len(r); i++ {
go func(i int) {
r[i], _, _ = c.Exchange(m.Copy(), addrstr)
if r[i] == nil {
t.Fatalf("response %d is nil", i)
}
wg.Done()
}(i)
}

2
vendor/github.com/miekg/dns/dnsutil/util.go сгенерированный поставляемый
Просмотреть файл

@@ -11,7 +11,7 @@ import (
"github.com/miekg/dns"
)
// AddDomain adds origin to s if s is not already a FQDN.
// AddOrigin adds origin to s if s is not already a FQDN.
// Note that the result may not be a FQDN. If origin does not end
// with a ".", the result won't either.
// This implements the zonefile convention (specified in RFC 1035,

30
vendor/github.com/miekg/dns/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +1,7 @@
/*
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 send out to the DNS. The package
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.
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
@@ -14,7 +14,7 @@ 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}
Class: dns.ClassINET, Ttl: 3600}
r.Preference = 10
r.Mx = "mx.miek.nl."
@@ -22,16 +22,16 @@ Or directly from a string:
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
Or when the default TTL (3600) and class (IN) suit you:
Or when the default origin (.) and TTL (3600) and class (IN) suit you:
mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
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:
records (sets). Use pattern for creating a message:
m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX)
@@ -51,7 +51,7 @@ 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 send.
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:
@@ -63,7 +63,23 @@ class) is as easy as setting:
c.SingleInflight = true
If these "advanced" features are not needed, a simple UDP query can be send,
More advanced options are availabe using a net.Dialer and the corresponding API.
For example it is possible to set a timeout, or to specify a source IP address
and port to use for the connection:
c := new(dns.Client)
laddr := net.UDPAddr{
IP: net.ParseIP("[::1]"),
Port: 12345,
Zone: "",
}
d := net.Dialer{
Timeout: 200 * time.Millisecond,
LocalAddr: &laddr,
}
in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")
If these "advanced" features are not needed, a simple UDP query can be sent,
with:
in, err := dns.Exchange(m1, "127.0.0.1:53")

15
vendor/github.com/miekg/dns/edns.go сгенерированный поставляемый
Просмотреть файл

@@ -21,6 +21,7 @@ const (
EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
EDNS0PADDING = 0xc // EDNS0 padding (RFC7830)
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
@@ -74,6 +75,8 @@ func (rr *OPT) String() string {
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
case *EDNS0_LOCAL:
s += "\n; LOCAL OPT: " + o.String()
case *EDNS0_PADDING:
s += "\n; PADDING: " + o.String()
}
}
return s
@@ -595,3 +598,15 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
}
return
}
// 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
// compression is applied before encryption which may break signatures.
type EDNS0_PADDING struct {
Padding []byte
}
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
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) }

7
vendor/github.com/miekg/dns/internal/socket/cmsghdr.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,7 @@
// +build linux
package socket
func (h *cmsghdr) len() int { return int(h.Len) }
func (h *cmsghdr) lvl() int { return int(h.Level) }
func (h *cmsghdr) typ() int { return int(h.Type) }

20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
// +build arm mips mipsle 386
// +build linux
package socket
type cmsghdr struct {
Len uint32
Level int32
Type int32
}
const (
sizeofCmsghdr = 0xc
)
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}

20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build linux
package socket
type cmsghdr struct {
Len uint64
Level int32
Type int32
}
const (
sizeofCmsghdr = 0x10
)
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint64(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}

13
vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,13 @@
// +build !linux
package socket
type cmsghdr struct{}
const sizeofCmsghdr = 0
func (h *cmsghdr) len() int { return 0 }
func (h *cmsghdr) lvl() int { return 0 }
func (h *cmsghdr) typ() int { return 0 }
func (h *cmsghdr) set(l, lvl, typ int) {}

118
vendor/github.com/miekg/dns/internal/socket/controlmessage.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,118 @@
package socket
import (
"errors"
"unsafe"
)
func controlHeaderLen() int {
return roundup(sizeofCmsghdr)
}
func controlMessageLen(dataLen int) int {
return roundup(sizeofCmsghdr) + dataLen
}
// returns the whole length of control message.
func ControlMessageSpace(dataLen int) int {
return roundup(sizeofCmsghdr) + roundup(dataLen)
}
// A ControlMessage represents the head message in a stream of control
// messages.
//
// A control message comprises of a header, data and a few padding
// fields to conform to the interface to the kernel.
//
// See RFC 3542 for further information.
type ControlMessage []byte
// Data returns the data field of the control message at the head.
func (m ControlMessage) Data(dataLen int) []byte {
l := controlHeaderLen()
if len(m) < l || len(m) < l+dataLen {
return nil
}
return m[l : l+dataLen]
}
// ParseHeader parses and returns the header fields of the control
// message at the head.
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
l := controlHeaderLen()
if len(m) < l {
return 0, 0, 0, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
}
// Next returns the control message at the next.
func (m ControlMessage) Next(dataLen int) ControlMessage {
l := ControlMessageSpace(dataLen)
if len(m) < l {
return nil
}
return m[l:]
}
// MarshalHeader marshals the header fields of the control message at
// the head.
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
if len(m) < controlHeaderLen() {
return errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(dataLen), lvl, typ)
return nil
}
// Marshal marshals the control message at the head, and returns the next
// control message.
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
l := len(data)
if len(m) < ControlMessageSpace(l) {
return nil, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(l), lvl, typ)
if l > 0 {
copy(m.Data(l), data)
}
return m.Next(l), nil
}
// Parse parses as a single or multiple control messages.
func (m ControlMessage) Parse() ([]ControlMessage, error) {
var ms []ControlMessage
for len(m) >= controlHeaderLen() {
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
l := h.len()
if l <= 0 {
return nil, errors.New("invalid header length")
}
if uint64(l) < uint64(controlHeaderLen()) {
return nil, errors.New("invalid message length")
}
if uint64(l) > uint64(len(m)) {
return nil, errors.New("short buffer")
}
ms = append(ms, ControlMessage(m[:l]))
ll := l - controlHeaderLen()
if len(m) >= ControlMessageSpace(ll) {
m = m[ControlMessageSpace(ll):]
} else {
m = m[controlMessageLen(ll):]
}
}
return ms, nil
}
// NewControlMessage returns a new stream of control messages.
func NewControlMessage(dataLen []int) ControlMessage {
var l int
for i := range dataLen {
l += ControlMessageSpace(dataLen[i])
}
return make([]byte, l)
}

103
vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,103 @@
// +build linux
package socket
import (
"bytes"
"testing"
)
type mockControl struct {
Level int
Type int
Data []byte
}
func TestControlMessage(t *testing.T) {
for _, tt := range []struct {
cs []mockControl
}{
{
[]mockControl{
{Level: 1, Type: 1},
},
},
{
[]mockControl{
{Level: 2, Type: 2, Data: []byte{0xfe}},
},
},
{
[]mockControl{
{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
},
},
{
[]mockControl{
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
},
},
{
[]mockControl{
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
{Level: 2, Type: 2, Data: []byte{0xfe}},
},
},
} {
var w []byte
var tailPadLen int
mm := NewControlMessage([]int{0})
for i, c := range tt.cs {
m := NewControlMessage([]int{len(c.Data)})
l := len(m) - len(mm)
if i == len(tt.cs)-1 && l > len(c.Data) {
tailPadLen = l - len(c.Data)
}
w = append(w, m...)
}
var err error
ww := make([]byte, len(w))
copy(ww, w)
m := ControlMessage(ww)
for _, c := range tt.cs {
if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
}
copy(m.Data(len(c.Data)), c.Data)
m = m.Next(len(c.Data))
}
m = ControlMessage(w)
for _, c := range tt.cs {
m, err = m.Marshal(c.Level, c.Type, c.Data)
if err != nil {
t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
}
}
if !bytes.Equal(ww, w) {
t.Fatalf("got %#v; want %#v", ww, w)
}
ws := [][]byte{w}
if tailPadLen > 0 {
// Test a message with no tail padding.
nopad := w[:len(w)-tailPadLen]
ws = append(ws, [][]byte{nopad}...)
}
for _, w := range ws {
ms, err := ControlMessage(w).Parse()
if err != nil {
t.Fatalf("(%v).Parse() = %v", tt.cs, err)
}
for i, m := range ms {
lvl, typ, dataLen, err := m.ParseHeader()
if err != nil {
t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
}
if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
}
}
}
}
}

4
vendor/github.com/miekg/dns/internal/socket/socket.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,4 @@
// Package socket contains ControlMessage parsing code from
// golang.org/x/net/internal/socket. Instead of supporting all possible
// architectures, we're only supporting linux 32/64 bit.
package socket

14
vendor/github.com/miekg/dns/internal/socket/sys.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,14 @@
package socket
import "unsafe"
var (
kernelAlign = func() int {
var p uintptr
return int(unsafe.Sizeof(p))
}()
)
func roundup(l int) int {
return (l + kernelAlign - 1) & ^(kernelAlign - 1)
}

7
vendor/github.com/miekg/dns/msg_helpers.go сгенерированный поставляемый
Просмотреть файл

@@ -458,6 +458,13 @@ Option:
}
edns = append(edns, e)
off += int(optlen)
case EDNS0PADDING:
e := new(EDNS0_PADDING)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
default:
e := new(EDNS0_LOCAL)
e.Code = code

188
vendor/github.com/miekg/dns/parse_test.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,7 @@ import (
"math/rand"
"net"
"reflect"
"regexp"
"strconv"
"strings"
"testing"
@@ -571,81 +572,88 @@ test IN CNAME test.a.example.com.
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", i, float32(delta)/1e9, float32(i)/(float32(delta)/1e9))
}
func ExampleParseZone() {
zone := `$ORIGIN .
$TTL 3600 ; 1 hour
name IN SOA a6.nstld.com. hostmaster.nic.name. (
203362132 ; serial
300 ; refresh (5 minutes)
300 ; retry (5 minutes)
1209600 ; expire (2 weeks)
300 ; minimum (5 minutes)
)
$TTL 10800 ; 3 hours
name. 10800 IN NS name.
IN NS g6.nstld.com.
7200 NS h6.nstld.com.
3600 IN NS j6.nstld.com.
IN 3600 NS k6.nstld.com.
NS l6.nstld.com.
NS a6.nstld.com.
NS c6.nstld.com.
NS d6.nstld.com.
NS f6.nstld.com.
NS m6.nstld.com.
(
NS m7.nstld.com.
)
$ORIGIN name.
0-0onlus NS ns7.ehiweb.it.
NS ns8.ehiweb.it.
0-g MX 10 mx01.nic
MX 10 mx02.nic
MX 10 mx03.nic
MX 10 mx04.nic
$ORIGIN 0-g.name
moutamassey NS ns01.yahoodomains.jp.
NS ns02.yahoodomains.jp.
func TestOmittedTTL(t *testing.T) {
zone := `
$ORIGIN example.com.
example.com. 42 IN SOA ns1.example.com. hostmaster.example.com. 1 86400 60 86400 3600 ; TTL=42 SOA
example.com. NS 2 ; TTL=42 absolute owner name
@ MD 3 ; TTL=42 current-origin owner name
MF 4 ; TTL=42 leading-space implied owner name
43 TYPE65280 \# 1 05 ; TTL=43 implied owner name explicit TTL
MB 6 ; TTL=43 leading-tab implied owner name
$TTL 1337
example.com. 88 MG 7 ; TTL=88 explicit TTL
example.com. MR 8 ; TTL=1337 after first $TTL
$TTL 314
1 TXT 9 ; TTL=1 implied owner name explicit TTL
example.com. DNAME 10 ; TTL=314 after second $TTL
`
to := ParseZone(strings.NewReader(zone), "", "testzone")
for x := range to {
fmt.Println(x.RR)
reCaseFromComment := regexp.MustCompile(`TTL=(\d+)\s+(.*)`)
records := ParseZone(strings.NewReader(zone), "", "")
var i int
for record := range records {
i++
if record.Error != nil {
t.Error(record.Error)
continue
}
expected := reCaseFromComment.FindStringSubmatch(record.Comment)
expectedTTL, _ := strconv.ParseUint(expected[1], 10, 32)
ttl := record.RR.Header().Ttl
if ttl != uint32(expectedTTL) {
t.Errorf("%s: expected TTL %d, got %d", expected[2], expectedTTL, ttl)
}
}
if i != 10 {
t.Errorf("expected %d records, got %d", 5, i)
}
// Output:
// name. 3600 IN SOA a6.nstld.com. hostmaster.nic.name. 203362132 300 300 1209600 300
// name. 10800 IN NS name.
// name. 10800 IN NS g6.nstld.com.
// name. 7200 IN NS h6.nstld.com.
// name. 3600 IN NS j6.nstld.com.
// name. 3600 IN NS k6.nstld.com.
// name. 10800 IN NS l6.nstld.com.
// name. 10800 IN NS a6.nstld.com.
// name. 10800 IN NS c6.nstld.com.
// name. 10800 IN NS d6.nstld.com.
// name. 10800 IN NS f6.nstld.com.
// name. 10800 IN NS m6.nstld.com.
// name. 10800 IN NS m7.nstld.com.
// 0-0onlus.name. 10800 IN NS ns7.ehiweb.it.
// 0-0onlus.name. 10800 IN NS ns8.ehiweb.it.
// 0-g.name. 10800 IN MX 10 mx01.nic.name.
// 0-g.name. 10800 IN MX 10 mx02.nic.name.
// 0-g.name. 10800 IN MX 10 mx03.nic.name.
// 0-g.name. 10800 IN MX 10 mx04.nic.name.
// moutamassey.0-g.name.name. 10800 IN NS ns01.yahoodomains.jp.
// moutamassey.0-g.name.name. 10800 IN NS ns02.yahoodomains.jp.
}
func ExampleHIP() {
h := `www.example.com IN HIP ( 2 200100107B1A74DF365639CC39F1D578
AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
rvs.example.com. )`
if hip, err := NewRR(h); err == nil {
fmt.Println(hip.String())
func TestRelativeNameErrors(t *testing.T) {
var badZones = []struct {
label string
zoneContents string
expectedErr string
}{
{
"relative owner name without origin",
"example.com 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600",
"bad owner name",
},
{
"relative owner name in RDATA",
"example.com. 3600 IN SOA ns hostmaster 1 86400 60 86400 3600",
"bad SOA Ns",
},
{
"origin reference without origin",
"@ 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600",
"bad owner name",
},
{
"relative owner name in $INCLUDE",
"$INCLUDE file.db example.com",
"bad origin name",
},
{
"relative owner name in $ORIGIN",
"$ORIGIN example.com",
"bad origin name",
},
}
for _, errorCase := range badZones {
entries := ParseZone(strings.NewReader(errorCase.zoneContents), "", "")
for entry := range entries {
if entry.Error == nil {
t.Errorf("%s: expected error, got nil", errorCase.label)
continue
}
err := entry.Error.err
if err != errorCase.expectedErr {
t.Errorf("%s: expected error `%s`, got `%s`", errorCase.label, errorCase.expectedErr, err)
}
}
}
// Output:
// www.example.com. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
}
func TestHIP(t *testing.T) {
@@ -686,24 +694,6 @@ b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
}
}
func ExampleSOA() {
s := "example.com. 1000 SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100"
if soa, err := NewRR(s); err == nil {
fmt.Println(soa.String())
}
// Output:
// example.com. 1000 IN SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100
}
func TestLineNumberError(t *testing.T) {
s := "example.com. 1000 SOA master.example.com. admin.example.com. monkey 4294967294 4294967293 4294967295 100"
if _, err := NewRR(s); err != nil {
if err.Error() != "dns: bad SOA zone parameter: \"monkey\" at line: 1:68" {
t.Error("not expecting this error: ", err)
}
}
}
// Test with no known RR on the line
func TestLineNumberError2(t *testing.T) {
tests := map[string]string{
@@ -801,28 +791,6 @@ func TestLowercaseTokens(t *testing.T) {
}
}
func ExampleParseZone_generate() {
// From the manual: http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2566761
zone := "$GENERATE 1-2 0 NS SERVER$.EXAMPLE.\n$GENERATE 1-8 $ CNAME $.0"
to := ParseZone(strings.NewReader(zone), "0.0.192.IN-ADDR.ARPA.", "")
for x := range to {
if x.Error == nil {
fmt.Println(x.RR.String())
}
}
// Output:
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER1.EXAMPLE.
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER2.EXAMPLE.
// 1.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 1.0.0.0.192.IN-ADDR.ARPA.
// 2.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 2.0.0.0.192.IN-ADDR.ARPA.
// 3.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 3.0.0.0.192.IN-ADDR.ARPA.
// 4.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 4.0.0.0.192.IN-ADDR.ARPA.
// 5.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 5.0.0.0.192.IN-ADDR.ARPA.
// 6.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 6.0.0.0.192.IN-ADDR.ARPA.
// 7.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 7.0.0.0.192.IN-ADDR.ARPA.
// 8.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 8.0.0.0.192.IN-ADDR.ARPA.
}
func TestSRVPacking(t *testing.T) {
msg := Msg{}

2
vendor/github.com/miekg/dns/privaterr_test.go сгенерированный поставляемый
Просмотреть файл

@@ -143,7 +143,7 @@ func (rd *VERSION) Len() int {
}
var smallzone = `$ORIGIN example.org.
@ SOA sns.dns.icann.org. noc.dns.icann.org. (
@ 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. (
2014091518 7200 3600 1209600 3600
)
A 1.2.3.4

129
vendor/github.com/miekg/dns/scan.go сгенерированный поставляемый
Просмотреть файл

@@ -105,6 +105,12 @@ type Token struct {
Comment string
}
// ttlState describes the state necessary to fill in an omitted RR TTL
type ttlState struct {
ttl uint32 // ttl is the current default TTL
isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
}
// NewRR reads the RR contained in the string s. Only the first RR is
// returned. If s contains no RR, return nil with no error. The class
// defaults to IN and TTL defaults to 3600. The full zone file syntax
@@ -120,7 +126,8 @@ func NewRR(s string) (RR, error) {
// ReadRR reads the RR contained in q.
// See NewRR for more documentation.
func ReadRR(q io.Reader, filename string) (RR, error) {
r := <-parseZoneHelper(q, ".", filename, 1)
defttl := &ttlState{defaultTtl, false}
r := <-parseZoneHelper(q, ".", defttl, filename, 1)
if r == nil {
return nil, nil
}
@@ -132,10 +139,10 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
}
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
// returned channel, which consist out the parsed RR, a potential comment or an error.
// If there is an error the RR is nil. The string file is only used
// returned channel, each consisting of either a parsed RR and optional comment
// or a nil RR and an error. The string file is only used
// in error reporting. The string origin is used as the initial origin, as
// if the file would start with: $ORIGIN origin .
// if the file would start with an $ORIGIN directive.
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
// The channel t is closed by ParseZone when the end of r is reached.
//
@@ -157,16 +164,16 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
// The text "; this is comment" is returned in Token.Comment. Comments inside the
// RR are discarded. Comments on a line by themselves are discarded too.
func ParseZone(r io.Reader, origin, file string) chan *Token {
return parseZoneHelper(r, origin, file, 10000)
return parseZoneHelper(r, origin, nil, file, 10000)
}
func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
func parseZoneHelper(r io.Reader, origin string, defttl *ttlState, file string, chansize int) chan *Token {
t := make(chan *Token, chansize)
go parseZone(r, origin, file, t, 0)
go parseZone(r, origin, defttl, file, t, 0)
return t
}
func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *Token, include int) {
defer func() {
if include == 0 {
close(t)
@@ -186,18 +193,16 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
// After detecting these, we know the zRrtype so we can jump to functions
// handling the rdata for each of these types.
if origin == "" {
origin = "."
}
origin = Fqdn(origin)
if _, ok := IsDomainName(origin); !ok {
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
return
if origin != "" {
origin = Fqdn(origin)
if _, ok := IsDomainName(origin); !ok {
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
return
}
}
st := zExpectOwnerDir // initial state
var h RR_Header
var defttl uint32 = defaultTtl
var prevName string
for l := range c {
// Lexer spotted an error already
@@ -209,27 +214,21 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
switch st {
case zExpectOwnerDir:
// We can also expect a directive, like $TTL or $ORIGIN
h.Ttl = defttl
if defttl != nil {
h.Ttl = defttl.ttl
}
h.Class = ClassINET
switch l.value {
case zNewline:
st = zExpectOwnerDir
case zOwner:
h.Name = l.token
if l.token[0] == '@' {
h.Name = origin
prevName = h.Name
st = zExpectOwnerBl
break
}
if h.Name[l.length-1] != '.' {
h.Name = appendOrigin(h.Name, origin)
}
_, ok := IsDomainName(l.token)
name, ok := toAbsoluteName(l.token, origin)
if !ok {
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
return
}
h.Name = name
prevName = h.Name
st = zExpectOwnerBl
case zDirTtl:
@@ -258,8 +257,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
return
}
h.Ttl = ttl
// Don't about the defttl, we should take the $TTL value
// defttl = ttl
if defttl == nil || !defttl.isByDirective {
defttl = &ttlState{ttl, false}
}
st = zExpectAnyNoTtlBl
default:
@@ -282,20 +282,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
case zBlank:
l := <-c
if l.value == zString {
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
name, ok := toAbsoluteName(l.token, origin)
if !ok {
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
return
}
// a new origin is specified.
if l.token[l.length-1] != '.' {
if origin != "." { // Prevent .. endings
neworigin = l.token + "." + origin
} else {
neworigin = l.token + origin
}
} else {
neworigin = l.token
}
neworigin = name
}
case zNewline, zEOF:
// Ok
@@ -313,7 +305,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
return
}
parseZone(r1, l.token, neworigin, t, include+1)
parseZone(r1, neworigin, defttl, l.token, t, include+1)
st = zExpectOwnerDir
case zExpectDirTtlBl:
if l.value != zBlank {
@@ -335,7 +327,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
return
}
defttl = ttl
defttl = &ttlState{ttl, true}
st = zExpectOwnerDir
case zExpectDirOriginBl:
if l.value != zBlank {
@@ -351,19 +343,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
if e, _ := slurpRemainder(c, f); e != nil {
t <- &Token{Error: e}
}
if _, ok := IsDomainName(l.token); !ok {
name, ok := toAbsoluteName(l.token, origin)
if !ok {
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
return
}
if l.token[l.length-1] != '.' {
if origin != "." { // Prevent .. endings
origin = l.token + "." + origin
} else {
origin = l.token + origin
}
} else {
origin = l.token
}
origin = name
st = zExpectOwnerDir
case zExpectDirGenerateBl:
if l.value != zBlank {
@@ -390,6 +375,10 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
case zExpectAny:
switch l.value {
case zRrtpe:
if defttl == nil {
t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}}
return
}
h.Rrtype = l.torc
st = zExpectRdata
case zClass:
@@ -402,7 +391,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
return
}
h.Ttl = ttl
// defttl = ttl // don't set the defttl here
if defttl == nil || !defttl.isByDirective {
defttl = &ttlState{ttl, false}
}
st = zExpectAnyNoTtlBl
default:
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
@@ -441,7 +432,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
return
}
h.Ttl = ttl
// defttl = ttl // don't set the def ttl anymore
if defttl == nil || !defttl.isByDirective {
defttl = &ttlState{ttl, false}
}
st = zExpectRrtypeBl
case zRrtpe:
h.Rrtype = l.torc
@@ -918,6 +911,34 @@ func stringToCm(token string) (e, m uint8, ok bool) {
return
}
func toAbsoluteName(name, origin string) (absolute string, ok bool) {
// check for an explicit origin reference
if name == "@" {
// require a nonempty origin
if origin == "" {
return "", false
}
return origin, true
}
// require a valid domain name
_, ok = IsDomainName(name)
if !ok || name == "" {
return "", false
}
// check if name is already absolute
if name[len(name)-1] == '.' {
return name, true
}
// require a nonempty origin
if origin == "" {
return "", false
}
return appendOrigin(name, origin), true
}
func appendOrigin(name, origin string) string {
if origin == "." {
return name + origin

592
vendor/github.com/miekg/dns/scan_rr.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

5
vendor/github.com/miekg/dns/scan_test.go сгенерированный поставляемый
Просмотреть файл

@@ -21,13 +21,16 @@ func TestParseZoneInclude(t *testing.T) {
t.Fatalf("could not close tmpfile %q: %s", tmpfile.Name(), err)
}
zone := "$INCLUDE " + tmpfile.Name()
zone := "$ORIGIN example.org.\n$INCLUDE " + tmpfile.Name()
tok := ParseZone(strings.NewReader(zone), "", "")
for x := range tok {
if x.Error != nil {
t.Fatalf("expected no error, but got %s", x.Error)
}
if x.RR.Header().Name != "foo.example.org." {
t.Fatalf("expected %s, but got %s", "foo.example.org.", x.RR.Header().Name)
}
}
os.Remove(tmpfile.Name())

10
vendor/github.com/miekg/dns/server_test.go сгенерированный поставляемый
Просмотреть файл

@@ -30,6 +30,16 @@ func HelloServerBadID(w ResponseWriter, req *Msg) {
w.WriteMsg(m)
}
func HelloServerEchoAddrPort(w ResponseWriter, req *Msg) {
m := new(Msg)
m.SetReply(req)
remoteAddr := w.RemoteAddr().String()
m.Extra = make([]RR, 1)
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{remoteAddr}}
w.WriteMsg(m)
}
func AnotherHelloServer(w ResponseWriter, req *Msg) {
m := new(Msg)
m.SetReply(req)

15
vendor/github.com/miekg/dns/udp.go сгенерированный поставляемый
Просмотреть файл

@@ -27,8 +27,19 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
return n, &SessionUDP{raddr, oob[:oobn]}, err
}
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
oob := correctSource(session.context)
n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
return n, err
}
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
func correctSource(oob []byte) []byte {
dst, err := parseUDPSocketDst(oob)
// If the destination could not be determined, ignore.
if err != nil || dst == nil {
return nil
}
return marshalUDPSocketSrc(dst)
}

115
vendor/github.com/miekg/dns/udp_linux.go сгенерированный поставляемый
Просмотреть файл

@@ -13,8 +13,34 @@ package dns
import (
"net"
"syscall"
"unsafe"
"github.com/miekg/dns/internal/socket"
)
const (
sizeofInet6Pktinfo = 0x14
sizeofInetPktinfo = 0xc
protocolIP = 0
protocolIPv6 = 41
)
type inetPktinfo struct {
Ifindex int32
Spec_dst [4]byte /* in_addr */
Addr [4]byte /* in_addr */
}
type inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex int32
}
type inetControlMessage struct {
Src net.IP // source address, specifying only
Dst net.IP // destination address, receiving only
}
// setUDPSocketOptions sets the UDP socket options.
// This function is implemented on a per platform basis. See udp_*.go for more details
func setUDPSocketOptions(conn *net.UDPConn) error {
@@ -103,3 +129,92 @@ func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
defer file.Close()
return syscall.Getsockname(int(file.Fd()))
}
// marshalInetPacketInfo marshals a ipv4 control message, returning
// the byte slice for the next marshal, if any
func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
if cm != nil {
pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
if ip := cm.Src.To4(); ip != nil {
copy(pi.Spec_dst[:], ip)
}
}
return m.Next(sizeofInetPktinfo)
}
// marshalInet6PacketInfo marshals a ipv6 control message, returning
// the byte slice for the next marshal, if any
func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
if cm != nil {
pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
copy(pi.Addr[:], ip)
}
}
return m.Next(sizeofInet6Pktinfo)
}
func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
if len(cm.Dst) < net.IPv4len {
cm.Dst = make(net.IP, net.IPv4len)
}
copy(cm.Dst, pi.Addr[:])
}
func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
if len(cm.Dst) < net.IPv6len {
cm.Dst = make(net.IP, net.IPv6len)
}
copy(cm.Dst, pi.Addr[:])
}
// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
// the Dst address
func parseUDPSocketDst(oob []byte) (net.IP, error) {
cm := new(inetControlMessage)
ms, err := socket.ControlMessage(oob).Parse()
if err != nil {
return nil, err
}
for _, m := range ms {
lvl, typ, l, err := m.ParseHeader()
if err != nil {
return nil, err
}
if lvl == protocolIPv6 { // IPv6
if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
parseInet6PacketInfo(cm, m.Data(l))
}
} else if lvl == protocolIP { // IPv4
if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
parseInetPacketInfo(cm, m.Data(l))
}
}
}
return cm.Dst, nil
}
// marshalUDPSocketSrc takes the given src address and returns out-of-band data
// to give to WriteMsgUDP
func marshalUDPSocketSrc(src net.IP) []byte {
var oob []byte
// If the dst is definitely an ipv6, then use ipv6 control to respond
// otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
// See marshalInet6PacketInfo
cm := new(inetControlMessage)
cm.Src = src
if src.To4() == nil {
oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
marshalInet6PacketInfo(oob, cm)
} else {
oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
marshalInetPacketInfo(oob, cm)
}
return oob
}

68
vendor/github.com/miekg/dns/udp_linux_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,68 @@
// +build linux,!appengine
package dns
import (
"bytes"
"net"
"testing"
)
func TestParseUDPSocketDst(t *testing.T) {
// dst is :ffff:100.100.100.100
oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
dst, err := parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv6 oob: %v", err)
}
dst4 := dst.To4()
if dst4 == nil {
t.Errorf("failed to parse ipv4: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected ipv4: %v", dst4)
}
// dst is 2001:db8::1
oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
dst, err = parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv6 oob: %v", err)
}
dst6 := dst.To16()
if dst6 == nil {
t.Errorf("failed to parse ipv6: %v", dst)
} else if dst6.String() != "2001:db8::1" {
t.Errorf("unexpected ipv6: %v", dst4)
}
// dst is 100.100.100.100 but was received on 10.10.10.10
oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
dst, err = parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv4 oob: %v", err)
}
dst4 = dst.To4()
if dst4 == nil {
t.Errorf("failed to parse ipv4: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected ipv4: %v", dst4)
}
}
func TestMarshalUDPSocketSrc(t *testing.T) {
// src is 100.100.100.100
exoob := []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0}
oob := marshalUDPSocketSrc(net.ParseIP("100.100.100.100"))
if !bytes.Equal(exoob, oob) {
t.Errorf("expected ipv4 oob:\n%v", exoob)
t.Errorf("actual ipv4 oob:\n%v", oob)
}
// src is 2001:db8::1
exoob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
oob = marshalUDPSocketSrc(net.ParseIP("2001:db8::1"))
if !bytes.Equal(exoob, oob) {
t.Errorf("expected ipv6 oob:\n%v", exoob)
t.Errorf("actual ipv6 oob:\n%v", oob)
}
}

10
vendor/github.com/miekg/dns/udp_other.go сгенерированный поставляемый
Просмотреть файл

@@ -9,7 +9,9 @@ import (
// These do nothing. See udp_linux.go for an example of how to implement this.
// We tried to adhire to some kind of naming scheme.
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
func parseUDPSocketDst(oob []byte) (net.IP, error) { return nil, nil }
func marshalUDPSocketSrc(src net.IP) []byte { return nil }

5
vendor/github.com/miekg/dns/udp_windows.go сгенерированный поставляемый
Просмотреть файл

@@ -4,10 +4,12 @@ package dns
import "net"
// SessionUDP holds the remote address
type SessionUDP struct {
raddr *net.UDPAddr
}
// RemoteAddr returns the remote network address.
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
@@ -21,9 +23,8 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
return n, session, err
}
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
n, err := conn.WriteTo(b, session.raddr)
return n, err
}