summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/miekg/dns
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/miekg/dns')
-rw-r--r--vendor/github.com/miekg/dns/CONTRIBUTORS1
-rw-r--r--vendor/github.com/miekg/dns/client.go332
-rw-r--r--vendor/github.com/miekg/dns/client_test.go168
-rw-r--r--vendor/github.com/miekg/dns/dnsutil/util.go2
-rw-r--r--vendor/github.com/miekg/dns/doc.go30
-rw-r--r--vendor/github.com/miekg/dns/edns.go15
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr.go7
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go20
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go20
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go13
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage.go118
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go103
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/socket.go4
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/sys.go14
-rw-r--r--vendor/github.com/miekg/dns/msg_helpers.go7
-rw-r--r--vendor/github.com/miekg/dns/parse_test.go190
-rw-r--r--vendor/github.com/miekg/dns/privaterr_test.go2
-rw-r--r--vendor/github.com/miekg/dns/scan.go129
-rw-r--r--vendor/github.com/miekg/dns/scan_rr.go590
-rw-r--r--vendor/github.com/miekg/dns/scan_test.go5
-rw-r--r--vendor/github.com/miekg/dns/server_test.go10
-rw-r--r--vendor/github.com/miekg/dns/udp.go15
-rw-r--r--vendor/github.com/miekg/dns/udp_linux.go115
-rw-r--r--vendor/github.com/miekg/dns/udp_linux_test.go68
-rw-r--r--vendor/github.com/miekg/dns/udp_other.go10
-rw-r--r--vendor/github.com/miekg/dns/udp_windows.go5
26 files changed, 1286 insertions, 707 deletions
diff --git a/vendor/github.com/miekg/dns/CONTRIBUTORS b/vendor/github.com/miekg/dns/CONTRIBUTORS
index f77e8a895..5903779d8 100644
--- a/vendor/github.com/miekg/dns/CONTRIBUTORS
+++ b/vendor/github.com/miekg/dns/CONTRIBUTORS
@@ -7,3 +7,4 @@ Marek Majkowski
Peter van Dijk
Omri Bahumi
Alex Sergeyev
+James Hartig
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
index 1c14a19d8..359a0ab8f 100644
--- a/vendor/github.com/miekg/dns/client.go
+++ b/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,91 +49,74 @@ 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()
+ client := Client{Net: "udp"}
+ r, _, err = client.Exchange(m, a)
+ return r, err
+}
- opt := m.IsEdns0()
- // If EDNS0 is used use that for size.
- if opt != nil && opt.UDPSize() >= MinMsgSize {
- co.UDPSize = opt.UDPSize()
+func (c *Client) dialTimeout() time.Duration {
+ if c.Timeout != 0 {
+ return c.Timeout
}
-
- co.SetWriteDeadline(time.Now().Add(dnsTimeout))
- if err = co.WriteMsg(m); err != nil {
- return nil, err
+ if c.DialTimeout != 0 {
+ return c.DialTimeout
}
+ return dnsTimeout
+}
- co.SetReadDeadline(time.Now().Add(dnsTimeout))
- r, err = co.ReadMsg()
- if err == nil && r.Id != m.Id {
- err = ErrId
+func (c *Client) readTimeout() time.Duration {
+ if c.ReadTimeout != 0 {
+ return c.ReadTimeout
}
- return r, err
+ return dnsTimeout
}
-// 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
+func (c *Client) writeTimeout() time.Duration {
+ if c.WriteTimeout != 0 {
+ return c.WriteTimeout
}
+ return dnsTimeout
+}
- 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()
+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())
- co.SetWriteDeadline(deadline)
- if err = co.WriteMsg(m); err != nil {
- return nil, err
- }
+ network := "udp"
+ useTLS := false
- co.SetReadDeadline(deadline)
- r, err = co.ReadMsg()
- if err == nil && r.Id != m.Id {
- err = ErrId
+ 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
+ }
}
- 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
+ conn = new(Conn)
+ if useTLS {
+ conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
+ } else {
+ conn.Conn, err = d.Dial(network, address)
}
- r, err = co.ReadMsg()
- if err == nil && r.Id != m.Id {
- err = ErrId
+ if err != nil {
+ return nil, err
}
- return r, err
+ return conn, nil
}
// Exchange performs a synchronous query. It sends the message m to the address
@@ -142,22 +130,14 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
// 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) {
+// 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(ctx, m, a)
+ return c.exchange(m, address)
}
- // This adds a bunch of garbage, TODO(miek).
+
t := "nop"
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
t = t1
@@ -167,75 +147,18 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (
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)
+ return c.exchange(m, address)
})
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
- }
- if c.DialTimeout != 0 {
- return c.DialTimeout
- }
- return dnsTimeout
+ return r, rtt, err
}
-func (c *Client) readTimeout() time.Duration {
- if c.ReadTimeout != 0 {
- return c.ReadTimeout
- }
- return dnsTimeout
-}
-
-func (c *Client) writeTimeout() time.Duration {
- if c.WriteTimeout != 0 {
- return c.WriteTimeout
- }
- return dnsTimeout
-}
-
-func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
+func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
var co *Conn
- network := "udp"
- tls := false
-
- switch c.Net {
- case "tcp-tls":
- network = "tcp"
- tls = true
- case "tcp4-tls":
- network = "tcp4"
- tls = true
- case "tcp6-tls":
- network = "tcp6"
- tls = true
- default:
- if c.Net != "" {
- network = c.Net
- }
- }
-
- var deadline time.Time
- if c.Timeout != 0 {
- deadline = time.Now().Add(c.Timeout)
- }
-
- dialDeadline := deadlineOrTimeoutOrCtx(ctx, deadline, c.dialTimeout())
- dialTimeout := dialDeadline.Sub(time.Now())
- if tls {
- co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, dialTimeout)
- } else {
- co, err = DialTimeout(network, a, dialTimeout)
- }
+ 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)
- }
- 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
+// 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 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)
}
diff --git a/vendor/github.com/miekg/dns/client_test.go b/vendor/github.com/miekg/dns/client_test.go
index 73083dbaf..3ff619cfa 100644
--- a/vendor/github.com/miekg/dns/client_test.go
+++ b/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)
}
diff --git a/vendor/github.com/miekg/dns/dnsutil/util.go b/vendor/github.com/miekg/dns/dnsutil/util.go
index 9ed03f296..c8c6af7b3 100644
--- a/vendor/github.com/miekg/dns/dnsutil/util.go
+++ b/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,
diff --git a/vendor/github.com/miekg/dns/doc.go b/vendor/github.com/miekg/dns/doc.go
index e38753d7d..ceabd24c1 100644
--- a/vendor/github.com/miekg/dns/doc.go
+++ b/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")
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
index dbff3714c..718842f28 100644
--- a/vendor/github.com/miekg/dns/edns.go
+++ b/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) }
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
new file mode 100644
index 000000000..62f2d2f74
--- /dev/null
+++ b/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) }
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
new file mode 100644
index 000000000..e92e85800
--- /dev/null
+++ b/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)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
new file mode 100644
index 000000000..ddfc9e09a
--- /dev/null
+++ b/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)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
new file mode 100644
index 000000000..8078487c8
--- /dev/null
+++ b/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) {}
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage.go
new file mode 100644
index 000000000..3176e9602
--- /dev/null
+++ b/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)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
new file mode 100644
index 000000000..e9fff4d45
--- /dev/null
+++ b/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))
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/socket.go b/vendor/github.com/miekg/dns/internal/socket/socket.go
new file mode 100644
index 000000000..edb58e29a
--- /dev/null
+++ b/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
diff --git a/vendor/github.com/miekg/dns/internal/socket/sys.go b/vendor/github.com/miekg/dns/internal/socket/sys.go
new file mode 100644
index 000000000..2f3f5cfed
--- /dev/null
+++ b/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)
+}
diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go
index 8d415c92a..0ca12b048 100644
--- a/vendor/github.com/miekg/dns/msg_helpers.go
+++ b/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
diff --git a/vendor/github.com/miekg/dns/parse_test.go b/vendor/github.com/miekg/dns/parse_test.go
index fc5bdaf5d..c7ecb499d 100644
--- a/vendor/github.com/miekg/dns/parse_test.go
+++ b/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)
- }
- // 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.
+ 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)
+ }
}
-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{}
diff --git a/vendor/github.com/miekg/dns/privaterr_test.go b/vendor/github.com/miekg/dns/privaterr_test.go
index 72ec8f5c0..f50d0f48c 100644
--- a/vendor/github.com/miekg/dns/privaterr_test.go
+++ b/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
diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go
index 5f7f64423..c7b1eb19a 100644
--- a/vendor/github.com/miekg/dns/scan.go
+++ b/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
diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go
index b8b18fd77..824b9c949 100644
--- a/vendor/github.com/miekg/dns/scan_rr.go
+++ b/vendor/github.com/miekg/dns/scan_rr.go
@@ -130,9 +130,10 @@ func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 { // Dynamic updates.
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
rr.A = net.ParseIP(l.token)
if rr.A == nil || l.err {
return nil, &ParseError{f, "bad A A", l}, ""
@@ -145,9 +146,10 @@ func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
rr.AAAA = net.ParseIP(l.token)
if rr.AAAA == nil || l.err {
return nil, &ParseError{f, "bad AAAA AAAA", l}, ""
@@ -161,20 +163,15 @@ func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Ns = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Ns = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad NS Ns", l}, ""
}
- if rr.Ns[l.length-1] != '.' {
- rr.Ns = appendOrigin(rr.Ns, o)
- }
+ rr.Ns = name
return rr, nil, ""
}
@@ -187,17 +184,12 @@ func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- if l.token == "@" {
- rr.Ptr = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad PTR Ptr", l}, ""
}
- if rr.Ptr[l.length-1] != '.' {
- rr.Ptr = appendOrigin(rr.Ptr, o)
- }
+ rr.Ptr = name
return rr, nil, ""
}
@@ -207,20 +199,15 @@ func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string)
l := <-c
rr.Ptr = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Ptr = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad NSAP-PTR Ptr", l}, ""
}
- if rr.Ptr[l.length-1] != '.' {
- rr.Ptr = appendOrigin(rr.Ptr, o)
- }
+ rr.Ptr = name
return rr, nil, ""
}
@@ -230,34 +217,26 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Mbox = l.token
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- if l.token == "@" {
- rr.Mbox = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad RP Mbox", l}, ""
- }
- if rr.Mbox[l.length-1] != '.' {
- rr.Mbox = appendOrigin(rr.Mbox, o)
- }
+
+ mbox, mboxOk := toAbsoluteName(l.token, o)
+ if l.err || !mboxOk {
+ return nil, &ParseError{f, "bad RP Mbox", l}, ""
}
+ rr.Mbox = mbox
+
<-c // zBlank
l = <-c
rr.Txt = l.token
- if l.token == "@" {
- rr.Txt = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ txt, txtOk := toAbsoluteName(l.token, o)
+ if l.err || !txtOk {
return nil, &ParseError{f, "bad RP Txt", l}, ""
}
- if rr.Txt[l.length-1] != '.' {
- rr.Txt = appendOrigin(rr.Txt, o)
- }
+ rr.Txt = txt
+
return rr, nil, ""
}
@@ -267,20 +246,15 @@ func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Mr = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Mr = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MR Mr", l}, ""
}
- if rr.Mr[l.length-1] != '.' {
- rr.Mr = appendOrigin(rr.Mr, o)
- }
+ rr.Mr = name
return rr, nil, ""
}
@@ -290,20 +264,15 @@ func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Mb = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Mb = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MB Mb", l}, ""
}
- if rr.Mb[l.length-1] != '.' {
- rr.Mb = appendOrigin(rr.Mb, o)
- }
+ rr.Mb = name
return rr, nil, ""
}
@@ -313,20 +282,15 @@ func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Mg = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Mg = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MG Mg", l}, ""
}
- if rr.Mg[l.length-1] != '.' {
- rr.Mg = appendOrigin(rr.Mg, o)
- }
+ rr.Mg = name
return rr, nil, ""
}
@@ -362,34 +326,26 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Rmail = l.token
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- if l.token == "@" {
- rr.Rmail = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
- }
- if rr.Rmail[l.length-1] != '.' {
- rr.Rmail = appendOrigin(rr.Rmail, o)
- }
+
+ rmail, rmailOk := toAbsoluteName(l.token, o)
+ if l.err || !rmailOk {
+ return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
}
+ rr.Rmail = rmail
+
<-c // zBlank
l = <-c
rr.Email = l.token
- if l.token == "@" {
- rr.Email = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ email, emailOk := toAbsoluteName(l.token, o)
+ if l.err || !emailOk {
return nil, &ParseError{f, "bad MINFO Email", l}, ""
}
- if rr.Email[l.length-1] != '.' {
- rr.Email = appendOrigin(rr.Email, o)
- }
+ rr.Email = email
+
return rr, nil, ""
}
@@ -399,20 +355,15 @@ func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Mf = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Mf = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MF Mf", l}, ""
}
- if rr.Mf[l.length-1] != '.' {
- rr.Mf = appendOrigin(rr.Mf, o)
- }
+ rr.Mf = name
return rr, nil, ""
}
@@ -422,20 +373,15 @@ func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Md = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Md = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MD Md", l}, ""
}
- if rr.Md[l.length-1] != '.' {
- rr.Md = appendOrigin(rr.Md, o)
- }
+ rr.Md = name
return rr, nil, ""
}
@@ -444,57 +390,54 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad MX Pref", l}, ""
}
rr.Preference = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Mx = l.token
- if l.token == "@" {
- rr.Mx = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad MX Mx", l}, ""
}
- if rr.Mx[l.length-1] != '.' {
- rr.Mx = appendOrigin(rr.Mx, o)
- }
+ rr.Mx = name
+
return rr, nil, ""
}
func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(RT)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil {
return nil, &ParseError{f, "bad RT Preference", l}, ""
}
rr.Preference = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Host = l.token
- if l.token == "@" {
- rr.Host = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad RT Host", l}, ""
}
- if rr.Host[l.length-1] != '.' {
- rr.Host = appendOrigin(rr.Host, o)
- }
+ rr.Host = name
+
return rr, nil, ""
}
@@ -503,28 +446,25 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
}
rr.Subtype = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Hostname = l.token
- if l.token == "@" {
- rr.Hostname = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad AFSDB Hostname", l}, ""
}
- if rr.Hostname[l.length-1] != '.' {
- rr.Hostname = appendOrigin(rr.Hostname, o)
- }
+ rr.Hostname = name
return rr, nil, ""
}
@@ -533,9 +473,10 @@ func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
if l.err {
return nil, &ParseError{f, "bad X25 PSDNAddress", l}, ""
}
@@ -548,28 +489,25 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad KX Pref", l}, ""
}
rr.Preference = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Exchanger = l.token
- if l.token == "@" {
- rr.Exchanger = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad KX Exchanger", l}, ""
}
- if rr.Exchanger[l.length-1] != '.' {
- rr.Exchanger = appendOrigin(rr.Exchanger, o)
- }
+ rr.Exchanger = name
return rr, nil, ""
}
@@ -579,20 +517,15 @@ func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Target = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Target = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad CNAME Target", l}, ""
}
- if rr.Target[l.length-1] != '.' {
- rr.Target = appendOrigin(rr.Target, o)
- }
+ rr.Target = name
return rr, nil, ""
}
@@ -602,20 +535,15 @@ func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Target = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Target = o
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad CNAME Target", l}, ""
- }
- if rr.Target[l.length-1] != '.' {
- rr.Target = appendOrigin(rr.Target, o)
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad DNAME Target", l}, ""
}
+ rr.Target = name
return rr, nil, ""
}
@@ -625,35 +553,26 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.Ns = l.token
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- <-c // zBlank
- if l.token == "@" {
- rr.Ns = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad SOA Ns", l}, ""
- }
- if rr.Ns[l.length-1] != '.' {
- rr.Ns = appendOrigin(rr.Ns, o)
- }
+
+ ns, nsOk := toAbsoluteName(l.token, o)
+ if l.err || !nsOk {
+ return nil, &ParseError{f, "bad SOA Ns", l}, ""
}
+ rr.Ns = ns
+ <-c // zBlank
l = <-c
rr.Mbox = l.token
- if l.token == "@" {
- rr.Mbox = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad SOA Mbox", l}, ""
- }
- if rr.Mbox[l.length-1] != '.' {
- rr.Mbox = appendOrigin(rr.Mbox, o)
- }
+
+ mbox, mboxOk := toAbsoluteName(l.token, o)
+ if l.err || !mboxOk {
+ return nil, &ParseError{f, "bad SOA Mbox", l}, ""
}
+ rr.Mbox = mbox
+
<-c // zBlank
var (
@@ -667,9 +586,10 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
}
if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
if i == 0 {
- // Serial should be a number
+ // Serial must be a number
return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
}
+ // We allow other fields to be unitful duration strings
if v, ok = stringToTtl(l.token); !ok {
return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
@@ -702,14 +622,16 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad SRV Priority", l}, ""
}
rr.Priority = uint16(i)
+
<-c // zBlank
l = <-c // zString
i, e = strconv.ParseUint(l.token, 10, 16)
@@ -717,6 +639,7 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad SRV Weight", l}, ""
}
rr.Weight = uint16(i)
+
<-c // zBlank
l = <-c // zString
i, e = strconv.ParseUint(l.token, 10, 16)
@@ -724,20 +647,16 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad SRV Port", l}, ""
}
rr.Port = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Target = l.token
- if l.token == "@" {
- rr.Target = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad SRV Target", l}, ""
}
- if rr.Target[l.length-1] != '.' {
- rr.Target = appendOrigin(rr.Target, o)
- }
+ rr.Target = name
return rr, nil, ""
}
@@ -746,14 +665,16 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NAPTR Order", l}, ""
}
rr.Order = uint16(i)
+
<-c // zBlank
l = <-c // zString
i, e = strconv.ParseUint(l.token, 10, 16)
@@ -761,6 +682,7 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad NAPTR Preference", l}, ""
}
rr.Preference = uint16(i)
+
// Flags
<-c // zBlank
l = <-c // _QUOTE
@@ -817,21 +739,17 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
} else {
return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
}
+
// After quote no space??
<-c // zBlank
l = <-c // zString
rr.Replacement = l.token
- if l.token == "@" {
- rr.Replacement = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad NAPTR Replacement", l}, ""
}
- if rr.Replacement[l.length-1] != '.' {
- rr.Replacement = appendOrigin(rr.Replacement, o)
- }
+ rr.Replacement = name
return rr, nil, ""
}
@@ -841,34 +759,26 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.PreviousName = l.token
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
- if l.token == "@" {
- rr.PreviousName = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
- }
- if rr.PreviousName[l.length-1] != '.' {
- rr.PreviousName = appendOrigin(rr.PreviousName, o)
- }
+
+ previousName, previousNameOk := toAbsoluteName(l.token, o)
+ if l.err || !previousNameOk {
+ return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
}
+ rr.PreviousName = previousName
+
<-c // zBlank
l = <-c
rr.NextName = l.token
- if l.token == "@" {
- rr.NextName = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+
+ nextName, nextNameOk := toAbsoluteName(l.token, o)
+ if l.err || !nextNameOk {
return nil, &ParseError{f, "bad TALINK NextName", l}, ""
}
- if rr.NextName[l.length-1] != '.' {
- rr.NextName = appendOrigin(rr.NextName, o)
- }
+ rr.NextName = nextName
+
return rr, nil, ""
}
@@ -880,9 +790,10 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.VertPre = 162 // 10
rr.Size = 18 // 1
ok := false
+
// North
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
i, e := strconv.ParseUint(l.token, 10, 32)
@@ -1013,14 +924,16 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
// HitLength is not represented
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l}, ""
}
rr.PublicKeyAlgorithm = uint8(i)
+
<-c // zBlank
l = <-c // zString
if l.length == 0 || l.err {
@@ -1043,19 +956,11 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
- if l.token == "@" {
- xs = append(xs, o)
- l = <-c
- continue
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
}
- if l.token[l.length-1] != '.' {
- l.token = appendOrigin(l.token, o)
- }
- xs = append(xs, l.token)
+ xs = append(xs, name)
case zBlank:
// Ok
default:
@@ -1072,9 +977,10 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
if v, ok := StringToCertType[l.token]; ok {
rr.Type = v
} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
@@ -1129,10 +1035,12 @@ func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(RRSIG)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
if t, ok := StringToType[l.tokenUpper]; !ok {
if strings.HasPrefix(l.tokenUpper, "TYPE") {
t, ok = typeToInt(l.tokenUpper)
@@ -1146,6 +1054,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
} else {
rr.TypeCovered = t
}
+
<-c // zBlank
l = <-c
i, err := strconv.ParseUint(l.token, 10, 8)
@@ -1153,6 +1062,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad RRSIG Algorithm", l}, ""
}
rr.Algorithm = uint8(i)
+
<-c // zBlank
l = <-c
i, err = strconv.ParseUint(l.token, 10, 8)
@@ -1160,6 +1070,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad RRSIG Labels", l}, ""
}
rr.Labels = uint8(i)
+
<-c // zBlank
l = <-c
i, err = strconv.ParseUint(l.token, 10, 32)
@@ -1167,6 +1078,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, ""
}
rr.OrigTtl = uint32(i)
+
<-c // zBlank
l = <-c
if i, err := StringToTime(l.token); err != nil {
@@ -1180,6 +1092,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
} else {
rr.Expiration = i
}
+
<-c // zBlank
l = <-c
if i, err := StringToTime(l.token); err != nil {
@@ -1191,6 +1104,7 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
} else {
rr.Inception = i
}
+
<-c // zBlank
l = <-c
i, err = strconv.ParseUint(l.token, 10, 16)
@@ -1198,25 +1112,22 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return nil, &ParseError{f, "bad RRSIG KeyTag", l}, ""
}
rr.KeyTag = uint16(i)
+
<-c // zBlank
l = <-c
rr.SignerName = l.token
- if l.token == "@" {
- rr.SignerName = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
- }
- if rr.SignerName[l.length-1] != '.' {
- rr.SignerName = appendOrigin(rr.SignerName, o)
- }
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
}
+ rr.SignerName = name
+
s, e, c1 := endingToString(c, "bad RRSIG Signature", f)
if e != nil {
return nil, e, c1
}
rr.Signature = s
+
return rr, nil, c1
}
@@ -1226,20 +1137,15 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
l := <-c
rr.NextDomain = l.token
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
- if l.token == "@" {
- rr.NextDomain = o
- } else {
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
- return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
- }
- if rr.NextDomain[l.length-1] != '.' {
- rr.NextDomain = appendOrigin(rr.NextDomain, o)
- }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
}
+ rr.NextDomain = name
rr.TypeBitMap = make([]uint16, 0)
var (
@@ -1271,9 +1177,10 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3 Hash", l}, ""
@@ -1339,9 +1246,10 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, ""
@@ -1373,9 +1281,10 @@ func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
if l.length != 17 || l.err {
return nil, &ParseError{f, "bad EUI48 Address", l}, ""
}
@@ -1405,9 +1314,10 @@ func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
if l.length != 23 || l.err {
return nil, &ParseError{f, "bad EUI64 Address", l}, ""
}
@@ -1437,9 +1347,10 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SSHFP Algorithm", l}, ""
@@ -1466,9 +1377,10 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " Flags", l}, ""
@@ -1522,9 +1434,10 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad RKEY Flags", l}, ""
@@ -1577,10 +1490,12 @@ func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(GPOS)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
_, e := strconv.ParseFloat(l.token, 64)
if e != nil || l.err {
return nil, &ParseError{f, "bad GPOS Longitude", l}, ""
@@ -1606,10 +1521,12 @@ func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
rr := new(DS)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, ""
@@ -1665,10 +1582,12 @@ func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(TA)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad TA KeyTag", l}, ""
@@ -1703,10 +1622,12 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(TLSA)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad TLSA Usage", l}, ""
@@ -1738,10 +1659,12 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(SMIMEA)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return nil, &ParseError{f, "bad SMIMEA Usage", l}, ""
@@ -1773,10 +1696,12 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(RFC3597)
rr.Hdr = h
+
l := <-c
if l.token != "\\#" {
return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
}
+
<-c // zBlank
l = <-c
rdlength, e := strconv.Atoi(l.token)
@@ -1850,7 +1775,7 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 { // Dynamic updates.
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
@@ -1897,9 +1822,10 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad NID Preference", l}, ""
@@ -1920,9 +1846,10 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad L32 Preference", l}, ""
@@ -1942,31 +1869,25 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad LP Preference", l}, ""
}
rr.Preference = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Fqdn = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Fqdn = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
return nil, &ParseError{f, "bad LP Fqdn", l}, ""
}
- if rr.Fqdn[l.length-1] != '.' {
- rr.Fqdn = appendOrigin(rr.Fqdn, o)
- }
+ rr.Fqdn = name
+
return rr, nil, ""
}
@@ -1975,9 +1896,10 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad L64 Preference", l}, ""
@@ -1996,10 +1918,12 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(UID)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad UID Uid", l}, ""
@@ -2011,10 +1935,12 @@ func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(GID)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return nil, &ParseError{f, "bad GID Gid", l}, ""
@@ -2026,6 +1952,7 @@ func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(UINFO)
rr.Hdr = h
+
s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
if e != nil {
return nil, e, c1
@@ -2042,55 +1969,46 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, ""
}
+
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return nil, &ParseError{f, "bad PX Preference", l}, ""
}
rr.Preference = uint16(i)
+
<-c // zBlank
l = <-c // zString
rr.Map822 = l.token
- if l.length == 0 {
- return rr, nil, ""
- }
- if l.token == "@" {
- rr.Map822 = o
- return rr, nil, ""
- }
- _, ok := IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+ map822, map822Ok := toAbsoluteName(l.token, o)
+ if l.err || !map822Ok {
return nil, &ParseError{f, "bad PX Map822", l}, ""
}
- if rr.Map822[l.length-1] != '.' {
- rr.Map822 = appendOrigin(rr.Map822, o)
- }
+ rr.Map822 = map822
+
<-c // zBlank
l = <-c // zString
rr.Mapx400 = l.token
- if l.token == "@" {
- rr.Mapx400 = o
- return rr, nil, ""
- }
- _, ok = IsDomainName(l.token)
- if !ok || l.length == 0 || l.err {
+ mapx400, mapx400Ok := toAbsoluteName(l.token, o)
+ if l.err || !mapx400Ok {
return nil, &ParseError{f, "bad PX Mapx400", l}, ""
}
- if rr.Mapx400[l.length-1] != '.' {
- rr.Mapx400 = appendOrigin(rr.Mapx400, o)
- }
+ rr.Mapx400 = mapx400
+
return rr, nil, ""
}
func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(CAA)
rr.Hdr = h
+
l := <-c
- if l.length == 0 {
+ if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
+
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad CAA Flag", l}, ""
diff --git a/vendor/github.com/miekg/dns/scan_test.go b/vendor/github.com/miekg/dns/scan_test.go
index b31c4c779..e43ad4478 100644
--- a/vendor/github.com/miekg/dns/scan_test.go
+++ b/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())
diff --git a/vendor/github.com/miekg/dns/server_test.go b/vendor/github.com/miekg/dns/server_test.go
index f17a2f90f..b74f2f1a8 100644
--- a/vendor/github.com/miekg/dns/server_test.go
+++ b/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)
diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go
index af111b9a8..12a209678 100644
--- a/vendor/github.com/miekg/dns/udp.go
+++ b/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)
+}
diff --git a/vendor/github.com/miekg/dns/udp_linux.go b/vendor/github.com/miekg/dns/udp_linux.go
index 033df4239..13747ed34 100644
--- a/vendor/github.com/miekg/dns/udp_linux.go
+++ b/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
+}
diff --git a/vendor/github.com/miekg/dns/udp_linux_test.go b/vendor/github.com/miekg/dns/udp_linux_test.go
new file mode 100644
index 000000000..14a8acefd
--- /dev/null
+++ b/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)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/udp_other.go b/vendor/github.com/miekg/dns/udp_other.go
index 488a282b2..531f4ebcc 100644
--- a/vendor/github.com/miekg/dns/udp_other.go
+++ b/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 }
diff --git a/vendor/github.com/miekg/dns/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go
index 51e532ac2..2ad4ede7f 100644
--- a/vendor/github.com/miekg/dns/udp_windows.go
+++ b/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
}
-