Rebuild vendor

This commit is contained in:
Paul Querna 2019-05-07 09:42:52 -07:00
parent 9a3a9fc4a0
commit 5785bb4620
No known key found for this signature in database
GPG Key ID: E6B265F073D7A8CB
304 changed files with 5577 additions and 24832 deletions

View File

@ -1,8 +0,0 @@
coverage:
status:
project:
default:
target: 40%
threshold: null
patch: false
changes: false

View File

@ -1,19 +1,20 @@
language: go language: go
sudo: false sudo: false
go: go:
- 1.10.x - 1.9.x
- 1.11.x
- 1.12.x
- tip - tip
env:
- TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic"
- TESTS="-race -v ./..."
before_install: before_install:
# don't use the miekg/dns when testing forks # don't use the miekg/dns when testing forks
- mkdir -p $GOPATH/src/github.com/miekg - mkdir -p $GOPATH/src/github.com/miekg
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true - ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
script: script:
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./... - go test $TESTS
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)

View File

@ -3,55 +3,13 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = [ packages = ["ed25519","ed25519/internal/edwards25519"]
"ed25519", revision = "b080dc9a8c480b08e698fb1219160d598526310f"
"ed25519/internal/edwards25519",
]
pruneopts = ""
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
[[projects]]
branch = "master"
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
name = "golang.org/x/net"
packages = [
"bpf",
"context",
"internal/iana",
"internal/socket",
"ipv4",
"ipv6",
]
pruneopts = ""
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
[[projects]]
branch = "master"
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
name = "golang.org/x/sync"
packages = ["errgroup"]
pruneopts = ""
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
branch = "master"
digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = ""
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
input-imports = [ inputs-digest = "5046e265393bd5e54f570ce29ae8bc6fa3f30ef5110e922996540400f287c64a"
"golang.org/x/crypto/ed25519",
"golang.org/x/net/ipv4",
"golang.org/x/net/ipv6",
"golang.org/x/sync/errgroup",
"golang.org/x/sys/unix",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -24,15 +24,3 @@
[[constraint]] [[constraint]]
branch = "master" branch = "master"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[[constraint]]
branch = "master"
name = "golang.org/x/sys"
[[constraint]]
branch = "master"
name = "golang.org/x/sync"

View File

@ -1,52 +0,0 @@
# Makefile for releasing.
#
# The release is controlled from version.go. The version found there is
# used to tag the git repo, we're not building any artifects so there is nothing
# to upload to github.
#
# * Up the version in version.go
# * Run: make -f Makefile.release release
# * will *commit* your change with 'Release $VERSION'
# * push to github
#
define GO
//+build ignore
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
fmt.Println(dns.Version.String())
}
endef
$(file > version_release.go,$(GO))
VERSION:=$(shell go run version_release.go)
TAG="v$(VERSION)"
all:
@echo Use the \'release\' target to start a release $(VERSION)
rm -f version_release.go
.PHONY: release
release: commit push
@echo Released $(VERSION)
rm -f version_release.go
.PHONY: commit
commit:
@echo Committing release $(VERSION)
git commit -am"Release $(VERSION)"
git tag $(TAG)
.PHONY: push
push:
@echo Pushing release $(VERSION) to master
git push --tags
git push

View File

@ -7,10 +7,10 @@
> Less is more. > Less is more.
Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types. Complete and usable DNS library. All widely used Resource Records are supported, including the
It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS
isn't a convenience function for it. Server side and client side programming is supported, i.e. you programmer there isn't a convenience function for it. Server side and client side programming is
can build servers and resolvers with it. supported, i.e. you can build servers and resolvers with it.
We try to keep the "master" branch as sane as possible and at the bleeding edge of standards, We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
avoiding breaking changes wherever reasonable. We support the last two versions of Go. avoiding breaking changes wherever reasonable. We support the last two versions of Go.
@ -42,9 +42,10 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/tianon/rawdns * https://github.com/tianon/rawdns
* https://mesosphere.github.io/mesos-dns/ * https://mesosphere.github.io/mesos-dns/
* https://pulse.turbobytes.com/ * https://pulse.turbobytes.com/
* https://play.google.com/store/apps/details?id=com.turbobytes.dig
* https://github.com/fcambus/statzone * https://github.com/fcambus/statzone
* https://github.com/benschw/dns-clb-go * https://github.com/benschw/dns-clb-go
* https://github.com/corny/dnscheck for <http://public-dns.info/> * https://github.com/corny/dnscheck for http://public-dns.info/
* https://namesmith.io * https://namesmith.io
* https://github.com/miekg/unbound * https://github.com/miekg/unbound
* https://github.com/miekg/exdns * https://github.com/miekg/exdns
@ -55,41 +56,35 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/bamarni/dockness * https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns * https://github.com/fffaraz/microdns
* http://kelda.io * http://kelda.io
* https://github.com/ipdcode/hades <https://jd.com> * https://github.com/ipdcode/hades (JD.COM)
* https://github.com/StackExchange/dnscontrol/ * https://github.com/StackExchange/dnscontrol/
* https://www.dnsperf.com/ * https://www.dnsperf.com/
* https://dnssectest.net/ * https://dnssectest.net/
* https://dns.apebits.com * https://dns.apebits.com
* https://github.com/oif/apex * https://github.com/oif/apex
* https://github.com/jedisct1/dnscrypt-proxy
* https://github.com/jedisct1/rpdns
* https://github.com/xor-gate/sshfp
* https://github.com/rs/dnstrace
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
* https://github.com/semihalev/sdns
* https://render.com
* https://github.com/peterzen/goresolver
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
# Features # Features
* UDP/TCP queries, IPv4 and IPv6 * UDP/TCP queries, IPv4 and IPv6;
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported * RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
* Fast * Fast:
* Server side programming (mimicking the net/http package) * Reply speed around ~ 80K qps (faster hardware results in more qps);
* Client side programming * Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519 * Server side programming (mimicking the net/http package);
* EDNS0, NSID, Cookies * Client side programming;
* AXFR/IXFR * DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
* TSIG, SIG(0) * EDNS0, NSID, Cookies;
* DNS over TLS (DoT): encrypted connection between client and server over TCP * AXFR/IXFR;
* DNS name compression * TSIG, SIG(0);
* DNS over TLS: optional encrypted connection between client and server;
* DNS name compression;
* Depends only on the standard library.
Have fun! Have fun!
Miek Gieben - 2010-2012 - <miek@miek.nl> Miek Gieben - 2010-2012 - <miek@miek.nl>
DNS Authors 2012-
# Building # Building
@ -101,8 +96,8 @@ work:
## Examples ## Examples
A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc A short "how to use the API" is at the beginning of doc.go (this also will show
github.com/miekg/dns`). when you call `godoc github.com/miekg/dns`).
Example programs can be found in the `github.com/miekg/exdns` repository. Example programs can be found in the `github.com/miekg/exdns` repository.
@ -160,13 +155,12 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 7553 - URI record * 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations * 7858 - DNS over TLS: Initiation and Performance Considerations
* 7871 - EDNS0 Client Subnet * 7871 - EDNS0 Client Subnet
* 7873 - Domain Name System (DNS) Cookies * 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
* 8080 - EdDSA for DNSSEC * 8080 - EdDSA for DNSSEC
* 8499 - DNS Terminology
## Loosely Based Upon ## Loosely based upon
* ldns - <https://nlnetlabs.nl/projects/ldns/about/> * `ldns`
* NSD - <https://nlnetlabs.nl/projects/nsd/about/> * `NSD`
* Net::DNS - <http://www.net-dns.org/> * `Net::DNS`
* GRONG - <https://github.com/bortzmeyer/grong> * `GRONG`

View File

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

216
vendor/github.com/miekg/dns/client.go generated vendored
View File

@ -3,26 +3,26 @@ package dns
// A client implementation. // A client implementation.
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"net" "net"
"strings" "strings"
"time" "time"
) )
const ( const dnsTimeout time.Duration = 2 * time.Second
dnsTimeout time.Duration = 2 * time.Second const tcpIdleTimeout time.Duration = 8 * time.Second
tcpIdleTimeout time.Duration = 8 * time.Second
)
// A Conn represents a connection to a DNS server. // A Conn represents a connection to a DNS server.
type Conn struct { type Conn struct {
net.Conn // a net.Conn holding the connection net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messages UDPSize uint16 // minimum receive buffer for UDP messages
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
rtt time.Duration
t time.Time
tsigRequestMAC string tsigRequestMAC string
} }
@ -83,22 +83,33 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// create a new dialer with the appropriate timeout // create a new dialer with the appropriate timeout
var d net.Dialer var d net.Dialer
if c.Dialer == nil { if c.Dialer == nil {
d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())} d = net.Dialer{}
} else { } else {
d = *c.Dialer d = net.Dialer(*c.Dialer)
} }
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
network := c.Net network := "udp"
if network == "" { useTLS := false
network = "udp"
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
}
} }
useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
conn = new(Conn) conn = new(Conn)
if useTLS { if useTLS {
network = strings.TrimSuffix(network, "-tls")
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig) conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
} else { } else {
conn.Conn, err = d.Dial(network, address) conn.Conn, err = d.Dial(network, address)
@ -106,7 +117,6 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return conn, nil return conn, nil
} }
@ -129,15 +139,20 @@ func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, er
return c.exchange(m, address) return c.exchange(m, address)
} }
q := m.Question[0] t := "nop"
key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass) if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) { t = t1
}
cl := "nop"
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
cl = cl1
}
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
return c.exchange(m, address) return c.exchange(m, address)
}) })
if r != nil && shared { if r != nil && shared {
r = r.Copy() r = r.Copy()
} }
return r, rtt, err return r, rtt, err
} }
@ -162,9 +177,8 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
} }
co.TsigSecret = c.TsigSecret co.TsigSecret = c.TsigSecret
t := time.Now()
// write with the appropriate write timeout // write with the appropriate write timeout
co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout()))) co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
if err = co.WriteMsg(m); err != nil { if err = co.WriteMsg(m); err != nil {
return nil, 0, err return nil, 0, err
} }
@ -174,15 +188,12 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
if err == nil && r.Id != m.Id { if err == nil && r.Id != m.Id {
err = ErrId err = ErrId
} }
rtt = time.Since(t) return r, co.rtt, err
return r, rtt, err
} }
// ReadMsg reads a message from the connection co. // ReadMsg reads a message from the connection co.
// If the received message contains a TSIG record the transaction signature // If the received message contains a TSIG record the transaction
// is verified. This method always tries to return the message, however if an // signature is verified.
// error is returned there are no guarantees that the returned message is a
// valid representation of the packet read.
func (co *Conn) ReadMsg() (*Msg, error) { func (co *Conn) ReadMsg() (*Msg, error) {
p, err := co.ReadMsgHeader(nil) p, err := co.ReadMsgHeader(nil)
if err != nil { if err != nil {
@ -191,10 +202,13 @@ func (co *Conn) ReadMsg() (*Msg, error) {
m := new(Msg) m := new(Msg)
if err := m.Unpack(p); err != nil { if err := m.Unpack(p); err != nil {
// If an error was returned, we still want to allow the user to use // If ErrTruncated was returned, we still want to allow the user to use
// the message, but naively they can just check err if they don't want // the message, but naively they can just check err if they don't want
// to use an erroneous message // to use a truncated message
return m, err if err == ErrTruncated {
return m, err
}
return nil, err
} }
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok { if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
@ -215,15 +229,19 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
n int n int
err error err error
) )
switch co.Conn.(type) {
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn: case *net.TCPConn, *tls.Conn:
var length uint16 r := t.(io.Reader)
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
// First two bytes specify the length of the entire message.
l, err := tcpMsgLen(r)
if err != nil {
return nil, err return nil, err
} }
p = make([]byte, l)
p = make([]byte, length) n, err = tcpRead(r, p)
n, err = io.ReadFull(co.Conn, p) co.rtt = time.Since(co.t)
default: default:
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
@ -231,6 +249,7 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
co.rtt = time.Since(co.t)
} }
if err != nil { if err != nil {
@ -250,27 +269,78 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
return p, err return p, err
} }
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
func tcpMsgLen(t io.Reader) (int, error) {
p := []byte{0, 0}
n, err := t.Read(p)
if err != nil {
return 0, err
}
// As seen with my local router/switch, returns 1 byte on the above read,
// resulting a a ShortRead. Just write it out (instead of loop) and read the
// other byte.
if n == 1 {
n1, err := t.Read(p[1:])
if err != nil {
return 0, err
}
n += n1
}
if n != 2 {
return 0, ErrShortRead
}
l := binary.BigEndian.Uint16(p)
if l == 0 {
return 0, ErrShortRead
}
return int(l), nil
}
// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
func tcpRead(t io.Reader, p []byte) (int, error) {
n, err := t.Read(p)
if err != nil {
return n, err
}
for n < len(p) {
j, err := t.Read(p[n:])
if err != nil {
return n, err
}
n += j
}
return n, err
}
// Read implements the net.Conn read method. // Read implements the net.Conn read method.
func (co *Conn) Read(p []byte) (n int, err error) { func (co *Conn) Read(p []byte) (n int, err error) {
if co.Conn == nil { if co.Conn == nil {
return 0, ErrConnEmpty return 0, ErrConnEmpty
} }
if len(p) < 2 {
switch co.Conn.(type) { return 0, io.ErrShortBuffer
}
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn: case *net.TCPConn, *tls.Conn:
var length uint16 r := t.(io.Reader)
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
l, err := tcpMsgLen(r)
if err != nil {
return 0, err return 0, err
} }
if int(length) > len(p) { if l > len(p) {
return 0, io.ErrShortBuffer return int(l), io.ErrShortBuffer
} }
return tcpRead(r, p[:l])
return io.ReadFull(co.Conn, p[:length])
} }
// UDP connection // UDP connection
return co.Conn.Read(p) n, err = co.Conn.Read(p)
if err != nil {
return n, err
}
return n, err
} }
// WriteMsg sends a message through the connection co. // WriteMsg sends a message through the connection co.
@ -292,26 +362,34 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
if err != nil { if err != nil {
return err return err
} }
_, err = co.Write(out) co.t = time.Now()
return err if _, err = co.Write(out); err != nil {
return err
}
return nil
} }
// Write implements the net.Conn Write method. // Write implements the net.Conn Write method.
func (co *Conn) Write(p []byte) (n int, err error) { func (co *Conn) Write(p []byte) (n int, err error) {
switch co.Conn.(type) { switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn: case *net.TCPConn, *tls.Conn:
if len(p) > MaxMsgSize { w := t.(io.Writer)
lp := len(p)
if lp < 2 {
return 0, io.ErrShortBuffer
}
if lp > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, lp+2)
l := make([]byte, 2) binary.BigEndian.PutUint16(l, uint16(lp))
binary.BigEndian.PutUint16(l, uint16(len(p))) p = append(l, p...)
n, err := io.Copy(w, bytes.NewReader(p))
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
return int(n), err return int(n), err
} }
n, err = co.Conn.Write(p)
return co.Conn.Write(p) return n, err
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
@ -354,7 +432,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
// ExchangeConn performs a synchronous query. It sends the message m via the connection // 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. // c and waits for a reply. The connection c is not closed by ExchangeConn.
// Deprecated: This function is going away, but can easily be mimicked: // This function is going away, but can easily be mimicked:
// //
// co := &dns.Conn{Conn: c} // c is your net.Conn // co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m) // co.WriteMsg(m)
@ -378,7 +456,11 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
// DialTimeout acts like Dial but takes a timeout. // DialTimeout acts like Dial but takes a timeout.
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) { func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}} client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
return client.Dial(address) conn, err = client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// DialWithTLS connects to the address on the named network with TLS. // DialWithTLS connects to the address on the named network with TLS.
@ -387,7 +469,12 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
network += "-tls" network += "-tls"
} }
client := Client{Net: network, TLSConfig: tlsConfig} client := Client{Net: network, TLSConfig: tlsConfig}
return client.Dial(address) conn, err = client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout. // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
@ -396,7 +483,11 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
network += "-tls" network += "-tls"
} }
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig} client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
return client.Dial(address) conn, err = client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// ExchangeContext acts like Exchange, but honors the deadline on the provided // ExchangeContext acts like Exchange, but honors the deadline on the provided
@ -407,11 +498,10 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg,
if deadline, ok := ctx.Deadline(); !ok { if deadline, ok := ctx.Deadline(); !ok {
timeout = 0 timeout = 0
} else { } else {
timeout = time.Until(deadline) timeout = deadline.Sub(time.Now())
} }
// not passing the context to the underlying calls, as the API does not support // 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. // context. For timeouts you should set up Client.Dialer and call Client.Exchange.
// TODO(tmthrgd,miekg): this is a race condition.
c.Dialer = &net.Dialer{Timeout: timeout} c.Dialer = &net.Dialer{Timeout: timeout}
return c.Exchange(m, a) return c.Exchange(m, a)
} }

View File

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

189
vendor/github.com/miekg/dns/compress_generate.go generated vendored Normal file
View File

@ -0,0 +1,189 @@
//+build ignore
// compression_generate.go is meant to run with go generate. It will use
// go/{importer,types} to track down all the RR struct types. Then for each type
// it will look to see if there are (compressible) names, if so it will add that
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
// compression so that Len() is fast.
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/types"
"log"
"os"
)
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from compress_generate.go
package dns
`
// getTypeStruct will take a type and the package scope, and return the
// (innermost) struct if the type is considered a RR type (currently defined as
// those structs beginning with a RR_Header, could be redefined as implementing
// the RR interface). The bool return value indicates if embedded structs were
// resolved.
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
st, ok := t.Underlying().(*types.Struct)
if !ok {
return nil, false
}
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
return st, false
}
if st.Field(0).Anonymous() {
st, _ := getTypeStruct(st.Field(0).Type(), scope)
return st, true
}
return nil, false
}
func main() {
// Import and type-check the package
pkg, err := importer.Default().Import("github.com/miekg/dns")
fatalIfErr(err)
scope := pkg.Scope()
var domainTypes []string // Types that have a domain name in them (either compressible or not).
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
Names:
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
st, _ := getTypeStruct(o.Type(), scope)
if st == nil {
continue
}
if name == "PrivateRR" {
continue
}
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
log.Fatalf("Constant Type%s does not exist.", o.Name())
}
for i := 1; i < st.NumFields(); i++ {
if _, ok := st.Field(i).Type().(*types.Slice); ok {
if st.Tag(i) == `dns:"domain-name"` {
domainTypes = append(domainTypes, o.Name())
continue Names
}
if st.Tag(i) == `dns:"cdomain-name"` {
cdomainTypes = append(cdomainTypes, o.Name())
domainTypes = append(domainTypes, o.Name())
continue Names
}
continue
}
switch {
case st.Tag(i) == `dns:"domain-name"`:
domainTypes = append(domainTypes, o.Name())
continue Names
case st.Tag(i) == `dns:"cdomain-name"`:
cdomainTypes = append(cdomainTypes, o.Name())
domainTypes = append(domainTypes, o.Name())
continue Names
}
}
}
b := &bytes.Buffer{}
b.WriteString(packageHdr)
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n")
for _, name := range domainTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "case *%s:\n", name)
for i := 1; i < st.NumFields(); i++ {
out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
if _, ok := st.Field(i).Type().(*types.Slice); ok {
switch st.Tag(i) {
case `dns:"domain-name"`:
fallthrough
case `dns:"cdomain-name"`:
// For HIP we need to slice over the elements in this slice.
fmt.Fprintf(b, `for i := range x.%s {
compressionLenHelper(c, x.%s[i])
}
`, st.Field(i).Name(), st.Field(i).Name())
}
continue
}
switch {
case st.Tag(i) == `dns:"cdomain-name"`:
fallthrough
case st.Tag(i) == `dns:"domain-name"`:
out(st.Field(i).Name())
}
}
}
fmt.Fprintln(b, "}\n}\n\n")
// compressionLenSearchType - search cdomain-tags types for compressible names.
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n")
for _, name := range cdomainTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "case *%s:\n", name)
j := 1
for i := 1; i < st.NumFields(); i++ {
out := func(s string, j int) {
fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
}
// There are no slice types with names that can be compressed.
switch {
case st.Tag(i) == `dns:"cdomain-name"`:
out(st.Field(i).Name(), j)
j++
}
}
k := "k1"
ok := "ok1"
for i := 2; i < j; i++ {
k += fmt.Sprintf(" + k%d", i)
ok += fmt.Sprintf(" && ok%d", i)
}
fmt.Fprintf(b, "return %s, %s\n", k, ok)
}
fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
// gofmt
res, err := format.Source(b.Bytes())
if err != nil {
b.WriteTo(os.Stderr)
log.Fatal(err)
}
f, err := os.Create("zcompress.go")
fatalIfErr(err)
defer f.Close()
f.Write(res)
}
func fatalIfErr(err error) {
if err != nil {
log.Fatal(err)
}
}

View File

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

71
vendor/github.com/miekg/dns/dns.go generated vendored
View File

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

103
vendor/github.com/miekg/dns/dnssec.go generated vendored
View File

@ -67,10 +67,12 @@ var AlgorithmToString = map[uint8]string{
PRIVATEOID: "PRIVATEOID", PRIVATEOID: "PRIVATEOID",
} }
// StringToAlgorithm is the reverse of AlgorithmToString.
var StringToAlgorithm = reverseInt8(AlgorithmToString)
// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's. // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
var AlgorithmToHash = map[uint8]crypto.Hash{ var AlgorithmToHash = map[uint8]crypto.Hash{
RSAMD5: crypto.MD5, // Deprecated in RFC 6725 RSAMD5: crypto.MD5, // Deprecated in RFC 6725
DSA: crypto.SHA1,
RSASHA1: crypto.SHA1, RSASHA1: crypto.SHA1,
RSASHA1NSEC3SHA1: crypto.SHA1, RSASHA1NSEC3SHA1: crypto.SHA1,
RSASHA256: crypto.SHA256, RSASHA256: crypto.SHA256,
@ -99,6 +101,9 @@ var HashToString = map[uint8]string{
SHA512: "SHA512", SHA512: "SHA512",
} }
// StringToHash is a map of names to hash IDs.
var StringToHash = reverseInt8(HashToString)
// DNSKEY flag values. // DNSKEY flag values.
const ( const (
SEP = 1 SEP = 1
@ -167,7 +172,7 @@ func (k *DNSKEY) KeyTag() uint16 {
keytag += int(v) << 8 keytag += int(v) << 8
} }
} }
keytag += keytag >> 16 & 0xFFFF keytag += (keytag >> 16) & 0xFFFF
keytag &= 0xFFFF keytag &= 0xFFFF
} }
return uint16(keytag) return uint16(keytag)
@ -234,7 +239,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record. // ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
c := &CDNSKEY{DNSKEY: *k} c := &CDNSKEY{DNSKEY: *k}
c.Hdr = k.Hdr c.Hdr = *k.Hdr.copyHeader()
c.Hdr.Rrtype = TypeCDNSKEY c.Hdr.Rrtype = TypeCDNSKEY
return c return c
} }
@ -242,7 +247,7 @@ func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
// ToCDS converts a DS record to a CDS record. // ToCDS converts a DS record to a CDS record.
func (d *DS) ToCDS() *CDS { func (d *DS) ToCDS() *CDS {
c := &CDS{DS: *d} c := &CDS{DS: *d}
c.Hdr = d.Hdr c.Hdr = *d.Hdr.copyHeader()
c.Hdr.Rrtype = TypeCDS c.Hdr.Rrtype = TypeCDS
return c return c
} }
@ -262,17 +267,16 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
return ErrKey return ErrKey
} }
h0 := rrset[0].Header()
rr.Hdr.Rrtype = TypeRRSIG rr.Hdr.Rrtype = TypeRRSIG
rr.Hdr.Name = h0.Name rr.Hdr.Name = rrset[0].Header().Name
rr.Hdr.Class = h0.Class rr.Hdr.Class = rrset[0].Header().Class
if rr.OrigTtl == 0 { // If set don't override if rr.OrigTtl == 0 { // If set don't override
rr.OrigTtl = h0.Ttl rr.OrigTtl = rrset[0].Header().Ttl
} }
rr.TypeCovered = h0.Rrtype rr.TypeCovered = rrset[0].Header().Rrtype
rr.Labels = uint8(CountLabel(h0.Name)) rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
if strings.HasPrefix(h0.Name, "*") { if strings.HasPrefix(rrset[0].Header().Name, "*") {
rr.Labels-- // wildcard, remove from label count rr.Labels-- // wildcard, remove from label count
} }
@ -396,7 +400,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if rr.Algorithm != k.Algorithm { if rr.Algorithm != k.Algorithm {
return ErrKey return ErrKey
} }
if !strings.EqualFold(rr.SignerName, k.Hdr.Name) { if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
return ErrKey return ErrKey
} }
if k.Protocol != 3 { if k.Protocol != 3 {
@ -406,7 +410,10 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
// IsRRset checked that we have at least one RR and that the RRs in // IsRRset checked that we have at least one RR and that the RRs in
// the set have consistent type, class, and name. Also check that type and // the set have consistent type, class, and name. Also check that type and
// class matches the RRSIG record. // class matches the RRSIG record.
if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered { if rrset[0].Header().Class != rr.Hdr.Class {
return ErrRRset
}
if rrset[0].Header().Rrtype != rr.TypeCovered {
return ErrRRset return ErrRRset
} }
@ -504,8 +511,8 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
} }
modi := (int64(rr.Inception) - utc) / year68 modi := (int64(rr.Inception) - utc) / year68
mode := (int64(rr.Expiration) - utc) / year68 mode := (int64(rr.Expiration) - utc) / year68
ti := int64(rr.Inception) + modi*year68 ti := int64(rr.Inception) + (modi * year68)
te := int64(rr.Expiration) + mode*year68 te := int64(rr.Expiration) + (mode * year68)
return ti <= utc && utc <= te return ti <= utc && utc <= te
} }
@ -525,11 +532,6 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
return nil return nil
} }
if len(keybuf) < 1+1+64 {
// Exponent must be at least 1 byte and modulus at least 64
return nil
}
// RFC 2537/3110, section 2. RSA Public KEY Resource Records // RFC 2537/3110, section 2. RSA Public KEY Resource Records
// Length is in the 0th byte, unless its zero, then it // Length is in the 0th byte, unless its zero, then it
// it in bytes 1 and 2 and its a 16 bit number // it in bytes 1 and 2 and its a 16 bit number
@ -539,35 +541,25 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
keyoff = 3 keyoff = 3
} }
if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
// Exponent larger than supported by the crypto package,
// empty, or contains prohibited leading zero.
return nil
}
modoff := keyoff + int(explen)
modlen := len(keybuf) - modoff
if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
// Modulus is too small, large, or contains prohibited leading zero.
return nil
}
pubkey := new(rsa.PublicKey) pubkey := new(rsa.PublicKey)
var expo uint64 pubkey.N = big.NewInt(0)
// The exponent of length explen is between keyoff and modoff. shift := uint64((explen - 1) * 8)
for _, v := range keybuf[keyoff:modoff] { expo := uint64(0)
expo <<= 8 for i := int(explen - 1); i > 0; i-- {
expo |= uint64(v) expo += uint64(keybuf[keyoff+i]) << shift
shift -= 8
} }
if expo > 1<<31-1 { // Remainder
// Larger exponent than supported by the crypto package. expo += uint64(keybuf[keyoff])
if expo > (2<<31)+1 {
// Larger expo than supported.
// println("dns: F5 primes (or larger) are not supported")
return nil return nil
} }
pubkey.E = int(expo) pubkey.E = int(expo)
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
return pubkey return pubkey
} }
@ -592,8 +584,10 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
return nil return nil
} }
} }
pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2]) pubkey.X = big.NewInt(0)
pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:]) pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
pubkey.Y = big.NewInt(0)
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
return pubkey return pubkey
} }
@ -614,10 +608,10 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
p, keybuf := keybuf[:size], keybuf[size:] p, keybuf := keybuf[:size], keybuf[size:]
g, y := keybuf[:size], keybuf[size:] g, y := keybuf[:size], keybuf[size:]
pubkey := new(dsa.PublicKey) pubkey := new(dsa.PublicKey)
pubkey.Parameters.Q = new(big.Int).SetBytes(q) pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
pubkey.Parameters.P = new(big.Int).SetBytes(p) pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
pubkey.Parameters.G = new(big.Int).SetBytes(g) pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
pubkey.Y = new(big.Int).SetBytes(y) pubkey.Y = big.NewInt(0).SetBytes(y)
return pubkey return pubkey
} }
@ -647,16 +641,15 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
wires := make(wireSlice, len(rrset)) wires := make(wireSlice, len(rrset))
for i, r := range rrset { for i, r := range rrset {
r1 := r.copy() r1 := r.copy()
h := r1.Header() r1.Header().Ttl = s.OrigTtl
h.Ttl = s.OrigTtl labels := SplitDomainName(r1.Header().Name)
labels := SplitDomainName(h.Name)
// 6.2. Canonical RR Form. (4) - wildcards // 6.2. Canonical RR Form. (4) - wildcards
if len(labels) > int(s.Labels) { if len(labels) > int(s.Labels) {
// Wildcard // Wildcard
h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
} }
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
h.Name = strings.ToLower(h.Name) r1.Header().Name = strings.ToLower(r1.Header().Name)
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase. // 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
@ -714,7 +707,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
x.Target = strings.ToLower(x.Target) x.Target = strings.ToLower(x.Target)
} }
// 6.2. Canonical RR Form. (5) - origTTL // 6.2. Canonical RR Form. (5) - origTTL
wire := make([]byte, Len(r1)+1) // +1 to be safe(r) wire := make([]byte, r1.len()+1) // +1 to be safe(r)
off, err1 := PackRR(r1, wire, 0, nil, false) off, err1 := PackRR(r1, wire, 0, nil, false)
if err1 != nil { if err1 != nil {
return nil, err1 return nil, err1

View File

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

View File

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

111
vendor/github.com/miekg/dns/doc.go generated vendored
View File

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

View File

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

View File

@ -1,144 +0,0 @@
//+build ignore
// types_generate.go is meant to run with go generate. It will use
// go/{importer,types} to track down all the RR struct types. Then for each type
// it will generate conversion tables (TypeToRR and TypeToString) and banal
// methods (len, Header, copy) based on the struct tags. The generated source is
// written to ztypes.go, and is meant to be checked into git.
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/types"
"log"
"os"
)
var packageHdr = `
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
package dns
`
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
st, ok := t.Underlying().(*types.Struct)
if !ok {
return nil, false
}
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
return st, false
}
if st.Field(0).Anonymous() {
st, _ := getTypeStruct(st.Field(0).Type(), scope)
return st, true
}
return nil, false
}
func main() {
// Import and type-check the package
pkg, err := importer.Default().Import("github.com/miekg/dns")
fatalIfErr(err)
scope := pkg.Scope()
// Collect actual types (*X)
var namedTypes []string
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
continue
}
if name == "PrivateRR" || name == "OPT" {
continue
}
namedTypes = append(namedTypes, o.Name())
}
b := &bytes.Buffer{}
b.WriteString(packageHdr)
// Generate the duplicate check for each type.
fmt.Fprint(b, "// isDuplicate() functions\n\n")
for _, name := range namedTypes {
o := scope.Lookup(name)
st, isEmbedded := getTypeStruct(o.Type(), scope)
if isEmbedded {
continue
}
fmt.Fprintf(b, "func (r1 *%s) isDuplicate(_r2 RR) bool {\n", name)
fmt.Fprintf(b, "r2, ok := _r2.(*%s)\n", name)
fmt.Fprint(b, "if !ok { return false }\n")
fmt.Fprint(b, "_ = r2\n")
for i := 1; i < st.NumFields(); i++ {
field := st.Field(i).Name()
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
// *indirectly* defined as a slice in the net package).
if _, ok := st.Field(i).Type().(*types.Slice); ok {
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
o3(`for i := 0; i < len(r1.%s); i++ {
if !isDuplicateName(r1.%s[i], r2.%s[i]) {
return false
}
}`)
continue
}
o3(`for i := 0; i < len(r1.%s); i++ {
if r1.%s[i] != r2.%s[i] {
return false
}
}`)
continue
}
switch st.Tag(i) {
case `dns:"-"`:
// ignored
case `dns:"a"`, `dns:"aaaa"`:
o2("if !r1.%s.Equal(r2.%s) {\nreturn false\n}")
case `dns:"cdomain-name"`, `dns:"domain-name"`:
o2("if !isDuplicateName(r1.%s, r2.%s) {\nreturn false\n}")
default:
o2("if r1.%s != r2.%s {\nreturn false\n}")
}
}
fmt.Fprintf(b, "return true\n}\n\n")
}
// gofmt
res, err := format.Source(b.Bytes())
if err != nil {
b.WriteTo(os.Stderr)
log.Fatal(err)
}
// write result
f, err := os.Create("zduplicate.go")
fatalIfErr(err)
defer f.Close()
f.Write(res)
}
func fatalIfErr(err error) {
if err != nil {
log.Fatal(err)
}
}

108
vendor/github.com/miekg/dns/edns.go generated vendored
View File

@ -78,44 +78,36 @@ func (rr *OPT) String() string {
return s return s
} }
func (rr *OPT) len(off int, compression map[string]struct{}) int { func (rr *OPT) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
for _, o := range rr.Option { for i := 0; i < len(rr.Option); i++ {
l += 4 // Account for 2-byte option code and 2-byte option length. l += 4 // Account for 2-byte option code and 2-byte option length.
lo, _ := o.pack() lo, _ := rr.Option[i].pack()
l += len(lo) l += len(lo)
} }
return l return l
} }
func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on OPT")
}
func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
// return the old value -> delete SetVersion? // return the old value -> delete SetVersion?
// Version returns the EDNS version used. Only zero is defined. // Version returns the EDNS version used. Only zero is defined.
func (rr *OPT) Version() uint8 { func (rr *OPT) Version() uint8 {
return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16) return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
} }
// SetVersion sets the version of EDNS. This is usually zero. // SetVersion sets the version of EDNS. This is usually zero.
func (rr *OPT) SetVersion(v uint8) { func (rr *OPT) SetVersion(v uint8) {
rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16 rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
} }
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL). // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
func (rr *OPT) ExtendedRcode() int { func (rr *OPT) ExtendedRcode() int {
return int(rr.Hdr.Ttl&0xFF000000>>24) << 4 return int((rr.Hdr.Ttl & 0xFF000000) >> 24)
} }
// SetExtendedRcode sets the EDNS extended RCODE field. // SetExtendedRcode sets the EDNS extended RCODE field.
// func (rr *OPT) SetExtendedRcode(v uint8) {
// If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0. rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24)
func (rr *OPT) SetExtendedRcode(v uint16) {
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
} }
// UDPSize returns the UDP buffer size. // UDPSize returns the UDP buffer size.
@ -159,8 +151,6 @@ type EDNS0 interface {
unpack([]byte) error unpack([]byte) error
// String returns the string representation of the option. // String returns the string representation of the option.
String() string String() string
// copy returns a deep-copy of the option.
copy() EDNS0
} }
// EDNS0_NSID option is used to retrieve a nameserver // EDNS0_NSID option is used to retrieve a nameserver
@ -191,8 +181,7 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
// Option implements the EDNS0 interface. // Option implements the EDNS0 interface.
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code. func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil } func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
func (e *EDNS0_NSID) String() string { return e.Nsid } func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
// an idea of where the client lives. See RFC 7871. It can then give back a different // an idea of where the client lives. See RFC 7871. It can then give back a different
@ -282,16 +271,22 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 { if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
return errors.New("dns: bad netmask") return errors.New("dns: bad netmask")
} }
addr := make(net.IP, net.IPv4len) addr := make([]byte, net.IPv4len)
copy(addr, b[4:]) for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
e.Address = addr.To16() addr[i] = b[4+i]
}
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
case 2: case 2:
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 { if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
return errors.New("dns: bad netmask") return errors.New("dns: bad netmask")
} }
addr := make(net.IP, net.IPv6len) addr := make([]byte, net.IPv6len)
copy(addr, b[4:]) for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
e.Address = addr addr[i] = b[4+i]
}
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
addr[11], addr[12], addr[13], addr[14], addr[15]}
default: default:
return errors.New("dns: bad address family") return errors.New("dns: bad address family")
} }
@ -310,16 +305,6 @@ func (e *EDNS0_SUBNET) String() (s string) {
return return
} }
func (e *EDNS0_SUBNET) copy() EDNS0 {
return &EDNS0_SUBNET{
e.Code,
e.Family,
e.SourceNetmask,
e.SourceScope,
e.Address,
}
}
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message. // The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
// //
// o := new(dns.OPT) // o := new(dns.OPT)
@ -355,7 +340,6 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE } func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil } func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
func (e *EDNS0_COOKIE) String() string { return e.Cookie } func (e *EDNS0_COOKIE) String() string { return e.Cookie }
func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} }
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
// an expiration on an update RR. This is helpful for clients that cannot clean // an expiration on an update RR. This is helpful for clients that cannot clean
@ -377,7 +361,6 @@ type EDNS0_UL struct {
// Option implements the EDNS0 interface. // Option implements the EDNS0 interface.
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL } func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) } func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease} }
// Copied: http://golang.org/src/pkg/net/dnsmsg.go // Copied: http://golang.org/src/pkg/net/dnsmsg.go
func (e *EDNS0_UL) pack() ([]byte, error) { func (e *EDNS0_UL) pack() ([]byte, error) {
@ -432,15 +415,11 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
func (e *EDNS0_LLQ) String() string { func (e *EDNS0_LLQ) String() string {
s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) + s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) + " " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
" " + strconv.FormatUint(uint64(e.LeaseLife), 10) " " + strconv.FormatUint(uint64(e.LeaseLife), 10)
return s return s
} }
func (e *EDNS0_LLQ) copy() EDNS0 {
return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
}
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
type EDNS0_DAU struct { type EDNS0_DAU struct {
Code uint16 // Always EDNS0DAU Code uint16 // Always EDNS0DAU
AlgCode []uint8 AlgCode []uint8
@ -453,18 +432,16 @@ func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_DAU) String() string { func (e *EDNS0_DAU) String() string {
s := "" s := ""
for _, alg := range e.AlgCode { for i := 0; i < len(e.AlgCode); i++ {
if a, ok := AlgorithmToString[alg]; ok { if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(alg)) s += " " + strconv.Itoa(int(e.AlgCode[i]))
} }
} }
return s return s
} }
func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
type EDNS0_DHU struct { type EDNS0_DHU struct {
Code uint16 // Always EDNS0DHU Code uint16 // Always EDNS0DHU
AlgCode []uint8 AlgCode []uint8
@ -477,18 +454,16 @@ func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_DHU) String() string { func (e *EDNS0_DHU) String() string {
s := "" s := ""
for _, alg := range e.AlgCode { for i := 0; i < len(e.AlgCode); i++ {
if a, ok := HashToString[alg]; ok { if a, ok := HashToString[e.AlgCode[i]]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(alg)) s += " " + strconv.Itoa(int(e.AlgCode[i]))
} }
} }
return s return s
} }
func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
type EDNS0_N3U struct { type EDNS0_N3U struct {
Code uint16 // Always EDNS0N3U Code uint16 // Always EDNS0N3U
AlgCode []uint8 AlgCode []uint8
@ -502,18 +477,16 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_N3U) String() string { func (e *EDNS0_N3U) String() string {
// Re-use the hash map // Re-use the hash map
s := "" s := ""
for _, alg := range e.AlgCode { for i := 0; i < len(e.AlgCode); i++ {
if a, ok := HashToString[alg]; ok { if a, ok := HashToString[e.AlgCode[i]]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(alg)) s += " " + strconv.Itoa(int(e.AlgCode[i]))
} }
} }
return s return s
} }
func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct { type EDNS0_EXPIRE struct {
Code uint16 // Always EDNS0EXPIRE Code uint16 // Always EDNS0EXPIRE
Expire uint32 Expire uint32
@ -522,11 +495,13 @@ type EDNS0_EXPIRE struct {
// Option implements the EDNS0 interface. // Option implements the EDNS0 interface.
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE } func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) } func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire} }
func (e *EDNS0_EXPIRE) pack() ([]byte, error) { func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
b := make([]byte, 4) b := make([]byte, 4)
binary.BigEndian.PutUint32(b, e.Expire) b[0] = byte(e.Expire >> 24)
b[1] = byte(e.Expire >> 16)
b[2] = byte(e.Expire >> 8)
b[3] = byte(e.Expire)
return b, nil return b, nil
} }
@ -561,11 +536,6 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
func (e *EDNS0_LOCAL) String() string { func (e *EDNS0_LOCAL) String() string {
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data) return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
} }
func (e *EDNS0_LOCAL) copy() EDNS0 {
b := make([]byte, len(e.Data))
copy(b, e.Data)
return &EDNS0_LOCAL{e.Code, b}
}
func (e *EDNS0_LOCAL) pack() ([]byte, error) { func (e *EDNS0_LOCAL) pack() ([]byte, error) {
b := make([]byte, len(e.Data)) b := make([]byte, len(e.Data))
@ -638,7 +608,6 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
} }
return return
} }
func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
// EDNS0_PADDING option is used to add padding to a request/response. The default // 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 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
@ -652,8 +621,3 @@ func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil } func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil } func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) } func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
func (e *EDNS0_PADDING) copy() EDNS0 {
b := make([]byte, len(e.Padding))
copy(b, e.Padding)
return &EDNS0_PADDING{b}
}

View File

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

View File

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

View File

@ -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) }

View File

@ -1,12 +1,18 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm mips mipsle 386 // +build arm mips mipsle 386
// +build linux // +build linux
package socket package socket
type cmsghdr struct {
Len uint32
Level int32
Type int32
}
const (
sizeofCmsghdr = 0xc
)
func (h *cmsghdr) set(l, lvl, typ int) { func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l) h.Len = uint32(l)
h.Level = int32(lvl) h.Level = int32(lvl)

View File

@ -1,12 +1,18 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build linux // +build linux
package socket package socket
type cmsghdr struct {
Len uint64
Level int32
Type int32
}
const (
sizeofCmsghdr = 0x10
)
func (h *cmsghdr) set(l, lvl, typ int) { func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint64(l) h.Len = uint64(l)
h.Level = int32(lvl) h.Level = int32(lvl)

View File

@ -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) {}

View File

@ -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)
}

View File

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

14
vendor/github.com/miekg/dns/internal/socket/sys.go generated vendored Normal file
View File

@ -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)
}

View File

@ -16,7 +16,7 @@ func SplitDomainName(s string) (labels []string) {
fqdnEnd := 0 // offset of the final '.' or the length of the name fqdnEnd := 0 // offset of the final '.' or the length of the name
idx := Split(s) idx := Split(s)
begin := 0 begin := 0
if IsFqdn(s) { if s[len(s)-1] == '.' {
fqdnEnd = len(s) - 1 fqdnEnd = len(s) - 1
} else { } else {
fqdnEnd = len(s) fqdnEnd = len(s)
@ -28,13 +28,16 @@ func SplitDomainName(s string) (labels []string) {
case 1: case 1:
// no-op // no-op
default: default:
for _, end := range idx[1:] { end := 0
for i := 1; i < len(idx); i++ {
end = idx[i]
labels = append(labels, s[begin:end-1]) labels = append(labels, s[begin:end-1])
begin = end begin = end
} }
} }
return append(labels, s[begin:fqdnEnd]) labels = append(labels, s[begin:fqdnEnd])
return labels
} }
// CompareDomainName compares the names s1 and s2 and // CompareDomainName compares the names s1 and s2 and
@ -175,10 +178,10 @@ func equal(a, b string) bool {
ai := a[i] ai := a[i]
bi := b[i] bi := b[i]
if ai >= 'A' && ai <= 'Z' { if ai >= 'A' && ai <= 'Z' {
ai |= 'a' - 'A' ai |= ('a' - 'A')
} }
if bi >= 'A' && bi <= 'Z' { if bi >= 'A' && bi <= 'Z' {
bi |= 'a' - 'A' bi |= ('a' - 'A')
} }
if ai != bi { if ai != bi {
return false return false

View File

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

View File

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

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

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,8 @@ import (
) )
var packageHdr = ` var packageHdr = `
// Code generated by "go run msg_generate.go"; DO NOT EDIT. // *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from msg_generate.go
package dns package dns
@ -80,7 +81,13 @@ func main() {
o := scope.Lookup(name) o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope) st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {\n", name) fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil {
return off, err
}
headerEnd := off
`)
for i := 1; i < st.NumFields(); i++ { for i := 1; i < st.NumFields(); i++ {
o := func(s string) { o := func(s string) {
fmt.Fprintf(b, s, st.Field(i).Name()) fmt.Fprintf(b, s, st.Field(i).Name())
@ -100,7 +107,7 @@ return off, err
case `dns:"nsec"`: case `dns:"nsec"`:
o("off, err = packDataNsec(rr.%s, msg, off)\n") o("off, err = packDataNsec(rr.%s, msg, off)\n")
case `dns:"domain-name"`: case `dns:"domain-name"`:
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n") o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
default: default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
} }
@ -110,9 +117,9 @@ return off, err
switch { switch {
case st.Tag(i) == `dns:"-"`: // ignored case st.Tag(i) == `dns:"-"`: // ignored
case st.Tag(i) == `dns:"cdomain-name"`: case st.Tag(i) == `dns:"cdomain-name"`:
o("off, err = packDomainName(rr.%s, msg, off, compression, compress)\n") o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
case st.Tag(i) == `dns:"domain-name"`: case st.Tag(i) == `dns:"domain-name"`:
o("off, err = packDomainName(rr.%s, msg, off, compression, false)\n") o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
case st.Tag(i) == `dns:"a"`: case st.Tag(i) == `dns:"a"`:
o("off, err = packDataA(rr.%s, msg, off)\n") o("off, err = packDataA(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"aaaa"`: case st.Tag(i) == `dns:"aaaa"`:
@ -148,8 +155,7 @@ if rr.%s != "-" {
fallthrough fallthrough
case st.Tag(i) == `dns:"hex"`: case st.Tag(i) == `dns:"hex"`:
o("off, err = packStringHex(rr.%s, msg, off)\n") o("off, err = packStringHex(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"any"`:
o("off, err = packStringAny(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"octet"`: case st.Tag(i) == `dns:"octet"`:
o("off, err = packStringOctet(rr.%s, msg, off)\n") o("off, err = packStringOctet(rr.%s, msg, off)\n")
case st.Tag(i) == "": case st.Tag(i) == "":
@ -171,6 +177,8 @@ if rr.%s != "-" {
log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
} }
} }
// We have packed everything, only now we know the rdlength of this RR
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
fmt.Fprintln(b, "return off, nil }\n") fmt.Fprintln(b, "return off, nil }\n")
} }
@ -179,8 +187,14 @@ if rr.%s != "-" {
o := scope.Lookup(name) o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope) st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name) fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
fmt.Fprint(b, `rdStart := off fmt.Fprintf(b, "rr := new(%s)\n", name)
fmt.Fprint(b, "rr.Hdr = h\n")
fmt.Fprint(b, `if noRdata(h) {
return rr, off, nil
}
var err error
rdStart := off
_ = rdStart _ = rdStart
`) `)
@ -188,7 +202,7 @@ _ = rdStart
o := func(s string) { o := func(s string) {
fmt.Fprintf(b, s, st.Field(i).Name()) fmt.Fprintf(b, s, st.Field(i).Name())
fmt.Fprint(b, `if err != nil { fmt.Fprint(b, `if err != nil {
return off, err return rr, off, err
} }
`) `)
} }
@ -208,7 +222,7 @@ return off, err
log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
} }
fmt.Fprint(b, `if err != nil { fmt.Fprint(b, `if err != nil {
return off, err return rr, off, err
} }
`) `)
continue continue
@ -251,8 +265,6 @@ return off, err
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n") o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"hex"`: case `dns:"hex"`:
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n") o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"any"`:
o("rr.%s, off, err = unpackStringAny(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
case `dns:"octet"`: case `dns:"octet"`:
o("rr.%s, off, err = unpackStringOctet(msg, off)\n") o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
case "": case "":
@ -276,13 +288,22 @@ return off, err
// If we've hit len(msg) we return without error. // If we've hit len(msg) we return without error.
if i < st.NumFields()-1 { if i < st.NumFields()-1 {
fmt.Fprintf(b, `if off == len(msg) { fmt.Fprintf(b, `if off == len(msg) {
return off, nil return rr, off, nil
} }
`) `)
} }
} }
fmt.Fprintf(b, "return off, nil }\n\n") fmt.Fprintf(b, "return rr, off, err }\n\n")
} }
// Generate typeToUnpack map
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
for _, name := range namedTypes {
if name == "RFC3597" {
continue
}
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
}
fmt.Fprintln(b, "}\n")
// gofmt // gofmt
res, err := format.Source(b.Bytes()) res, err := format.Source(b.Bytes())

View File

@ -6,7 +6,7 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"net" "net"
"strings" "strconv"
) )
// helper functions called from the generated zmsg.go // helper functions called from the generated zmsg.go
@ -25,13 +25,12 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataA(a net.IP, msg []byte, off int) (int, error) { func packDataA(a net.IP, msg []byte, off int) (int, error) {
// It must be a slice of 4, even if it is 16, we encode only the first 4
if off+net.IPv4len > len(msg) {
return len(msg), &Error{err: "overflow packing a"}
}
switch len(a) { switch len(a) {
case net.IPv4len, net.IPv6len: case net.IPv4len, net.IPv6len:
// It must be a slice of 4, even if it is 16, we encode only the first 4
if off+net.IPv4len > len(msg) {
return len(msg), &Error{err: "overflow packing a"}
}
copy(msg[off:], a.To4()) copy(msg[off:], a.To4())
off += net.IPv4len off += net.IPv4len
case 0: case 0:
@ -52,12 +51,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) { func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
if off+net.IPv6len > len(msg) {
return len(msg), &Error{err: "overflow packing aaaa"}
}
switch len(aaaa) { switch len(aaaa) {
case net.IPv6len: case net.IPv6len:
if off+net.IPv6len > len(msg) {
return len(msg), &Error{err: "overflow packing aaaa"}
}
copy(msg[off:], aaaa) copy(msg[off:], aaaa)
off += net.IPv6len off += net.IPv6len
case 0: case 0:
@ -100,14 +99,14 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
return hdr, off, msg, err return hdr, off, msg, err
} }
// packHeader packs an RR header, returning the offset to the end of the header. // pack packs an RR header, returning the offset to the end of the header.
// See PackDomainName for documentation about the compression. // See PackDomainName for documentation about the compression.
func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) { func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
if off == len(msg) { if off == len(msg) {
return off, nil return off, nil
} }
off, err := packDomainName(hdr.Name, msg, off, compression, compress) off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
@ -123,7 +122,7 @@ func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap,
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR. off, err = packUint16(hdr.Rdlength, msg, off)
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
@ -142,24 +141,20 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b
return msg[:lenrd], nil return msg[:lenrd], nil
} }
var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
func fromBase32(s []byte) (buf []byte, err error) { func fromBase32(s []byte) (buf []byte, err error) {
for i, b := range s { for i, b := range s {
if b >= 'a' && b <= 'z' { if b >= 'a' && b <= 'z' {
s[i] = b - 32 s[i] = b - 32
} }
} }
buflen := base32HexNoPadEncoding.DecodedLen(len(s)) buflen := base32.HexEncoding.DecodedLen(len(s))
buf = make([]byte, buflen) buf = make([]byte, buflen)
n, err := base32HexNoPadEncoding.Decode(buf, s) n, err := base32.HexEncoding.Decode(buf, s)
buf = buf[:n] buf = buf[:n]
return return
} }
func toBase32(b []byte) string { func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) }
return base32HexNoPadEncoding.EncodeToString(b)
}
func fromBase64(s []byte) (buf []byte, err error) { func fromBase64(s []byte) (buf []byte, err error) {
buflen := base64.StdEncoding.DecodedLen(len(s)) buflen := base64.StdEncoding.DecodedLen(len(s))
@ -178,14 +173,14 @@ func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
if off+1 > len(msg) { if off+1 > len(msg) {
return 0, len(msg), &Error{err: "overflow unpacking uint8"} return 0, len(msg), &Error{err: "overflow unpacking uint8"}
} }
return msg[off], off + 1, nil return uint8(msg[off]), off + 1, nil
} }
func packUint8(i uint8, msg []byte, off int) (off1 int, err error) { func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
if off+1 > len(msg) { if off+1 > len(msg) {
return len(msg), &Error{err: "overflow packing uint8"} return len(msg), &Error{err: "overflow packing uint8"}
} }
msg[off] = i msg[off] = byte(i)
return off + 1, nil return off + 1, nil
} }
@ -224,8 +219,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"} return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
} }
// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes) // Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 | i = (uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
uint64(msg[off+4])<<8 | uint64(msg[off+5]) uint64(msg[off+4])<<8 | uint64(msg[off+5])))
off += 6 off += 6
return i, off, nil return i, off, nil
} }
@ -268,21 +263,29 @@ func unpackString(msg []byte, off int) (string, int, error) {
if off+l+1 > len(msg) { if off+l+1 > len(msg) {
return "", off, &Error{err: "overflow unpacking txt"} return "", off, &Error{err: "overflow unpacking txt"}
} }
var s strings.Builder s := make([]byte, 0, l)
s.Grow(l)
for _, b := range msg[off+1 : off+1+l] { for _, b := range msg[off+1 : off+1+l] {
switch { switch b {
case b == '"' || b == '\\': case '"', '\\':
s.WriteByte('\\') s = append(s, '\\', b)
s.WriteByte(b)
case b < ' ' || b > '~': // unprintable
s.WriteString(escapeByte(b))
default: default:
s.WriteByte(b) if b < 32 || b > 127 { // unprintable
var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\')
for i := 0; i < 3-len(bufs); i++ {
s = append(s, '0')
}
for _, r := range bufs {
s = append(s, r)
}
} else {
s = append(s, b)
}
} }
} }
off += 1 + l off += 1 + l
return s.String(), off, nil return string(s), off, nil
} }
func packString(s string, msg []byte, off int) (int, error) { func packString(s string, msg []byte, off int) (int, error) {
@ -356,7 +359,7 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
if off+len(h) > len(msg) { if off+(len(h)) > len(msg) {
return len(msg), &Error{err: "overflow packing hex"} return len(msg), &Error{err: "overflow packing hex"}
} }
copy(msg[off:off+len(h)], h) copy(msg[off:off+len(h)], h)
@ -364,22 +367,6 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
return off, nil return off, nil
} }
func unpackStringAny(msg []byte, off, end int) (string, int, error) {
if end > len(msg) {
return "", len(msg), &Error{err: "overflow unpacking anything"}
}
return string(msg[off:end]), end, nil
}
func packStringAny(s string, msg []byte, off int) (int, error) {
if off+len(s) > len(msg) {
return len(msg), &Error{err: "overflow packing anything"}
}
copy(msg[off:off+len(s)], s)
off += len(s)
return off, nil
}
func unpackStringTxt(msg []byte, off int) ([]string, int, error) { func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
txt, off, err := unpackTxt(msg, off) txt, off, err := unpackTxt(msg, off)
if err != nil { if err != nil {
@ -400,7 +387,7 @@ func packStringTxt(s []string, msg []byte, off int) (int, error) {
func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) { func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
var edns []EDNS0 var edns []EDNS0
Option: Option:
var code uint16 code := uint16(0)
if off+4 > len(msg) { if off+4 > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking opt"} return nil, len(msg), &Error{err: "overflow unpacking opt"}
} }
@ -554,7 +541,8 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
} }
// Walk the bytes in the window and extract the type bits // Walk the bytes in the window and extract the type bits
for j, b := range msg[off : off+length] { for j := 0; j < length; j++ {
b := msg[off+j]
// Check the bits one by one, and set the type // Check the bits one by one, and set the type
if b&0x80 == 0x80 { if b&0x80 == 0x80 {
nsec = append(nsec, uint16(window*256+j*8+0)) nsec = append(nsec, uint16(window*256+j*8+0))
@ -592,7 +580,8 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
return off, nil return off, nil
} }
var lastwindow, lastlength uint16 var lastwindow, lastlength uint16
for _, t := range bitmap { for j := 0; j < len(bitmap); j++ {
t := bitmap[j]
window := t / 256 window := t / 256
length := (t-window*256)/8 + 1 length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
@ -610,7 +599,7 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
// Setting the octets length // Setting the octets length
msg[off+1] = byte(length) msg[off+1] = byte(length)
// Setting the bit value for the type in the right octet // Setting the bit value for the type in the right octet
msg[off+1+int(length)] |= byte(1 << (7 - t%8)) msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
lastwindow, lastlength = window, length lastwindow, lastlength = window, length
} }
off += int(lastlength) + 2 off += int(lastlength) + 2
@ -636,10 +625,10 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
return servers, off, nil return servers, off, nil
} }
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) { func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
var err error var err error
for _, name := range names { for j := 0; j < len(names); j++ {
off, err = packDomainName(name, msg, off, compression, compress) off, err = PackDomainName(names[j], msg, off, compression, false && compress)
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }

View File

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

47
vendor/github.com/miekg/dns/nsecx.go generated vendored
View File

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

View File

@ -39,12 +39,11 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
} }
anyrr := rrfunc() anyrr := rrfunc()
rr, ok := anyrr.(*PrivateRR) switch rr := anyrr.(type) {
if !ok { case *PrivateRR:
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr)) return rr
} }
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
return rr
} }
// Header return the RR header of r. // Header return the RR header of r.
@ -53,16 +52,12 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() } func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
// Private len and copy parts to satisfy RR interface. // Private len and copy parts to satisfy RR interface.
func (r *PrivateRR) len(off int, compression map[string]struct{}) int { func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
l := r.Hdr.len(off, compression)
l += r.Data.Len()
return l
}
func (r *PrivateRR) copy() RR { func (r *PrivateRR) copy() RR {
// make new RR like this: // make new RR like this:
rr := mkPrivateRR(r.Hdr.Rrtype) rr := mkPrivateRR(r.Hdr.Rrtype)
rr.Hdr = r.Hdr newh := r.Hdr.copyHeader()
rr.Hdr = *newh
err := r.Data.Copy(rr.Data) err := r.Data.Copy(rr.Data)
if err != nil { if err != nil {
@ -70,47 +65,21 @@ func (r *PrivateRR) copy() RR {
} }
return rr return rr
} }
func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) { off, err := r.Hdr.pack(msg, off, compression, compress)
if err != nil {
return off, err
}
headerEnd := off
n, err := r.Data.Pack(msg[off:]) n, err := r.Data.Pack(msg[off:])
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
off += n off += n
r.Header().Rdlength = uint16(off - headerEnd)
return off, nil return off, nil
} }
func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
off1, err := r.Data.Unpack(msg[off:])
off += off1
return off, err
}
func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError {
var l lex
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
Fetch:
for {
// TODO(miek): we could also be returning _QUOTE, this might or might not
// be an issue (basically parsing TXT becomes hard)
switch l, _ = c.Next(); l.value {
case zNewline, zEOF:
break Fetch
case zString:
text = append(text, l.token)
}
}
err := r.Data.Parse(text)
if err != nil {
return &ParseError{file, err.Error(), l}
}
return nil
}
func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
// PrivateHandle registers a private resource record type. It requires // PrivateHandle registers a private resource record type. It requires
// string and numeric representation of private RR type and generator function as argument. // string and numeric representation of private RR type and generator function as argument.
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) { func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
@ -119,14 +88,62 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} } TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
TypeToString[rtype] = rtypestr TypeToString[rtype] = rtypestr
StringToType[rtypestr] = rtype StringToType[rtypestr] = rtype
typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
if noRdata(h) {
return &h, off, nil
}
var err error
rr := mkPrivateRR(h.Rrtype)
rr.Hdr = h
off1, err := rr.Data.Unpack(msg[off:])
off += off1
if err != nil {
return rr, off, err
}
return rr, off, err
}
setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := mkPrivateRR(h.Rrtype)
rr.Hdr = h
var l lex
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
Fetch:
for {
// TODO(miek): we could also be returning _QUOTE, this might or might not
// be an issue (basically parsing TXT becomes hard)
switch l = <-c; l.value {
case zNewline, zEOF:
break Fetch
case zString:
text = append(text, l.token)
}
}
err := rr.Data.Parse(text)
if err != nil {
return nil, &ParseError{f, err.Error(), l}, ""
}
return rr, nil, ""
}
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
} }
// PrivateHandleRemove removes definitions required to support private RR type. // PrivateHandleRemove removes defenitions required to support private RR type.
func PrivateHandleRemove(rtype uint16) { func PrivateHandleRemove(rtype uint16) {
rtypestr, ok := TypeToString[rtype] rtypestr, ok := TypeToString[rtype]
if ok { if ok {
delete(TypeToRR, rtype) delete(TypeToRR, rtype)
delete(TypeToString, rtype) delete(TypeToString, rtype)
delete(typeToparserFunc, rtype)
delete(StringToType, rtypestr) delete(StringToType, rtypestr)
delete(typeToUnpack, rtype)
} }
return
} }

49
vendor/github.com/miekg/dns/rawmsg.go generated vendored Normal file
View File

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

View File

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

View File

@ -3,9 +3,8 @@ package dns
// Dedup removes identical RRs from rrs. It preserves the original ordering. // Dedup removes identical RRs from rrs. It preserves the original ordering.
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies // The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
// rrs. // rrs.
// m is used to store the RRs temporary. If it is nil a new map will be allocated. // m is used to store the RRs temporay. If it is nil a new map will be allocated.
func Dedup(rrs []RR, m map[string]RR) []RR { func Dedup(rrs []RR, m map[string]RR) []RR {
if m == nil { if m == nil {
m = make(map[string]RR) m = make(map[string]RR)
} }
@ -15,11 +14,10 @@ func Dedup(rrs []RR, m map[string]RR) []RR {
for _, r := range rrs { for _, r := range rrs {
key := normalizedString(r) key := normalizedString(r)
keys = append(keys, &key) keys = append(keys, &key)
if mr, ok := m[key]; ok { if _, ok := m[key]; ok {
// Shortest TTL wins. // Shortest TTL wins.
rh, mrh := r.Header(), mr.Header() if m[key].Header().Ttl > r.Header().Ttl {
if mrh.Ttl > rh.Ttl { m[key].Header().Ttl = r.Header().Ttl
mrh.Ttl = rh.Ttl
} }
continue continue
} }

1151
vendor/github.com/miekg/dns/scan.go generated vendored

File diff suppressed because it is too large Load Diff

1746
vendor/github.com/miekg/dns/scan_rr.go generated vendored

File diff suppressed because it is too large Load Diff

56
vendor/github.com/miekg/dns/scanner.go generated vendored Normal file
View File

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

View File

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

698
vendor/github.com/miekg/dns/server.go generated vendored
View File

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

31
vendor/github.com/miekg/dns/sig0.go generated vendored
View File

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

View File

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

View File

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

View File

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

21
vendor/github.com/miekg/dns/tsig.go generated vendored
View File

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

271
vendor/github.com/miekg/dns/types.go generated vendored
View File

@ -205,6 +205,9 @@ var CertTypeToString = map[uint16]string{
CertOID: "OID", CertOID: "OID",
} }
// StringToCertType is the reverseof CertTypeToString.
var StringToCertType = reverseInt16(CertTypeToString)
//go:generate go run types_generate.go //go:generate go run types_generate.go
// Question holds a DNS question. There can be multiple questions in the // Question holds a DNS question. There can be multiple questions in the
@ -215,10 +218,8 @@ type Question struct {
Qclass uint16 Qclass uint16
} }
func (q *Question) len(off int, compression map[string]struct{}) int { func (q *Question) len() int {
l := domainNameLen(q.Name, off, compression, true) return len(q.Name) + 1 + 2 + 2
l += 2 + 2
return l
} }
func (q *Question) String() (s string) { func (q *Question) String() (s string) {
@ -238,25 +239,6 @@ type ANY struct {
func (rr *ANY) String() string { return rr.Hdr.String() } func (rr *ANY) String() string { return rr.Hdr.String() }
func (rr *ANY) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on ANY")
}
// NULL RR. See RFC 1035.
type NULL struct {
Hdr RR_Header
Data string `dns:"any"`
}
func (rr *NULL) String() string {
// There is no presentation format; prefix string with a comment.
return ";" + rr.Hdr.String() + rr.Data
}
func (rr *NULL) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on NULL")
}
// CNAME RR. See RFC 1034. // CNAME RR. See RFC 1034.
type CNAME struct { type CNAME struct {
Hdr RR_Header Hdr RR_Header
@ -348,7 +330,7 @@ func (rr *MX) String() string {
type AFSDB struct { type AFSDB struct {
Hdr RR_Header Hdr RR_Header
Subtype uint16 Subtype uint16
Hostname string `dns:"domain-name"` Hostname string `dns:"cdomain-name"`
} }
func (rr *AFSDB) String() string { func (rr *AFSDB) String() string {
@ -369,7 +351,7 @@ func (rr *X25) String() string {
type RT struct { type RT struct {
Hdr RR_Header Hdr RR_Header
Preference uint16 Preference uint16
Host string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035. Host string `dns:"cdomain-name"`
} }
func (rr *RT) String() string { func (rr *RT) String() string {
@ -404,7 +386,7 @@ type RP struct {
} }
func (rr *RP) String() string { func (rr *RP) String() string {
return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt) return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
} }
// SOA RR. See RFC 1035. // SOA RR. See RFC 1035.
@ -437,154 +419,128 @@ type TXT struct {
func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
func sprintName(s string) string { func sprintName(s string) string {
var dst strings.Builder src := []byte(s)
dst.Grow(len(s)) dst := make([]byte, 0, len(src))
for i := 0; i < len(s); { for i := 0; i < len(src); {
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
dst.WriteString(s[i : i+2]) dst = append(dst, src[i:i+2]...)
i += 2 i += 2
continue } else {
b, n := nextByte(src, i)
if n == 0 {
i++ // dangling back slash
} else if b == '.' {
dst = append(dst, b)
} else {
dst = appendDomainNameByte(dst, b)
}
i += n
} }
b, n := nextByte(s, i)
switch {
case n == 0:
i++ // dangling back slash
case b == '.':
dst.WriteByte('.')
default:
writeDomainNameByte(&dst, b)
}
i += n
} }
return dst.String() return string(dst)
} }
func sprintTxtOctet(s string) string { func sprintTxtOctet(s string) string {
var dst strings.Builder src := []byte(s)
dst.Grow(2 + len(s)) dst := make([]byte, 0, len(src))
dst.WriteByte('"') dst = append(dst, '"')
for i := 0; i < len(s); { for i := 0; i < len(src); {
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
dst.WriteString(s[i : i+2]) dst = append(dst, src[i:i+2]...)
i += 2 i += 2
continue } else {
b, n := nextByte(src, i)
if n == 0 {
i++ // dangling back slash
} else if b == '.' {
dst = append(dst, b)
} else {
if b < ' ' || b > '~' {
dst = appendByte(dst, b)
} else {
dst = append(dst, b)
}
}
i += n
} }
b, n := nextByte(s, i)
switch {
case n == 0:
i++ // dangling back slash
case b == '.':
dst.WriteByte('.')
case b < ' ' || b > '~':
dst.WriteString(escapeByte(b))
default:
dst.WriteByte(b)
}
i += n
} }
dst.WriteByte('"') dst = append(dst, '"')
return dst.String() return string(dst)
} }
func sprintTxt(txt []string) string { func sprintTxt(txt []string) string {
var out strings.Builder var out []byte
for i, s := range txt { for i, s := range txt {
out.Grow(3 + len(s))
if i > 0 { if i > 0 {
out.WriteString(` "`) out = append(out, ` "`...)
} else { } else {
out.WriteByte('"') out = append(out, '"')
} }
for j := 0; j < len(s); { bs := []byte(s)
b, n := nextByte(s, j) for j := 0; j < len(bs); {
b, n := nextByte(bs, j)
if n == 0 { if n == 0 {
break break
} }
writeTXTStringByte(&out, b) out = appendTXTStringByte(out, b)
j += n j += n
} }
out.WriteByte('"') out = append(out, '"')
} }
return out.String() return string(out)
} }
func writeDomainNameByte(s *strings.Builder, b byte) { func appendDomainNameByte(s []byte, b byte) []byte {
switch b { switch b {
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
s.WriteByte('\\') return append(s, '\\', b)
s.WriteByte(b)
default:
writeTXTStringByte(s, b)
} }
return appendTXTStringByte(s, b)
} }
func writeTXTStringByte(s *strings.Builder, b byte) { func appendTXTStringByte(s []byte, b byte) []byte {
switch { switch b {
case b == '"' || b == '\\': case '"', '\\':
s.WriteByte('\\') return append(s, '\\', b)
s.WriteByte(b)
case b < ' ' || b > '~':
s.WriteString(escapeByte(b))
default:
s.WriteByte(b)
} }
if b < ' ' || b > '~' {
return appendByte(s, b)
}
return append(s, b)
} }
const ( func appendByte(s []byte, b byte) []byte {
escapedByteSmall = "" + var buf [3]byte
`\000\001\002\003\004\005\006\007\008\009` + bufs := strconv.AppendInt(buf[:0], int64(b), 10)
`\010\011\012\013\014\015\016\017\018\019` + s = append(s, '\\')
`\020\021\022\023\024\025\026\027\028\029` + for i := 0; i < 3-len(bufs); i++ {
`\030\031` s = append(s, '0')
escapedByteLarge = `\127\128\129` +
`\130\131\132\133\134\135\136\137\138\139` +
`\140\141\142\143\144\145\146\147\148\149` +
`\150\151\152\153\154\155\156\157\158\159` +
`\160\161\162\163\164\165\166\167\168\169` +
`\170\171\172\173\174\175\176\177\178\179` +
`\180\181\182\183\184\185\186\187\188\189` +
`\190\191\192\193\194\195\196\197\198\199` +
`\200\201\202\203\204\205\206\207\208\209` +
`\210\211\212\213\214\215\216\217\218\219` +
`\220\221\222\223\224\225\226\227\228\229` +
`\230\231\232\233\234\235\236\237\238\239` +
`\240\241\242\243\244\245\246\247\248\249` +
`\250\251\252\253\254\255`
)
// escapeByte returns the \DDD escaping of b which must
// satisfy b < ' ' || b > '~'.
func escapeByte(b byte) string {
if b < ' ' {
return escapedByteSmall[b*4 : b*4+4]
} }
for _, r := range bufs {
b -= '~' + 1 s = append(s, r)
// The cast here is needed as b*4 may overflow byte. }
return escapedByteLarge[int(b)*4 : int(b)*4+4] return s
} }
func nextByte(s string, offset int) (byte, int) { func nextByte(b []byte, offset int) (byte, int) {
if offset >= len(s) { if offset >= len(b) {
return 0, 0 return 0, 0
} }
if s[offset] != '\\' { if b[offset] != '\\' {
// not an escape sequence // not an escape sequence
return s[offset], 1 return b[offset], 1
} }
switch len(s) - offset { switch len(b) - offset {
case 1: // dangling escape case 1: // dangling escape
return 0, 0 return 0, 0
case 2, 3: // too short to be \ddd case 2, 3: // too short to be \ddd
default: // maybe \ddd default: // maybe \ddd
if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) { if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
return dddStringToByte(s[offset+1:]), 4 return dddToByte(b[offset+1:]), 4
} }
} }
// not \ddd, just an RFC 1035 "quoted" character // not \ddd, just an RFC 1035 "quoted" character
return s[offset+1], 2 return b[offset+1], 2
} }
// SPF RR. See RFC 4408, Section 3.1.1. // SPF RR. See RFC 4408, Section 3.1.1.
@ -772,7 +728,7 @@ func (rr *LOC) String() string {
lat = lat % LOC_DEGREES lat = lat % LOC_DEGREES
m := lat / LOC_HOURS m := lat / LOC_HOURS
lat = lat % LOC_HOURS lat = lat % LOC_HOURS
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns) s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
lon := rr.Longitude lon := rr.Longitude
ew := "E" ew := "E"
@ -786,7 +742,7 @@ func (rr *LOC) String() string {
lon = lon % LOC_DEGREES lon = lon % LOC_DEGREES
m = lon / LOC_HOURS m = lon / LOC_HOURS
lon = lon % LOC_HOURS lon = lon % LOC_HOURS
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew) s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
var alt = float64(rr.Altitude) / 100 var alt = float64(rr.Altitude) / 100
alt -= LOC_ALTITUDEBASE alt -= LOC_ALTITUDEBASE
@ -796,9 +752,9 @@ func (rr *LOC) String() string {
s += fmt.Sprintf("%.0fm ", alt) s += fmt.Sprintf("%.0fm ", alt)
} }
s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m " s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m " s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m" s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
return s return s
} }
@ -845,15 +801,14 @@ type NSEC struct {
func (rr *NSEC) String() string { func (rr *NSEC) String() string {
s := rr.Hdr.String() + sprintName(rr.NextDomain) s := rr.Hdr.String() + sprintName(rr.NextDomain)
for _, t := range rr.TypeBitMap { for i := 0; i < len(rr.TypeBitMap); i++ {
s += " " + Type(t).String() s += " " + Type(rr.TypeBitMap[i]).String()
} }
return s return s
} }
func (rr *NSEC) len(off int, compression map[string]struct{}) int { func (rr *NSEC) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len() + len(rr.NextDomain) + 1
l += domainNameLen(rr.NextDomain, off+l, compression, false)
lastwindow := uint32(2 ^ 32 + 1) lastwindow := uint32(2 ^ 32 + 1)
for _, t := range rr.TypeBitMap { for _, t := range rr.TypeBitMap {
window := t / 256 window := t / 256
@ -1011,15 +966,14 @@ func (rr *NSEC3) String() string {
" " + strconv.Itoa(int(rr.Iterations)) + " " + strconv.Itoa(int(rr.Iterations)) +
" " + saltToString(rr.Salt) + " " + saltToString(rr.Salt) +
" " + rr.NextDomain " " + rr.NextDomain
for _, t := range rr.TypeBitMap { for i := 0; i < len(rr.TypeBitMap); i++ {
s += " " + Type(t).String() s += " " + Type(rr.TypeBitMap[i]).String()
} }
return s return s
} }
func (rr *NSEC3) len(off int, compression map[string]struct{}) int { func (rr *NSEC3) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
lastwindow := uint32(2 ^ 32 + 1) lastwindow := uint32(2 ^ 32 + 1)
for _, t := range rr.TypeBitMap { for _, t := range rr.TypeBitMap {
window := t / 256 window := t / 256
@ -1066,16 +1020,10 @@ type TKEY struct {
// TKEY has no official presentation format, but this will suffice. // TKEY has no official presentation format, but this will suffice.
func (rr *TKEY) String() string { func (rr *TKEY) String() string {
s := ";" + rr.Hdr.String() + s := "\n;; TKEY PSEUDOSECTION:\n"
" " + rr.Algorithm + s += rr.Hdr.String() + " " + rr.Algorithm + " " +
" " + TimeToString(rr.Inception) + strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
" " + TimeToString(rr.Expiration) + strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
" " + strconv.Itoa(int(rr.Mode)) +
" " + strconv.Itoa(int(rr.Error)) +
" " + strconv.Itoa(int(rr.KeySize)) +
" " + rr.Key +
" " + strconv.Itoa(int(rr.OtherLen)) +
" " + rr.OtherData
return s return s
} }
@ -1335,15 +1283,14 @@ type CSYNC struct {
func (rr *CSYNC) String() string { func (rr *CSYNC) String() string {
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags)) s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
for _, t := range rr.TypeBitMap { for i := 0; i < len(rr.TypeBitMap); i++ {
s += " " + Type(t).String() s += " " + Type(rr.TypeBitMap[i]).String()
} }
return s return s
} }
func (rr *CSYNC) len(off int, compression map[string]struct{}) int { func (rr *CSYNC) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len() + 4 + 2
l += 4 + 2
lastwindow := uint32(2 ^ 32 + 1) lastwindow := uint32(2 ^ 32 + 1)
for _, t := range rr.TypeBitMap { for _, t := range rr.TypeBitMap {
window := t / 256 window := t / 256
@ -1359,11 +1306,11 @@ func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
// string representation used when printing the record. // string representation used when printing the record.
// It takes serial arithmetic (RFC 1982) into account. // It takes serial arithmetic (RFC 1982) into account.
func TimeToString(t uint32) string { func TimeToString(t uint32) string {
mod := (int64(t)-time.Now().Unix())/year68 - 1 mod := ((int64(t) - time.Now().Unix()) / year68) - 1
if mod < 0 { if mod < 0 {
mod = 0 mod = 0
} }
ti := time.Unix(int64(t)-mod*year68, 0).UTC() ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
return ti.Format("20060102150405") return ti.Format("20060102150405")
} }
@ -1375,11 +1322,11 @@ func StringToTime(s string) (uint32, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
mod := t.Unix()/year68 - 1 mod := (t.Unix() / year68) - 1
if mod < 0 { if mod < 0 {
mod = 0 mod = 0
} }
return uint32(t.Unix() - mod*year68), nil return uint32(t.Unix() - (mod * year68)), nil
} }
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty. // saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.

View File

@ -27,7 +27,8 @@ var skipLen = map[string]struct{}{
} }
var packageHdr = ` var packageHdr = `
// Code generated by "go run types_generate.go"; DO NOT EDIT. // *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from types_generate.go
package dns package dns
@ -153,8 +154,8 @@ func main() {
if isEmbedded { if isEmbedded {
continue continue
} }
fmt.Fprintf(b, "func (rr *%s) len(off int, compression map[string]struct{}) int {\n", name) fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
fmt.Fprintf(b, "l := rr.Hdr.len(off, compression)\n") fmt.Fprintf(b, "l := rr.Hdr.len()\n")
for i := 1; i < st.NumFields(); i++ { for i := 1; i < st.NumFields(); i++ {
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) } o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
@ -162,11 +163,7 @@ func main() {
switch st.Tag(i) { switch st.Tag(i) {
case `dns:"-"`: case `dns:"-"`:
// ignored // ignored
case `dns:"cdomain-name"`: case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, true) }\n")
case `dns:"domain-name"`:
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, false) }\n")
case `dns:"txt"`:
o("for _, x := range rr.%s { l += len(x) + 1 }\n") o("for _, x := range rr.%s { l += len(x) + 1 }\n")
default: default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
@ -177,28 +174,22 @@ func main() {
switch { switch {
case st.Tag(i) == `dns:"-"`: case st.Tag(i) == `dns:"-"`:
// ignored // ignored
case st.Tag(i) == `dns:"cdomain-name"`: case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
o("l += domainNameLen(rr.%s, off+l, compression, true)\n") o("l += len(rr.%s) + 1\n")
case st.Tag(i) == `dns:"domain-name"`:
o("l += domainNameLen(rr.%s, off+l, compression, false)\n")
case st.Tag(i) == `dns:"octet"`: case st.Tag(i) == `dns:"octet"`:
o("l += len(rr.%s)\n") o("l += len(rr.%s)\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
fallthrough fallthrough
case st.Tag(i) == `dns:"base64"`: case st.Tag(i) == `dns:"base64"`:
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n") o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
o("l += len(rr.%s)/2\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
fallthrough fallthrough
case st.Tag(i) == `dns:"hex"`: case st.Tag(i) == `dns:"hex"`:
o("l += len(rr.%s)/2 + 1\n") o("l += len(rr.%s)/2 + 1\n")
case st.Tag(i) == `dns:"any"`:
o("l += len(rr.%s)\n")
case st.Tag(i) == `dns:"a"`: case st.Tag(i) == `dns:"a"`:
o("if len(rr.%s) != 0 { l += net.IPv4len }\n") o("l += net.IPv4len // %s\n")
case st.Tag(i) == `dns:"aaaa"`: case st.Tag(i) == `dns:"aaaa"`:
o("if len(rr.%s) != 0 { l += net.IPv6len }\n") o("l += net.IPv6len // %s\n")
case st.Tag(i) == `dns:"txt"`: case st.Tag(i) == `dns:"txt"`:
o("for _, t := range rr.%s { l += len(t) + 1 }\n") o("for _, t := range rr.%s { l += len(t) + 1 }\n")
case st.Tag(i) == `dns:"uint48"`: case st.Tag(i) == `dns:"uint48"`:
@ -234,7 +225,7 @@ func main() {
continue continue
} }
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name) fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
fields := []string{"rr.Hdr"} fields := []string{"*rr.Hdr.copyHeader()"}
for i := 1; i < st.NumFields(); i++ { for i := 1; i < st.NumFields(); i++ {
f := st.Field(i).Name() f := st.Field(i).Name()
if sl, ok := st.Field(i).Type().(*types.Slice); ok { if sl, ok := st.Field(i).Type().(*types.Slice); ok {
@ -244,13 +235,6 @@ func main() {
splits := strings.Split(t, ".") splits := strings.Split(t, ".")
t = splits[len(splits)-1] t = splits[len(splits)-1]
} }
// For the EDNS0 interface (used in the OPT RR), we need to call the copy method on each element.
if t == "EDNS0" {
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s));\nfor i,e := range rr.%s {\n %s[i] = e.copy()\n}\n",
f, t, f, f, f)
fields = append(fields, f)
continue
}
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n", fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
f, t, f, f, f) f, t, f, f, f)
fields = append(fields, f) fields = append(fields, f)

67
vendor/github.com/miekg/dns/udp.go generated vendored
View File

@ -4,27 +4,8 @@ package dns
import ( import (
"net" "net"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
) )
// This is the required size of the OOB buffer to pass to ReadMsgUDP.
var udpOOBSize = func() int {
// We can't know whether we'll get an IPv4 control message or an
// IPv6 control message ahead of time. To get around this, we size
// the buffer equal to the largest of the two.
oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface)
oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface)
if len(oob4) > len(oob6) {
return len(oob4)
}
return len(oob6)
}()
// SessionUDP holds the remote address and the associated // SessionUDP holds the remote address and the associated
// out-of-band data. // out-of-band data.
type SessionUDP struct { type SessionUDP struct {
@ -38,7 +19,7 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr. // net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
oob := make([]byte, udpOOBSize) oob := make([]byte, 40)
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob) n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
if err != nil { if err != nil {
return n, nil, err return n, nil, err
@ -53,50 +34,12 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
return n, err return n, err
} }
func setUDPSocketOptions(conn *net.UDPConn) error {
// Try setting the flags for both families and ignore the errors unless they
// both error.
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
if err6 != nil && err4 != nil {
return err4
}
return nil
}
// parseDstFromOOB takes oob data and returns the destination IP.
func parseDstFromOOB(oob []byte) net.IP {
// Start with IPv6 and then fallback to IPv4
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
// the lvl of the header for a 0 or 41 isn't cross-platform.
cm6 := new(ipv6.ControlMessage)
if cm6.Parse(oob) == nil && cm6.Dst != nil {
return cm6.Dst
}
cm4 := new(ipv4.ControlMessage)
if cm4.Parse(oob) == nil && cm4.Dst != nil {
return cm4.Dst
}
return nil
}
// correctSource takes oob data and returns new oob data with the Src equal to the Dst // correctSource takes oob data and returns new oob data with the Src equal to the Dst
func correctSource(oob []byte) []byte { func correctSource(oob []byte) []byte {
dst := parseDstFromOOB(oob) dst, err := parseUDPSocketDst(oob)
if dst == nil { // If the destination could not be determined, ignore.
if err != nil || dst == nil {
return nil return nil
} }
// If the dst is definitely an IPv6, then use ipv6's ControlMessage to return marshalUDPSocketSrc(dst)
// respond otherwise use ipv4's because ipv6's marshal ignores ipv4
// addresses.
if dst.To4() == nil {
cm := new(ipv6.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
} else {
cm := new(ipv4.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
}
return oob
} }

220
vendor/github.com/miekg/dns/udp_linux.go generated vendored Normal file
View File

@ -0,0 +1,220 @@
// +build linux,!appengine
package dns
// See:
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
//
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
// interface, this might not always be the correct one. This code will make sure the egress
// packet's interface matched the ingress' one.
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 {
sa, err := getUDPSocketName(conn)
if err != nil {
return err
}
switch sa.(type) {
case *syscall.SockaddrInet6:
v6only, err := getUDPSocketOptions6Only(conn)
if err != nil {
return err
}
setUDPSocketOptions6(conn)
if !v6only {
setUDPSocketOptions4(conn)
}
case *syscall.SockaddrInet4:
setUDPSocketOptions4(conn)
}
return nil
}
// setUDPSocketOptions4 prepares the v4 socket for sessions.
func setUDPSocketOptions4(conn *net.UDPConn) error {
file, err := conn.File()
if err != nil {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
file.Close()
return err
}
// Calling File() above results in the connection becoming blocking, we must fix that.
// See https://github.com/miekg/dns/issues/279
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
file.Close()
return err
}
file.Close()
return nil
}
// setUDPSocketOptions6 prepares the v6 socket for sessions.
func setUDPSocketOptions6(conn *net.UDPConn) error {
file, err := conn.File()
if err != nil {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
file.Close()
return err
}
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
file.Close()
return err
}
file.Close()
return nil
}
// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
// (dualstack).
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
file, err := conn.File()
if err != nil {
return false, err
}
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
if err != nil {
file.Close()
return false, err
}
file.Close()
return v6only == 1, nil
}
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
file, err := conn.File()
if err != nil {
return nil, err
}
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
}

17
vendor/github.com/miekg/dns/udp_other.go generated vendored Normal file
View File

@ -0,0 +1,17 @@
// +build !linux appengine
package dns
import (
"net"
)
// 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 parseUDPSocketDst(oob []byte) (net.IP, error) { return nil, nil }
func marshalUDPSocketSrc(src net.IP) []byte { return nil }

View File

@ -14,22 +14,17 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr. // net.UDPAddr.
// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
n, raddr, err := conn.ReadFrom(b) n, raddr, err := conn.ReadFrom(b)
if err != nil { if err != nil {
return n, nil, err return n, nil, err
} }
return n, &SessionUDP{raddr.(*net.UDPAddr)}, err session := &SessionUDP{raddr.(*net.UDPAddr)}
return n, session, err
} }
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), 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.
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
return conn.WriteTo(b, session.raddr) n, err := conn.WriteTo(b, session.raddr)
return n, err
} }
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
// use the standard method in udp.go for these.
func setUDPSocketOptions(*net.UDPConn) error { return nil }
func parseDstFromOOB([]byte, net.IP) net.IP { return nil }

View File

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

View File

@ -1,15 +0,0 @@
package dns
import "fmt"
// Version is current version of this library.
var Version = V{1, 1, 9}
// V holds the version of this library.
type V struct {
Major, Minor, Patch int
}
func (v V) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}

46
vendor/github.com/miekg/dns/xfr.go generated vendored
View File

@ -35,36 +35,30 @@ type Transfer struct {
// channel, err := transfer.In(message, master) // channel, err := transfer.In(message, master)
// //
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) { func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
switch q.Question[0].Qtype {
case TypeAXFR, TypeIXFR:
default:
return nil, &Error{"unsupported question type"}
}
timeout := dnsTimeout timeout := dnsTimeout
if t.DialTimeout != 0 { if t.DialTimeout != 0 {
timeout = t.DialTimeout timeout = t.DialTimeout
} }
if t.Conn == nil { if t.Conn == nil {
t.Conn, err = DialTimeout("tcp", a, timeout) t.Conn, err = DialTimeout("tcp", a, timeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
if err := t.WriteMsg(q); err != nil { if err := t.WriteMsg(q); err != nil {
return nil, err return nil, err
} }
env = make(chan *Envelope) env = make(chan *Envelope)
switch q.Question[0].Qtype { go func() {
case TypeAXFR: if q.Question[0].Qtype == TypeAXFR {
go t.inAxfr(q, env) go t.inAxfr(q, env)
case TypeIXFR: return
go t.inIxfr(q, env) }
} if q.Question[0].Qtype == TypeIXFR {
go t.inIxfr(q, env)
return
}
}()
return env, nil return env, nil
} }
@ -117,7 +111,7 @@ func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
} }
func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) { func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
var serial uint32 // The first serial seen is the current server serial serial := uint32(0) // The first serial seen is the current server serial
axfr := true axfr := true
n := 0 n := 0
qser := q.Ns[0].(*SOA).Serial qser := q.Ns[0].(*SOA).Serial
@ -243,18 +237,24 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
if err != nil { if err != nil {
return err return err
} }
_, err = t.Write(out) if _, err = t.Write(out); err != nil {
return err return err
}
return nil
} }
func isSOAFirst(in *Msg) bool { func isSOAFirst(in *Msg) bool {
return len(in.Answer) > 0 && if len(in.Answer) > 0 {
in.Answer[0].Header().Rrtype == TypeSOA return in.Answer[0].Header().Rrtype == TypeSOA
}
return false
} }
func isSOALast(in *Msg) bool { func isSOALast(in *Msg) bool {
return len(in.Answer) > 0 && if len(in.Answer) > 0 {
in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
}
return false
} }
const errXFR = "bad xfr rcode: %d" const errXFR = "bad xfr rcode: %d"

119
vendor/github.com/miekg/dns/zcompress.go generated vendored Normal file
View File

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

File diff suppressed because it is too large Load Diff

2048
vendor/github.com/miekg/dns/zmsg.go generated vendored

File diff suppressed because it is too large Load Diff

479
vendor/github.com/miekg/dns/ztypes.go generated vendored
View File

@ -1,4 +1,5 @@
// Code generated by "go run types_generate.go"; DO NOT EDIT. // *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from types_generate.go
package dns package dns
@ -54,7 +55,6 @@ var TypeToRR = map[uint16]func() RR{
TypeNSEC: func() RR { return new(NSEC) }, TypeNSEC: func() RR { return new(NSEC) },
TypeNSEC3: func() RR { return new(NSEC3) }, TypeNSEC3: func() RR { return new(NSEC3) },
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) }, TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
TypeNULL: func() RR { return new(NULL) },
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) }, TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
TypeOPT: func() RR { return new(OPT) }, TypeOPT: func() RR { return new(OPT) },
TypePTR: func() RR { return new(PTR) }, TypePTR: func() RR { return new(PTR) },
@ -210,7 +210,6 @@ func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
func (rr *NULL) Header() *RR_Header { return &rr.Hdr }
func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr } func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *OPT) Header() *RR_Header { return &rr.Hdr } func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
func (rr *PTR) Header() *RR_Header { return &rr.Hdr } func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
@ -238,150 +237,144 @@ func (rr *URI) Header() *RR_Header { return &rr.Hdr }
func (rr *X25) Header() *RR_Header { return &rr.Hdr } func (rr *X25) Header() *RR_Header { return &rr.Hdr }
// len() functions // len() functions
func (rr *A) len(off int, compression map[string]struct{}) int { func (rr *A) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
if len(rr.A) != 0 { l += net.IPv4len // A
l += net.IPv4len
}
return l return l
} }
func (rr *AAAA) len(off int, compression map[string]struct{}) int { func (rr *AAAA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
if len(rr.AAAA) != 0 { l += net.IPv6len // AAAA
l += net.IPv6len
}
return l return l
} }
func (rr *AFSDB) len(off int, compression map[string]struct{}) int { func (rr *AFSDB) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Subtype l += 2 // Subtype
l += domainNameLen(rr.Hostname, off+l, compression, false) l += len(rr.Hostname) + 1
return l return l
} }
func (rr *ANY) len(off int, compression map[string]struct{}) int { func (rr *ANY) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
return l return l
} }
func (rr *AVC) len(off int, compression map[string]struct{}) int { func (rr *AVC) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
for _, x := range rr.Txt { for _, x := range rr.Txt {
l += len(x) + 1 l += len(x) + 1
} }
return l return l
} }
func (rr *CAA) len(off int, compression map[string]struct{}) int { func (rr *CAA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Flag l++ // Flag
l += len(rr.Tag) + 1 l += len(rr.Tag) + 1
l += len(rr.Value) l += len(rr.Value)
return l return l
} }
func (rr *CERT) len(off int, compression map[string]struct{}) int { func (rr *CERT) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Type l += 2 // Type
l += 2 // KeyTag l += 2 // KeyTag
l++ // Algorithm l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.Certificate)) l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
return l return l
} }
func (rr *CNAME) len(off int, compression map[string]struct{}) int { func (rr *CNAME) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Target, off+l, compression, true) l += len(rr.Target) + 1
return l return l
} }
func (rr *DHCID) len(off int, compression map[string]struct{}) int { func (rr *DHCID) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += base64.StdEncoding.DecodedLen(len(rr.Digest)) l += base64.StdEncoding.DecodedLen(len(rr.Digest))
return l return l
} }
func (rr *DNAME) len(off int, compression map[string]struct{}) int { func (rr *DNAME) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Target, off+l, compression, false) l += len(rr.Target) + 1
return l return l
} }
func (rr *DNSKEY) len(off int, compression map[string]struct{}) int { func (rr *DNSKEY) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Flags l += 2 // Flags
l++ // Protocol l++ // Protocol
l++ // Algorithm l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l return l
} }
func (rr *DS) len(off int, compression map[string]struct{}) int { func (rr *DS) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // KeyTag l += 2 // KeyTag
l++ // Algorithm l++ // Algorithm
l++ // DigestType l++ // DigestType
l += len(rr.Digest)/2 + 1 l += len(rr.Digest)/2 + 1
return l return l
} }
func (rr *EID) len(off int, compression map[string]struct{}) int { func (rr *EID) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Endpoint)/2 + 1 l += len(rr.Endpoint)/2 + 1
return l return l
} }
func (rr *EUI48) len(off int, compression map[string]struct{}) int { func (rr *EUI48) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 6 // Address l += 6 // Address
return l return l
} }
func (rr *EUI64) len(off int, compression map[string]struct{}) int { func (rr *EUI64) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 8 // Address l += 8 // Address
return l return l
} }
func (rr *GID) len(off int, compression map[string]struct{}) int { func (rr *GID) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 4 // Gid l += 4 // Gid
return l return l
} }
func (rr *GPOS) len(off int, compression map[string]struct{}) int { func (rr *GPOS) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Longitude) + 1 l += len(rr.Longitude) + 1
l += len(rr.Latitude) + 1 l += len(rr.Latitude) + 1
l += len(rr.Altitude) + 1 l += len(rr.Altitude) + 1
return l return l
} }
func (rr *HINFO) len(off int, compression map[string]struct{}) int { func (rr *HINFO) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Cpu) + 1 l += len(rr.Cpu) + 1
l += len(rr.Os) + 1 l += len(rr.Os) + 1
return l return l
} }
func (rr *HIP) len(off int, compression map[string]struct{}) int { func (rr *HIP) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // HitLength l++ // HitLength
l++ // PublicKeyAlgorithm l++ // PublicKeyAlgorithm
l += 2 // PublicKeyLength l += 2 // PublicKeyLength
l += len(rr.Hit) / 2 l += len(rr.Hit)/2 + 1
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
for _, x := range rr.RendezvousServers { for _, x := range rr.RendezvousServers {
l += domainNameLen(x, off+l, compression, false) l += len(x) + 1
} }
return l return l
} }
func (rr *KX) len(off int, compression map[string]struct{}) int { func (rr *KX) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += domainNameLen(rr.Exchanger, off+l, compression, false) l += len(rr.Exchanger) + 1
return l return l
} }
func (rr *L32) len(off int, compression map[string]struct{}) int { func (rr *L32) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
if len(rr.Locator32) != 0 { l += net.IPv4len // Locator32
l += net.IPv4len
}
return l return l
} }
func (rr *L64) len(off int, compression map[string]struct{}) int { func (rr *L64) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += 8 // Locator64 l += 8 // Locator64
return l return l
} }
func (rr *LOC) len(off int, compression map[string]struct{}) int { func (rr *LOC) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Version l++ // Version
l++ // Size l++ // Size
l++ // HorizPre l++ // HorizPre
@ -391,139 +384,134 @@ func (rr *LOC) len(off int, compression map[string]struct{}) int {
l += 4 // Altitude l += 4 // Altitude
return l return l
} }
func (rr *LP) len(off int, compression map[string]struct{}) int { func (rr *LP) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += domainNameLen(rr.Fqdn, off+l, compression, false) l += len(rr.Fqdn) + 1
return l return l
} }
func (rr *MB) len(off int, compression map[string]struct{}) int { func (rr *MB) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Mb, off+l, compression, true) l += len(rr.Mb) + 1
return l return l
} }
func (rr *MD) len(off int, compression map[string]struct{}) int { func (rr *MD) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Md, off+l, compression, true) l += len(rr.Md) + 1
return l return l
} }
func (rr *MF) len(off int, compression map[string]struct{}) int { func (rr *MF) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Mf, off+l, compression, true) l += len(rr.Mf) + 1
return l return l
} }
func (rr *MG) len(off int, compression map[string]struct{}) int { func (rr *MG) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Mg, off+l, compression, true) l += len(rr.Mg) + 1
return l return l
} }
func (rr *MINFO) len(off int, compression map[string]struct{}) int { func (rr *MINFO) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Rmail, off+l, compression, true) l += len(rr.Rmail) + 1
l += domainNameLen(rr.Email, off+l, compression, true) l += len(rr.Email) + 1
return l return l
} }
func (rr *MR) len(off int, compression map[string]struct{}) int { func (rr *MR) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Mr, off+l, compression, true) l += len(rr.Mr) + 1
return l return l
} }
func (rr *MX) len(off int, compression map[string]struct{}) int { func (rr *MX) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += domainNameLen(rr.Mx, off+l, compression, true) l += len(rr.Mx) + 1
return l return l
} }
func (rr *NAPTR) len(off int, compression map[string]struct{}) int { func (rr *NAPTR) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Order l += 2 // Order
l += 2 // Preference l += 2 // Preference
l += len(rr.Flags) + 1 l += len(rr.Flags) + 1
l += len(rr.Service) + 1 l += len(rr.Service) + 1
l += len(rr.Regexp) + 1 l += len(rr.Regexp) + 1
l += domainNameLen(rr.Replacement, off+l, compression, false) l += len(rr.Replacement) + 1
return l return l
} }
func (rr *NID) len(off int, compression map[string]struct{}) int { func (rr *NID) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += 8 // NodeID l += 8 // NodeID
return l return l
} }
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int { func (rr *NIMLOC) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Locator)/2 + 1 l += len(rr.Locator)/2 + 1
return l return l
} }
func (rr *NINFO) len(off int, compression map[string]struct{}) int { func (rr *NINFO) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
for _, x := range rr.ZSData { for _, x := range rr.ZSData {
l += len(x) + 1 l += len(x) + 1
} }
return l return l
} }
func (rr *NS) len(off int, compression map[string]struct{}) int { func (rr *NS) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Ns, off+l, compression, true) l += len(rr.Ns) + 1
return l return l
} }
func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int { func (rr *NSAPPTR) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Ptr, off+l, compression, false) l += len(rr.Ptr) + 1
return l return l
} }
func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int { func (rr *NSEC3PARAM) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Hash l++ // Hash
l++ // Flags l++ // Flags
l += 2 // Iterations l += 2 // Iterations
l++ // SaltLength l++ // SaltLength
l += len(rr.Salt) / 2 l += len(rr.Salt)/2 + 1
return l return l
} }
func (rr *NULL) len(off int, compression map[string]struct{}) int { func (rr *OPENPGPKEY) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Data)
return l
}
func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l return l
} }
func (rr *PTR) len(off int, compression map[string]struct{}) int { func (rr *PTR) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Ptr, off+l, compression, true) l += len(rr.Ptr) + 1
return l return l
} }
func (rr *PX) len(off int, compression map[string]struct{}) int { func (rr *PX) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += domainNameLen(rr.Map822, off+l, compression, false) l += len(rr.Map822) + 1
l += domainNameLen(rr.Mapx400, off+l, compression, false) l += len(rr.Mapx400) + 1
return l return l
} }
func (rr *RFC3597) len(off int, compression map[string]struct{}) int { func (rr *RFC3597) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Rdata)/2 + 1 l += len(rr.Rdata)/2 + 1
return l return l
} }
func (rr *RKEY) len(off int, compression map[string]struct{}) int { func (rr *RKEY) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Flags l += 2 // Flags
l++ // Protocol l++ // Protocol
l++ // Algorithm l++ // Algorithm
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l return l
} }
func (rr *RP) len(off int, compression map[string]struct{}) int { func (rr *RP) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Mbox, off+l, compression, false) l += len(rr.Mbox) + 1
l += domainNameLen(rr.Txt, off+l, compression, false) l += len(rr.Txt) + 1
return l return l
} }
func (rr *RRSIG) len(off int, compression map[string]struct{}) int { func (rr *RRSIG) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // TypeCovered l += 2 // TypeCovered
l++ // Algorithm l++ // Algorithm
l++ // Labels l++ // Labels
@ -531,28 +519,28 @@ func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
l += 4 // Expiration l += 4 // Expiration
l += 4 // Inception l += 4 // Inception
l += 2 // KeyTag l += 2 // KeyTag
l += domainNameLen(rr.SignerName, off+l, compression, false) l += len(rr.SignerName) + 1
l += base64.StdEncoding.DecodedLen(len(rr.Signature)) l += base64.StdEncoding.DecodedLen(len(rr.Signature))
return l return l
} }
func (rr *RT) len(off int, compression map[string]struct{}) int { func (rr *RT) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Preference l += 2 // Preference
l += domainNameLen(rr.Host, off+l, compression, false) l += len(rr.Host) + 1
return l return l
} }
func (rr *SMIMEA) len(off int, compression map[string]struct{}) int { func (rr *SMIMEA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate)/2 + 1
return l return l
} }
func (rr *SOA) len(off int, compression map[string]struct{}) int { func (rr *SOA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Ns, off+l, compression, true) l += len(rr.Ns) + 1
l += domainNameLen(rr.Mbox, off+l, compression, true) l += len(rr.Mbox) + 1
l += 4 // Serial l += 4 // Serial
l += 4 // Refresh l += 4 // Refresh
l += 4 // Retry l += 4 // Retry
@ -560,322 +548,317 @@ func (rr *SOA) len(off int, compression map[string]struct{}) int {
l += 4 // Minttl l += 4 // Minttl
return l return l
} }
func (rr *SPF) len(off int, compression map[string]struct{}) int { func (rr *SPF) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
for _, x := range rr.Txt { for _, x := range rr.Txt {
l += len(x) + 1 l += len(x) + 1
} }
return l return l
} }
func (rr *SRV) len(off int, compression map[string]struct{}) int { func (rr *SRV) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Priority l += 2 // Priority
l += 2 // Weight l += 2 // Weight
l += 2 // Port l += 2 // Port
l += domainNameLen(rr.Target, off+l, compression, false) l += len(rr.Target) + 1
return l return l
} }
func (rr *SSHFP) len(off int, compression map[string]struct{}) int { func (rr *SSHFP) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Algorithm l++ // Algorithm
l++ // Type l++ // Type
l += len(rr.FingerPrint)/2 + 1 l += len(rr.FingerPrint)/2 + 1
return l return l
} }
func (rr *TA) len(off int, compression map[string]struct{}) int { func (rr *TA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // KeyTag l += 2 // KeyTag
l++ // Algorithm l++ // Algorithm
l++ // DigestType l++ // DigestType
l += len(rr.Digest)/2 + 1 l += len(rr.Digest)/2 + 1
return l return l
} }
func (rr *TALINK) len(off int, compression map[string]struct{}) int { func (rr *TALINK) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.PreviousName, off+l, compression, false) l += len(rr.PreviousName) + 1
l += domainNameLen(rr.NextName, off+l, compression, false) l += len(rr.NextName) + 1
return l return l
} }
func (rr *TKEY) len(off int, compression map[string]struct{}) int { func (rr *TKEY) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Algorithm, off+l, compression, false) l += len(rr.Algorithm) + 1
l += 4 // Inception l += 4 // Inception
l += 4 // Expiration l += 4 // Expiration
l += 2 // Mode l += 2 // Mode
l += 2 // Error l += 2 // Error
l += 2 // KeySize l += 2 // KeySize
l += len(rr.Key) / 2 l += len(rr.Key) + 1
l += 2 // OtherLen l += 2 // OtherLen
l += len(rr.OtherData) / 2 l += len(rr.OtherData) + 1
return l return l
} }
func (rr *TLSA) len(off int, compression map[string]struct{}) int { func (rr *TLSA) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate)/2 + 1
return l return l
} }
func (rr *TSIG) len(off int, compression map[string]struct{}) int { func (rr *TSIG) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += domainNameLen(rr.Algorithm, off+l, compression, false) l += len(rr.Algorithm) + 1
l += 6 // TimeSigned l += 6 // TimeSigned
l += 2 // Fudge l += 2 // Fudge
l += 2 // MACSize l += 2 // MACSize
l += len(rr.MAC) / 2 l += len(rr.MAC)/2 + 1
l += 2 // OrigId l += 2 // OrigId
l += 2 // Error l += 2 // Error
l += 2 // OtherLen l += 2 // OtherLen
l += len(rr.OtherData) / 2 l += len(rr.OtherData)/2 + 1
return l return l
} }
func (rr *TXT) len(off int, compression map[string]struct{}) int { func (rr *TXT) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
for _, x := range rr.Txt { for _, x := range rr.Txt {
l += len(x) + 1 l += len(x) + 1
} }
return l return l
} }
func (rr *UID) len(off int, compression map[string]struct{}) int { func (rr *UID) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 4 // Uid l += 4 // Uid
return l return l
} }
func (rr *UINFO) len(off int, compression map[string]struct{}) int { func (rr *UINFO) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.Uinfo) + 1 l += len(rr.Uinfo) + 1
return l return l
} }
func (rr *URI) len(off int, compression map[string]struct{}) int { func (rr *URI) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += 2 // Priority l += 2 // Priority
l += 2 // Weight l += 2 // Weight
l += len(rr.Target) l += len(rr.Target)
return l return l
} }
func (rr *X25) len(off int, compression map[string]struct{}) int { func (rr *X25) len() int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len()
l += len(rr.PSDNAddress) + 1 l += len(rr.PSDNAddress) + 1
return l return l
} }
// copy() functions // copy() functions
func (rr *A) copy() RR { func (rr *A) copy() RR {
return &A{rr.Hdr, copyIP(rr.A)} return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)}
} }
func (rr *AAAA) copy() RR { func (rr *AAAA) copy() RR {
return &AAAA{rr.Hdr, copyIP(rr.AAAA)} return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)}
} }
func (rr *AFSDB) copy() RR { func (rr *AFSDB) copy() RR {
return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname} return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname}
} }
func (rr *ANY) copy() RR { func (rr *ANY) copy() RR {
return &ANY{rr.Hdr} return &ANY{*rr.Hdr.copyHeader()}
} }
func (rr *AVC) copy() RR { func (rr *AVC) copy() RR {
Txt := make([]string, len(rr.Txt)) Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt) copy(Txt, rr.Txt)
return &AVC{rr.Hdr, Txt} return &AVC{*rr.Hdr.copyHeader(), Txt}
} }
func (rr *CAA) copy() RR { func (rr *CAA) copy() RR {
return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value} return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
} }
func (rr *CERT) copy() RR { func (rr *CERT) copy() RR {
return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
} }
func (rr *CNAME) copy() RR { func (rr *CNAME) copy() RR {
return &CNAME{rr.Hdr, rr.Target} return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
} }
func (rr *CSYNC) copy() RR { func (rr *CSYNC) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap)) TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap) copy(TypeBitMap, rr.TypeBitMap)
return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap} return &CSYNC{*rr.Hdr.copyHeader(), rr.Serial, rr.Flags, TypeBitMap}
} }
func (rr *DHCID) copy() RR { func (rr *DHCID) copy() RR {
return &DHCID{rr.Hdr, rr.Digest} return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
} }
func (rr *DNAME) copy() RR { func (rr *DNAME) copy() RR {
return &DNAME{rr.Hdr, rr.Target} return &DNAME{*rr.Hdr.copyHeader(), rr.Target}
} }
func (rr *DNSKEY) copy() RR { func (rr *DNSKEY) copy() RR {
return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
} }
func (rr *DS) copy() RR { func (rr *DS) copy() RR {
return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
} }
func (rr *EID) copy() RR { func (rr *EID) copy() RR {
return &EID{rr.Hdr, rr.Endpoint} return &EID{*rr.Hdr.copyHeader(), rr.Endpoint}
} }
func (rr *EUI48) copy() RR { func (rr *EUI48) copy() RR {
return &EUI48{rr.Hdr, rr.Address} return &EUI48{*rr.Hdr.copyHeader(), rr.Address}
} }
func (rr *EUI64) copy() RR { func (rr *EUI64) copy() RR {
return &EUI64{rr.Hdr, rr.Address} return &EUI64{*rr.Hdr.copyHeader(), rr.Address}
} }
func (rr *GID) copy() RR { func (rr *GID) copy() RR {
return &GID{rr.Hdr, rr.Gid} return &GID{*rr.Hdr.copyHeader(), rr.Gid}
} }
func (rr *GPOS) copy() RR { func (rr *GPOS) copy() RR {
return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude} return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude}
} }
func (rr *HINFO) copy() RR { func (rr *HINFO) copy() RR {
return &HINFO{rr.Hdr, rr.Cpu, rr.Os} return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os}
} }
func (rr *HIP) copy() RR { func (rr *HIP) copy() RR {
RendezvousServers := make([]string, len(rr.RendezvousServers)) RendezvousServers := make([]string, len(rr.RendezvousServers))
copy(RendezvousServers, rr.RendezvousServers) copy(RendezvousServers, rr.RendezvousServers)
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
} }
func (rr *KX) copy() RR { func (rr *KX) copy() RR {
return &KX{rr.Hdr, rr.Preference, rr.Exchanger} return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger}
} }
func (rr *L32) copy() RR { func (rr *L32) copy() RR {
return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)} return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)}
} }
func (rr *L64) copy() RR { func (rr *L64) copy() RR {
return &L64{rr.Hdr, rr.Preference, rr.Locator64} return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64}
} }
func (rr *LOC) copy() RR { func (rr *LOC) copy() RR {
return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude} return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
} }
func (rr *LP) copy() RR { func (rr *LP) copy() RR {
return &LP{rr.Hdr, rr.Preference, rr.Fqdn} return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn}
} }
func (rr *MB) copy() RR { func (rr *MB) copy() RR {
return &MB{rr.Hdr, rr.Mb} return &MB{*rr.Hdr.copyHeader(), rr.Mb}
} }
func (rr *MD) copy() RR { func (rr *MD) copy() RR {
return &MD{rr.Hdr, rr.Md} return &MD{*rr.Hdr.copyHeader(), rr.Md}
} }
func (rr *MF) copy() RR { func (rr *MF) copy() RR {
return &MF{rr.Hdr, rr.Mf} return &MF{*rr.Hdr.copyHeader(), rr.Mf}
} }
func (rr *MG) copy() RR { func (rr *MG) copy() RR {
return &MG{rr.Hdr, rr.Mg} return &MG{*rr.Hdr.copyHeader(), rr.Mg}
} }
func (rr *MINFO) copy() RR { func (rr *MINFO) copy() RR {
return &MINFO{rr.Hdr, rr.Rmail, rr.Email} return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email}
} }
func (rr *MR) copy() RR { func (rr *MR) copy() RR {
return &MR{rr.Hdr, rr.Mr} return &MR{*rr.Hdr.copyHeader(), rr.Mr}
} }
func (rr *MX) copy() RR { func (rr *MX) copy() RR {
return &MX{rr.Hdr, rr.Preference, rr.Mx} return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx}
} }
func (rr *NAPTR) copy() RR { func (rr *NAPTR) copy() RR {
return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement} return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
} }
func (rr *NID) copy() RR { func (rr *NID) copy() RR {
return &NID{rr.Hdr, rr.Preference, rr.NodeID} return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID}
} }
func (rr *NIMLOC) copy() RR { func (rr *NIMLOC) copy() RR {
return &NIMLOC{rr.Hdr, rr.Locator} return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator}
} }
func (rr *NINFO) copy() RR { func (rr *NINFO) copy() RR {
ZSData := make([]string, len(rr.ZSData)) ZSData := make([]string, len(rr.ZSData))
copy(ZSData, rr.ZSData) copy(ZSData, rr.ZSData)
return &NINFO{rr.Hdr, ZSData} return &NINFO{*rr.Hdr.copyHeader(), ZSData}
} }
func (rr *NS) copy() RR { func (rr *NS) copy() RR {
return &NS{rr.Hdr, rr.Ns} return &NS{*rr.Hdr.copyHeader(), rr.Ns}
} }
func (rr *NSAPPTR) copy() RR { func (rr *NSAPPTR) copy() RR {
return &NSAPPTR{rr.Hdr, rr.Ptr} return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr}
} }
func (rr *NSEC) copy() RR { func (rr *NSEC) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap)) TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap) copy(TypeBitMap, rr.TypeBitMap)
return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap} return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap}
} }
func (rr *NSEC3) copy() RR { func (rr *NSEC3) copy() RR {
TypeBitMap := make([]uint16, len(rr.TypeBitMap)) TypeBitMap := make([]uint16, len(rr.TypeBitMap))
copy(TypeBitMap, rr.TypeBitMap) copy(TypeBitMap, rr.TypeBitMap)
return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap} return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
} }
func (rr *NSEC3PARAM) copy() RR { func (rr *NSEC3PARAM) copy() RR {
return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt} return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
}
func (rr *NULL) copy() RR {
return &NULL{rr.Hdr, rr.Data}
} }
func (rr *OPENPGPKEY) copy() RR { func (rr *OPENPGPKEY) copy() RR {
return &OPENPGPKEY{rr.Hdr, rr.PublicKey} return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey}
} }
func (rr *OPT) copy() RR { func (rr *OPT) copy() RR {
Option := make([]EDNS0, len(rr.Option)) Option := make([]EDNS0, len(rr.Option))
for i, e := range rr.Option { copy(Option, rr.Option)
Option[i] = e.copy() return &OPT{*rr.Hdr.copyHeader(), Option}
}
return &OPT{rr.Hdr, Option}
} }
func (rr *PTR) copy() RR { func (rr *PTR) copy() RR {
return &PTR{rr.Hdr, rr.Ptr} return &PTR{*rr.Hdr.copyHeader(), rr.Ptr}
} }
func (rr *PX) copy() RR { func (rr *PX) copy() RR {
return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400} return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400}
} }
func (rr *RFC3597) copy() RR { func (rr *RFC3597) copy() RR {
return &RFC3597{rr.Hdr, rr.Rdata} return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata}
} }
func (rr *RKEY) copy() RR { func (rr *RKEY) copy() RR {
return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
} }
func (rr *RP) copy() RR { func (rr *RP) copy() RR {
return &RP{rr.Hdr, rr.Mbox, rr.Txt} return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt}
} }
func (rr *RRSIG) copy() RR { func (rr *RRSIG) copy() RR {
return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature} return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
} }
func (rr *RT) copy() RR { func (rr *RT) copy() RR {
return &RT{rr.Hdr, rr.Preference, rr.Host} return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host}
} }
func (rr *SMIMEA) copy() RR { func (rr *SMIMEA) copy() RR {
return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} return &SMIMEA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
} }
func (rr *SOA) copy() RR { func (rr *SOA) copy() RR {
return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl} return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
} }
func (rr *SPF) copy() RR { func (rr *SPF) copy() RR {
Txt := make([]string, len(rr.Txt)) Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt) copy(Txt, rr.Txt)
return &SPF{rr.Hdr, Txt} return &SPF{*rr.Hdr.copyHeader(), Txt}
} }
func (rr *SRV) copy() RR { func (rr *SRV) copy() RR {
return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target} return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
} }
func (rr *SSHFP) copy() RR { func (rr *SSHFP) copy() RR {
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint} return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
} }
func (rr *TA) copy() RR { func (rr *TA) copy() RR {
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
} }
func (rr *TALINK) copy() RR { func (rr *TALINK) copy() RR {
return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName} return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName}
} }
func (rr *TKEY) copy() RR { func (rr *TKEY) copy() RR {
return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData} return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
} }
func (rr *TLSA) copy() RR { func (rr *TLSA) copy() RR {
return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
} }
func (rr *TSIG) copy() RR { func (rr *TSIG) copy() RR {
return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData} return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
} }
func (rr *TXT) copy() RR { func (rr *TXT) copy() RR {
Txt := make([]string, len(rr.Txt)) Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt) copy(Txt, rr.Txt)
return &TXT{rr.Hdr, Txt} return &TXT{*rr.Hdr.copyHeader(), Txt}
} }
func (rr *UID) copy() RR { func (rr *UID) copy() RR {
return &UID{rr.Hdr, rr.Uid} return &UID{*rr.Hdr.copyHeader(), rr.Uid}
} }
func (rr *UINFO) copy() RR { func (rr *UINFO) copy() RR {
return &UINFO{rr.Hdr, rr.Uinfo} return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo}
} }
func (rr *URI) copy() RR { func (rr *URI) copy() RR {
return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target} return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target}
} }
func (rr *X25) copy() RR { func (rr *X25) copy() RR {
return &X25{rr.Hdr, rr.PSDNAddress} return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress}
} }

41
vendor/golang.org/x/net/bpf/asm.go generated vendored
View File

@ -1,41 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import "fmt"
// Assemble converts insts into raw instructions suitable for loading
// into a BPF virtual machine.
//
// Currently, no optimization is attempted, the assembled program flow
// is exactly as provided.
func Assemble(insts []Instruction) ([]RawInstruction, error) {
ret := make([]RawInstruction, len(insts))
var err error
for i, inst := range insts {
ret[i], err = inst.Assemble()
if err != nil {
return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
}
}
return ret, nil
}
// Disassemble attempts to parse raw back into
// Instructions. Unrecognized RawInstructions are assumed to be an
// extension not implemented by this package, and are passed through
// unchanged to the output. The allDecoded value reports whether insts
// contains no RawInstructions.
func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
insts = make([]Instruction, len(raw))
allDecoded = true
for i, r := range raw {
insts[i] = r.Disassemble()
if _, ok := insts[i].(RawInstruction); ok {
allDecoded = false
}
}
return insts, allDecoded
}

View File

@ -1,222 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
// A Register is a register of the BPF virtual machine.
type Register uint16
const (
// RegA is the accumulator register. RegA is always the
// destination register of ALU operations.
RegA Register = iota
// RegX is the indirection register, used by LoadIndirect
// operations.
RegX
)
// An ALUOp is an arithmetic or logic operation.
type ALUOp uint16
// ALU binary operation types.
const (
ALUOpAdd ALUOp = iota << 4
ALUOpSub
ALUOpMul
ALUOpDiv
ALUOpOr
ALUOpAnd
ALUOpShiftLeft
ALUOpShiftRight
aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
ALUOpMod
ALUOpXor
)
// A JumpTest is a comparison operator used in conditional jumps.
type JumpTest uint16
// Supported operators for conditional jumps.
// K can be RegX for JumpIfX
const (
// K == A
JumpEqual JumpTest = iota
// K != A
JumpNotEqual
// K > A
JumpGreaterThan
// K < A
JumpLessThan
// K >= A
JumpGreaterOrEqual
// K <= A
JumpLessOrEqual
// K & A != 0
JumpBitsSet
// K & A == 0
JumpBitsNotSet
)
// An Extension is a function call provided by the kernel that
// performs advanced operations that are expensive or impossible
// within the BPF virtual machine.
//
// Extensions are only implemented by the Linux kernel.
//
// TODO: should we prune this list? Some of these extensions seem
// either broken or near-impossible to use correctly, whereas other
// (len, random, ifindex) are quite useful.
type Extension int
// Extension functions available in the Linux kernel.
const (
// extOffset is the negative maximum number of instructions used
// to load instructions by overloading the K argument.
extOffset = -0x1000
// ExtLen returns the length of the packet.
ExtLen Extension = 1
// ExtProto returns the packet's L3 protocol type.
ExtProto Extension = 0
// ExtType returns the packet's type (skb->pkt_type in the kernel)
//
// TODO: better documentation. How nice an API do we want to
// provide for these esoteric extensions?
ExtType Extension = 4
// ExtPayloadOffset returns the offset of the packet payload, or
// the first protocol header that the kernel does not know how to
// parse.
ExtPayloadOffset Extension = 52
// ExtInterfaceIndex returns the index of the interface on which
// the packet was received.
ExtInterfaceIndex Extension = 8
// ExtNetlinkAttr returns the netlink attribute of type X at
// offset A.
ExtNetlinkAttr Extension = 12
// ExtNetlinkAttrNested returns the nested netlink attribute of
// type X at offset A.
ExtNetlinkAttrNested Extension = 16
// ExtMark returns the packet's mark value.
ExtMark Extension = 20
// ExtQueue returns the packet's assigned hardware queue.
ExtQueue Extension = 24
// ExtLinkLayerType returns the packet's hardware address type
// (e.g. Ethernet, Infiniband).
ExtLinkLayerType Extension = 28
// ExtRXHash returns the packets receive hash.
//
// TODO: figure out what this rxhash actually is.
ExtRXHash Extension = 32
// ExtCPUID returns the ID of the CPU processing the current
// packet.
ExtCPUID Extension = 36
// ExtVLANTag returns the packet's VLAN tag.
ExtVLANTag Extension = 44
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
// tag.
//
// TODO: I think this might be a lie: it reads bit 0x1000 of the
// VLAN header, which changed meaning in recent revisions of the
// spec - this extension may now return meaningless information.
ExtVLANTagPresent Extension = 48
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
// other value if no VLAN information is present.
ExtVLANProto Extension = 60
// ExtRand returns a uniformly random uint32.
ExtRand Extension = 56
)
// The following gives names to various bit patterns used in opcode construction.
const (
opMaskCls uint16 = 0x7
// opClsLoad masks
opMaskLoadDest = 0x01
opMaskLoadWidth = 0x18
opMaskLoadMode = 0xe0
// opClsALU & opClsJump
opMaskOperand = 0x08
opMaskOperator = 0xf0
)
const (
// +---------------+-----------------+---+---+---+
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
// +---------------+-----------------+---+---+---+
opClsLoadA uint16 = iota
// +---------------+-----------------+---+---+---+
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
// +---------------+-----------------+---+---+---+
opClsLoadX
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
// +---+---+---+---+---+---+---+---+
opClsStoreA
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
// +---+---+---+---+---+---+---+---+
opClsStoreX
// +---------------+-----------------+---+---+---+
// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
// +---------------+-----------------+---+---+---+
opClsALU
// +-----------------------------+---+---+---+---+
// | TestOperator (4b) | 0 | 1 | 0 | 1 |
// +-----------------------------+---+---+---+---+
opClsJump
// +---+-------------------------+---+---+---+---+
// | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
// +---+-------------------------+---+---+---+---+
opClsReturn
// +---+-------------------------+---+---+---+---+
// | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
// +---+-------------------------+---+---+---+---+
opClsMisc
)
const (
opAddrModeImmediate uint16 = iota << 5
opAddrModeAbsolute
opAddrModeIndirect
opAddrModeScratch
opAddrModePacketLen // actually an extension, not an addressing mode.
opAddrModeMemShift
)
const (
opLoadWidth4 uint16 = iota << 3
opLoadWidth2
opLoadWidth1
)
// Operand for ALU and Jump instructions
type opOperand uint16
// Supported operand sources.
const (
opOperandConstant opOperand = iota << 3
opOperandX
)
// An jumpOp is a conditional jump condition.
type jumpOp uint16
// Supported jump conditions.
const (
opJumpAlways jumpOp = iota << 4
opJumpEqual
opJumpGT
opJumpGE
opJumpSet
)
const (
opRetSrcConstant uint16 = iota << 4
opRetSrcA
)
const (
opMiscTAX = 0x00
opMiscTXA = 0x80
)

82
vendor/golang.org/x/net/bpf/doc.go generated vendored
View File

@ -1,82 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package bpf implements marshaling and unmarshaling of programs for the
Berkeley Packet Filter virtual machine, and provides a Go implementation
of the virtual machine.
BPF's main use is to specify a packet filter for network taps, so that
the kernel doesn't have to expensively copy every packet it sees to
userspace. However, it's been repurposed to other areas where running
user code in-kernel is needed. For example, Linux's seccomp uses BPF
to apply security policies to system calls. For simplicity, this
documentation refers only to packets, but other uses of BPF have their
own data payloads.
BPF programs run in a restricted virtual machine. It has almost no
access to kernel functions, and while conditional branches are
allowed, they can only jump forwards, to guarantee that there are no
infinite loops.
The virtual machine
The BPF VM is an accumulator machine. Its main register, called
register A, is an implicit source and destination in all arithmetic
and logic operations. The machine also has 16 scratch registers for
temporary storage, and an indirection register (register X) for
indirect memory access. All registers are 32 bits wide.
Each run of a BPF program is given one packet, which is placed in the
VM's read-only "main memory". LoadAbsolute and LoadIndirect
instructions can fetch up to 32 bits at a time into register A for
examination.
The goal of a BPF program is to produce and return a verdict (uint32),
which tells the kernel what to do with the packet. In the context of
packet filtering, the returned value is the number of bytes of the
packet to forward to userspace, or 0 to ignore the packet. Other
contexts like seccomp define their own return values.
In order to simplify programs, attempts to read past the end of the
packet terminate the program execution with a verdict of 0 (ignore
packet). This means that the vast majority of BPF programs don't need
to do any explicit bounds checking.
In addition to the bytes of the packet, some BPF programs have access
to extensions, which are essentially calls to kernel utility
functions. Currently, the only extensions supported by this package
are the Linux packet filter extensions.
Examples
This packet filter selects all ARP packets.
bpf.Assemble([]bpf.Instruction{
// Load "EtherType" field from the ethernet header.
bpf.LoadAbsolute{Off: 12, Size: 2},
// Skip over the next instruction if EtherType is not ARP.
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
// Verdict is "send up to 4k of the packet to userspace."
bpf.RetConstant{Val: 4096},
// Verdict is "ignore packet."
bpf.RetConstant{Val: 0},
})
This packet filter captures a random 1% sample of traffic.
bpf.Assemble([]bpf.Instruction{
// Get a 32-bit random number from the Linux kernel.
bpf.LoadExtension{Num: bpf.ExtRand},
// 1% dice roll?
bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
// Capture.
bpf.RetConstant{Val: 4096},
// Ignore.
bpf.RetConstant{Val: 0},
})
*/
package bpf // import "golang.org/x/net/bpf"

View File

@ -1,726 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import "fmt"
// An Instruction is one instruction executed by the BPF virtual
// machine.
type Instruction interface {
// Assemble assembles the Instruction into a RawInstruction.
Assemble() (RawInstruction, error)
}
// A RawInstruction is a raw BPF virtual machine instruction.
type RawInstruction struct {
// Operation to execute.
Op uint16
// For conditional jump instructions, the number of instructions
// to skip if the condition is true/false.
Jt uint8
Jf uint8
// Constant parameter. The meaning depends on the Op.
K uint32
}
// Assemble implements the Instruction Assemble method.
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
// Disassemble parses ri into an Instruction and returns it. If ri is
// not recognized by this package, ri itself is returned.
func (ri RawInstruction) Disassemble() Instruction {
switch ri.Op & opMaskCls {
case opClsLoadA, opClsLoadX:
reg := Register(ri.Op & opMaskLoadDest)
sz := 0
switch ri.Op & opMaskLoadWidth {
case opLoadWidth4:
sz = 4
case opLoadWidth2:
sz = 2
case opLoadWidth1:
sz = 1
default:
return ri
}
switch ri.Op & opMaskLoadMode {
case opAddrModeImmediate:
if sz != 4 {
return ri
}
return LoadConstant{Dst: reg, Val: ri.K}
case opAddrModeScratch:
if sz != 4 || ri.K > 15 {
return ri
}
return LoadScratch{Dst: reg, N: int(ri.K)}
case opAddrModeAbsolute:
if ri.K > extOffset+0xffffffff {
return LoadExtension{Num: Extension(-extOffset + ri.K)}
}
return LoadAbsolute{Size: sz, Off: ri.K}
case opAddrModeIndirect:
return LoadIndirect{Size: sz, Off: ri.K}
case opAddrModePacketLen:
if sz != 4 {
return ri
}
return LoadExtension{Num: ExtLen}
case opAddrModeMemShift:
return LoadMemShift{Off: ri.K}
default:
return ri
}
case opClsStoreA:
if ri.Op != opClsStoreA || ri.K > 15 {
return ri
}
return StoreScratch{Src: RegA, N: int(ri.K)}
case opClsStoreX:
if ri.Op != opClsStoreX || ri.K > 15 {
return ri
}
return StoreScratch{Src: RegX, N: int(ri.K)}
case opClsALU:
switch op := ALUOp(ri.Op & opMaskOperator); op {
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
switch operand := opOperand(ri.Op & opMaskOperand); operand {
case opOperandX:
return ALUOpX{Op: op}
case opOperandConstant:
return ALUOpConstant{Op: op, Val: ri.K}
default:
return ri
}
case aluOpNeg:
return NegateA{}
default:
return ri
}
case opClsJump:
switch op := jumpOp(ri.Op & opMaskOperator); op {
case opJumpAlways:
return Jump{Skip: ri.K}
case opJumpEqual, opJumpGT, opJumpGE, opJumpSet:
cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf)
switch operand := opOperand(ri.Op & opMaskOperand); operand {
case opOperandX:
return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse}
case opOperandConstant:
return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse}
default:
return ri
}
default:
return ri
}
case opClsReturn:
switch ri.Op {
case opClsReturn | opRetSrcA:
return RetA{}
case opClsReturn | opRetSrcConstant:
return RetConstant{Val: ri.K}
default:
return ri
}
case opClsMisc:
switch ri.Op {
case opClsMisc | opMiscTAX:
return TAX{}
case opClsMisc | opMiscTXA:
return TXA{}
default:
return ri
}
default:
panic("unreachable") // switch is exhaustive on the bit pattern
}
}
func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) {
var test JumpTest
// Decode "fake" jump conditions that don't appear in machine code
// Ensures the Assemble -> Disassemble stage recreates the same instructions
// See https://github.com/golang/go/issues/18470
if skipTrue == 0 {
switch op {
case opJumpEqual:
test = JumpNotEqual
case opJumpGT:
test = JumpLessOrEqual
case opJumpGE:
test = JumpLessThan
case opJumpSet:
test = JumpBitsNotSet
}
return test, skipFalse, 0
}
switch op {
case opJumpEqual:
test = JumpEqual
case opJumpGT:
test = JumpGreaterThan
case opJumpGE:
test = JumpGreaterOrEqual
case opJumpSet:
test = JumpBitsSet
}
return test, skipTrue, skipFalse
}
// LoadConstant loads Val into register Dst.
type LoadConstant struct {
Dst Register
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a LoadConstant) Assemble() (RawInstruction, error) {
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
}
// String returns the instruction in assembler notation.
func (a LoadConstant) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld #%d", a.Val)
case RegX:
return fmt.Sprintf("ldx #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadScratch loads scratch[N] into register Dst.
type LoadScratch struct {
Dst Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a LoadScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
}
// String returns the instruction in assembler notation.
func (a LoadScratch) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld M[%d]", a.N)
case RegX:
return fmt.Sprintf("ldx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
// register A.
type LoadAbsolute struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadAbsolute) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [%d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [%d]", a.Off)
case 4: // word
if a.Off > extOffset+0xffffffff {
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
}
return fmt.Sprintf("ld [%d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
// into register A.
type LoadIndirect struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadIndirect) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadIndirect) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [x + %d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [x + %d]", a.Off)
case 4: // word
return fmt.Sprintf("ld [x + %d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
// by 4 and stores the result in register X.
//
// This instruction is mainly useful to load into X the length of an
// IPv4 packet header in a single instruction, rather than have to do
// the arithmetic on the header's first byte by hand.
type LoadMemShift struct {
Off uint32
}
// Assemble implements the Instruction Assemble method.
func (a LoadMemShift) Assemble() (RawInstruction, error) {
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadMemShift) String() string {
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
}
// LoadExtension invokes a linux-specific extension and stores the
// result in register A.
type LoadExtension struct {
Num Extension
}
// Assemble implements the Instruction Assemble method.
func (a LoadExtension) Assemble() (RawInstruction, error) {
if a.Num == ExtLen {
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
}
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
}
// String returns the instruction in assembler notation.
func (a LoadExtension) String() string {
switch a.Num {
case ExtLen:
return "ld #len"
case ExtProto:
return "ld #proto"
case ExtType:
return "ld #type"
case ExtPayloadOffset:
return "ld #poff"
case ExtInterfaceIndex:
return "ld #ifidx"
case ExtNetlinkAttr:
return "ld #nla"
case ExtNetlinkAttrNested:
return "ld #nlan"
case ExtMark:
return "ld #mark"
case ExtQueue:
return "ld #queue"
case ExtLinkLayerType:
return "ld #hatype"
case ExtRXHash:
return "ld #rxhash"
case ExtCPUID:
return "ld #cpu"
case ExtVLANTag:
return "ld #vlan_tci"
case ExtVLANTagPresent:
return "ld #vlan_avail"
case ExtVLANProto:
return "ld #vlan_tpid"
case ExtRand:
return "ld #rand"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// StoreScratch stores register Src into scratch[N].
type StoreScratch struct {
Src Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a StoreScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
var op uint16
switch a.Src {
case RegA:
op = opClsStoreA
case RegX:
op = opClsStoreX
default:
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
}
return RawInstruction{
Op: op,
K: uint32(a.N),
}, nil
}
// String returns the instruction in assembler notation.
func (a StoreScratch) String() string {
switch a.Src {
case RegA:
return fmt.Sprintf("st M[%d]", a.N)
case RegX:
return fmt.Sprintf("stx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpConstant executes A = A <Op> Val.
type ALUOpConstant struct {
Op ALUOp
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op),
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpConstant) String() string {
switch a.Op {
case ALUOpAdd:
return fmt.Sprintf("add #%d", a.Val)
case ALUOpSub:
return fmt.Sprintf("sub #%d", a.Val)
case ALUOpMul:
return fmt.Sprintf("mul #%d", a.Val)
case ALUOpDiv:
return fmt.Sprintf("div #%d", a.Val)
case ALUOpMod:
return fmt.Sprintf("mod #%d", a.Val)
case ALUOpAnd:
return fmt.Sprintf("and #%d", a.Val)
case ALUOpOr:
return fmt.Sprintf("or #%d", a.Val)
case ALUOpXor:
return fmt.Sprintf("xor #%d", a.Val)
case ALUOpShiftLeft:
return fmt.Sprintf("lsh #%d", a.Val)
case ALUOpShiftRight:
return fmt.Sprintf("rsh #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpX executes A = A <Op> X
type ALUOpX struct {
Op ALUOp
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(opOperandX) | uint16(a.Op),
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpX) String() string {
switch a.Op {
case ALUOpAdd:
return "add x"
case ALUOpSub:
return "sub x"
case ALUOpMul:
return "mul x"
case ALUOpDiv:
return "div x"
case ALUOpMod:
return "mod x"
case ALUOpAnd:
return "and x"
case ALUOpOr:
return "or x"
case ALUOpXor:
return "xor x"
case ALUOpShiftLeft:
return "lsh x"
case ALUOpShiftRight:
return "rsh x"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// NegateA executes A = -A.
type NegateA struct{}
// Assemble implements the Instruction Assemble method.
func (a NegateA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(aluOpNeg),
}, nil
}
// String returns the instruction in assembler notation.
func (a NegateA) String() string {
return fmt.Sprintf("neg")
}
// Jump skips the following Skip instructions in the program.
type Jump struct {
Skip uint32
}
// Assemble implements the Instruction Assemble method.
func (a Jump) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsJump | uint16(opJumpAlways),
K: a.Skip,
}, nil
}
// String returns the instruction in assembler notation.
func (a Jump) String() string {
return fmt.Sprintf("ja %d", a.Skip)
}
// JumpIf skips the following Skip instructions in the program if A
// <Cond> Val is true.
type JumpIf struct {
Cond JumpTest
Val uint32
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIf) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIf) String() string {
return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse)
}
// JumpIfX skips the following Skip instructions in the program if A
// <Cond> X is true.
type JumpIfX struct {
Cond JumpTest
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIfX) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIfX) String() string {
return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse)
}
// jumpToRaw assembles a jump instruction into a RawInstruction
func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) {
var (
cond jumpOp
flip bool
)
switch test {
case JumpEqual:
cond = opJumpEqual
case JumpNotEqual:
cond, flip = opJumpEqual, true
case JumpGreaterThan:
cond = opJumpGT
case JumpLessThan:
cond, flip = opJumpGE, true
case JumpGreaterOrEqual:
cond = opJumpGE
case JumpLessOrEqual:
cond, flip = opJumpGT, true
case JumpBitsSet:
cond = opJumpSet
case JumpBitsNotSet:
cond, flip = opJumpSet, true
default:
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test)
}
jt, jf := skipTrue, skipFalse
if flip {
jt, jf = jf, jt
}
return RawInstruction{
Op: opClsJump | uint16(cond) | uint16(operand),
Jt: jt,
Jf: jf,
K: k,
}, nil
}
// jumpToString converts a jump instruction to assembler notation
func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string {
switch cond {
// K == A
case JumpEqual:
return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq")
// K != A
case JumpNotEqual:
return fmt.Sprintf("jneq %s,%d", operand, skipTrue)
// K > A
case JumpGreaterThan:
return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle")
// K < A
case JumpLessThan:
return fmt.Sprintf("jlt %s,%d", operand, skipTrue)
// K >= A
case JumpGreaterOrEqual:
return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt")
// K <= A
case JumpLessOrEqual:
return fmt.Sprintf("jle %s,%d", operand, skipTrue)
// K & A != 0
case JumpBitsSet:
if skipFalse > 0 {
return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse)
}
return fmt.Sprintf("jset %s,%d", operand, skipTrue)
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
case JumpBitsNotSet:
return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue)
default:
return fmt.Sprintf("unknown JumpTest %#v", cond)
}
}
func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string {
if skipTrue > 0 {
if skipFalse > 0 {
return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse)
}
return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue)
}
return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse)
}
// RetA exits the BPF program, returning the value of register A.
type RetA struct{}
// Assemble implements the Instruction Assemble method.
func (a RetA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsReturn | opRetSrcA,
}, nil
}
// String returns the instruction in assembler notation.
func (a RetA) String() string {
return fmt.Sprintf("ret a")
}
// RetConstant exits the BPF program, returning a constant value.
type RetConstant struct {
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a RetConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsReturn | opRetSrcConstant,
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a RetConstant) String() string {
return fmt.Sprintf("ret #%d", a.Val)
}
// TXA copies the value of register X to register A.
type TXA struct{}
// Assemble implements the Instruction Assemble method.
func (a TXA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTXA,
}, nil
}
// String returns the instruction in assembler notation.
func (a TXA) String() string {
return fmt.Sprintf("txa")
}
// TAX copies the value of register A to register X.
type TAX struct{}
// Assemble implements the Instruction Assemble method.
func (a TAX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTAX,
}, nil
}
// String returns the instruction in assembler notation.
func (a TAX) String() string {
return fmt.Sprintf("tax")
}
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
var (
cls uint16
sz uint16
)
switch dst {
case RegA:
cls = opClsLoadA
case RegX:
cls = opClsLoadX
default:
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
}
switch loadSize {
case 1:
sz = opLoadWidth1
case 2:
sz = opLoadWidth2
case 4:
sz = opLoadWidth4
default:
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
}
return RawInstruction{
Op: cls | sz | mode,
K: k,
}, nil
}

View File

@ -1,10 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
// A Setter is a type which can attach a compiled BPF filter to itself.
type Setter interface {
SetBPF(filter []RawInstruction) error
}

150
vendor/golang.org/x/net/bpf/vm.go generated vendored
View File

@ -1,150 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import (
"errors"
"fmt"
)
// A VM is an emulated BPF virtual machine.
type VM struct {
filter []Instruction
}
// NewVM returns a new VM using the input BPF program.
func NewVM(filter []Instruction) (*VM, error) {
if len(filter) == 0 {
return nil, errors.New("one or more Instructions must be specified")
}
for i, ins := range filter {
check := len(filter) - (i + 1)
switch ins := ins.(type) {
// Check for out-of-bounds jumps in instructions
case Jump:
if check <= int(ins.Skip) {
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
}
case JumpIf:
if check <= int(ins.SkipTrue) {
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
}
if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
}
case JumpIfX:
if check <= int(ins.SkipTrue) {
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
}
if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
}
// Check for division or modulus by zero
case ALUOpConstant:
if ins.Val != 0 {
break
}
switch ins.Op {
case ALUOpDiv, ALUOpMod:
return nil, errors.New("cannot divide by zero using ALUOpConstant")
}
// Check for unknown extensions
case LoadExtension:
switch ins.Num {
case ExtLen:
default:
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
}
}
}
// Make sure last instruction is a return instruction
switch filter[len(filter)-1].(type) {
case RetA, RetConstant:
default:
return nil, errors.New("BPF program must end with RetA or RetConstant")
}
// Though our VM works using disassembled instructions, we
// attempt to assemble the input filter anyway to ensure it is compatible
// with an operating system VM.
_, err := Assemble(filter)
return &VM{
filter: filter,
}, err
}
// Run runs the VM's BPF program against the input bytes.
// Run returns the number of bytes accepted by the BPF program, and any errors
// which occurred while processing the program.
func (v *VM) Run(in []byte) (int, error) {
var (
// Registers of the virtual machine
regA uint32
regX uint32
regScratch [16]uint32
// OK is true if the program should continue processing the next
// instruction, or false if not, causing the loop to break
ok = true
)
// TODO(mdlayher): implement:
// - NegateA:
// - would require a change from uint32 registers to int32
// registers
// TODO(mdlayher): add interop tests that check signedness of ALU
// operations against kernel implementation, and make sure Go
// implementation matches behavior
for i := 0; i < len(v.filter) && ok; i++ {
ins := v.filter[i]
switch ins := ins.(type) {
case ALUOpConstant:
regA = aluOpConstant(ins, regA)
case ALUOpX:
regA, ok = aluOpX(ins, regA, regX)
case Jump:
i += int(ins.Skip)
case JumpIf:
jump := jumpIf(ins, regA)
i += jump
case JumpIfX:
jump := jumpIfX(ins, regA, regX)
i += jump
case LoadAbsolute:
regA, ok = loadAbsolute(ins, in)
case LoadConstant:
regA, regX = loadConstant(ins, regA, regX)
case LoadExtension:
regA = loadExtension(ins, in)
case LoadIndirect:
regA, ok = loadIndirect(ins, in, regX)
case LoadMemShift:
regX, ok = loadMemShift(ins, in)
case LoadScratch:
regA, regX = loadScratch(ins, regScratch, regA, regX)
case RetA:
return int(regA), nil
case RetConstant:
return int(ins.Val), nil
case StoreScratch:
regScratch = storeScratch(ins, regScratch, regA, regX)
case TAX:
regX = regA
case TXA:
regA = regX
default:
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
}
}
return 0, nil
}

View File

@ -1,181 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import (
"encoding/binary"
"fmt"
)
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
return aluOpCommon(ins.Op, regA, ins.Val)
}
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
// Guard against division or modulus by zero by terminating
// the program, as the OS BPF VM does
if regX == 0 {
switch ins.Op {
case ALUOpDiv, ALUOpMod:
return 0, false
}
}
return aluOpCommon(ins.Op, regA, regX), true
}
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
switch op {
case ALUOpAdd:
return regA + value
case ALUOpSub:
return regA - value
case ALUOpMul:
return regA * value
case ALUOpDiv:
// Division by zero not permitted by NewVM and aluOpX checks
return regA / value
case ALUOpOr:
return regA | value
case ALUOpAnd:
return regA & value
case ALUOpShiftLeft:
return regA << value
case ALUOpShiftRight:
return regA >> value
case ALUOpMod:
// Modulus by zero not permitted by NewVM and aluOpX checks
return regA % value
case ALUOpXor:
return regA ^ value
default:
return regA
}
}
func jumpIf(ins JumpIf, regA uint32) int {
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
}
func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
}
func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
var ok bool
switch cond {
case JumpEqual:
ok = regA == value
case JumpNotEqual:
ok = regA != value
case JumpGreaterThan:
ok = regA > value
case JumpLessThan:
ok = regA < value
case JumpGreaterOrEqual:
ok = regA >= value
case JumpLessOrEqual:
ok = regA <= value
case JumpBitsSet:
ok = (regA & value) != 0
case JumpBitsNotSet:
ok = (regA & value) == 0
}
if ok {
return int(skipTrue)
}
return int(skipFalse)
}
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
offset := int(ins.Off)
size := int(ins.Size)
return loadCommon(in, offset, size)
}
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
switch ins.Dst {
case RegA:
regA = ins.Val
case RegX:
regX = ins.Val
}
return regA, regX
}
func loadExtension(ins LoadExtension, in []byte) uint32 {
switch ins.Num {
case ExtLen:
return uint32(len(in))
default:
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
}
}
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
offset := int(ins.Off) + int(regX)
size := int(ins.Size)
return loadCommon(in, offset, size)
}
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
offset := int(ins.Off)
if !inBounds(len(in), offset, 0) {
return 0, false
}
// Mask off high 4 bits and multiply low 4 bits by 4
return uint32(in[offset]&0x0f) * 4, true
}
func inBounds(inLen int, offset int, size int) bool {
return offset+size <= inLen
}
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
if !inBounds(len(in), offset, size) {
return 0, false
}
switch size {
case 1:
return uint32(in[offset]), true
case 2:
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
case 4:
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
default:
panic(fmt.Sprintf("invalid load size: %d", size))
}
}
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
switch ins.Dst {
case RegA:
regA = regScratch[ins.N]
case RegX:
regX = regScratch[ins.N]
}
return regA, regX
}
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
switch ins.Src {
case RegA:
regScratch[ins.N] = regA
case RegX:
regScratch[ins.N] = regX
}
return regScratch
}

View File

@ -1,223 +0,0 @@
// go generate gen.go
// Code generated by the command above; DO NOT EDIT.
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
package iana // import "golang.org/x/net/internal/iana"
// Differentiated Services Field Codepoints (DSCP), Updated: 2018-05-04
const (
DiffServCS0 = 0x00 // CS0
DiffServCS1 = 0x20 // CS1
DiffServCS2 = 0x40 // CS2
DiffServCS3 = 0x60 // CS3
DiffServCS4 = 0x80 // CS4
DiffServCS5 = 0xa0 // CS5
DiffServCS6 = 0xc0 // CS6
DiffServCS7 = 0xe0 // CS7
DiffServAF11 = 0x28 // AF11
DiffServAF12 = 0x30 // AF12
DiffServAF13 = 0x38 // AF13
DiffServAF21 = 0x48 // AF21
DiffServAF22 = 0x50 // AF22
DiffServAF23 = 0x58 // AF23
DiffServAF31 = 0x68 // AF31
DiffServAF32 = 0x70 // AF32
DiffServAF33 = 0x78 // AF33
DiffServAF41 = 0x88 // AF41
DiffServAF42 = 0x90 // AF42
DiffServAF43 = 0x98 // AF43
DiffServEF = 0xb8 // EF
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
NotECNTransport = 0x00 // Not-ECT (Not ECN-Capable Transport)
ECNTransport1 = 0x01 // ECT(1) (ECN-Capable Transport(1))
ECNTransport0 = 0x02 // ECT(0) (ECN-Capable Transport(0))
CongestionExperienced = 0x03 // CE (Congestion Experienced)
)
// Protocol Numbers, Updated: 2017-10-13
const (
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
ProtocolICMP = 1 // Internet Control Message
ProtocolIGMP = 2 // Internet Group Management
ProtocolGGP = 3 // Gateway-to-Gateway
ProtocolIPv4 = 4 // IPv4 encapsulation
ProtocolST = 5 // Stream
ProtocolTCP = 6 // Transmission Control
ProtocolCBT = 7 // CBT
ProtocolEGP = 8 // Exterior Gateway Protocol
ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
ProtocolNVPII = 11 // Network Voice Protocol
ProtocolPUP = 12 // PUP
ProtocolEMCON = 14 // EMCON
ProtocolXNET = 15 // Cross Net Debugger
ProtocolCHAOS = 16 // Chaos
ProtocolUDP = 17 // User Datagram
ProtocolMUX = 18 // Multiplexing
ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
ProtocolHMP = 20 // Host Monitoring
ProtocolPRM = 21 // Packet Radio Measurement
ProtocolXNSIDP = 22 // XEROX NS IDP
ProtocolTRUNK1 = 23 // Trunk-1
ProtocolTRUNK2 = 24 // Trunk-2
ProtocolLEAF1 = 25 // Leaf-1
ProtocolLEAF2 = 26 // Leaf-2
ProtocolRDP = 27 // Reliable Data Protocol
ProtocolIRTP = 28 // Internet Reliable Transaction
ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
ProtocolMFENSP = 31 // MFE Network Services Protocol
ProtocolMERITINP = 32 // MERIT Internodal Protocol
ProtocolDCCP = 33 // Datagram Congestion Control Protocol
Protocol3PC = 34 // Third Party Connect Protocol
ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
ProtocolXTP = 36 // XTP
ProtocolDDP = 37 // Datagram Delivery Protocol
ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
ProtocolTPPP = 39 // TP++ Transport Protocol
ProtocolIL = 40 // IL Transport Protocol
ProtocolIPv6 = 41 // IPv6 encapsulation
ProtocolSDRP = 42 // Source Demand Routing Protocol
ProtocolIPv6Route = 43 // Routing Header for IPv6
ProtocolIPv6Frag = 44 // Fragment Header for IPv6
ProtocolIDRP = 45 // Inter-Domain Routing Protocol
ProtocolRSVP = 46 // Reservation Protocol
ProtocolGRE = 47 // Generic Routing Encapsulation
ProtocolDSR = 48 // Dynamic Source Routing Protocol
ProtocolBNA = 49 // BNA
ProtocolESP = 50 // Encap Security Payload
ProtocolAH = 51 // Authentication Header
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
ProtocolNARP = 54 // NBMA Address Resolution Protocol
ProtocolMOBILE = 55 // IP Mobility
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
ProtocolSKIP = 57 // SKIP
ProtocolIPv6ICMP = 58 // ICMP for IPv6
ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
ProtocolIPv6Opts = 60 // Destination Options for IPv6
ProtocolCFTP = 62 // CFTP
ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
ProtocolKRYPTOLAN = 65 // Kryptolan
ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
ProtocolIPPC = 67 // Internet Pluribus Packet Core
ProtocolSATMON = 69 // SATNET Monitoring
ProtocolVISA = 70 // VISA Protocol
ProtocolIPCV = 71 // Internet Packet Core Utility
ProtocolCPNX = 72 // Computer Protocol Network Executive
ProtocolCPHB = 73 // Computer Protocol Heart Beat
ProtocolWSN = 74 // Wang Span Network
ProtocolPVP = 75 // Packet Video Protocol
ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
ProtocolWBMON = 78 // WIDEBAND Monitoring
ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
ProtocolISOIP = 80 // ISO Internet Protocol
ProtocolVMTP = 81 // VMTP
ProtocolSECUREVMTP = 82 // SECURE-VMTP
ProtocolVINES = 83 // VINES
ProtocolTTP = 84 // Transaction Transport Protocol
ProtocolIPTM = 84 // Internet Protocol Traffic Manager
ProtocolNSFNETIGP = 85 // NSFNET-IGP
ProtocolDGP = 86 // Dissimilar Gateway Protocol
ProtocolTCF = 87 // TCF
ProtocolEIGRP = 88 // EIGRP
ProtocolOSPFIGP = 89 // OSPFIGP
ProtocolSpriteRPC = 90 // Sprite RPC Protocol
ProtocolLARP = 91 // Locus Address Resolution Protocol
ProtocolMTP = 92 // Multicast Transport Protocol
ProtocolAX25 = 93 // AX.25 Frames
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
ProtocolENCAP = 98 // Encapsulation Header
ProtocolGMTP = 100 // GMTP
ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
ProtocolPNNI = 102 // PNNI over IP
ProtocolPIM = 103 // Protocol Independent Multicast
ProtocolARIS = 104 // ARIS
ProtocolSCPS = 105 // SCPS
ProtocolQNX = 106 // QNX
ProtocolAN = 107 // Active Networks
ProtocolIPComp = 108 // IP Payload Compression Protocol
ProtocolSNP = 109 // Sitara Networks Protocol
ProtocolCompaqPeer = 110 // Compaq Peer Protocol
ProtocolIPXinIP = 111 // IPX in IP
ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
ProtocolPGM = 113 // PGM Reliable Transport Protocol
ProtocolL2TP = 115 // Layer Two Tunneling Protocol
ProtocolDDX = 116 // D-II Data Exchange (DDX)
ProtocolIATP = 117 // Interactive Agent Transfer Protocol
ProtocolSTP = 118 // Schedule Transfer Protocol
ProtocolSRP = 119 // SpectraLink Radio Protocol
ProtocolUTI = 120 // UTI
ProtocolSMP = 121 // Simple Message Protocol
ProtocolPTP = 123 // Performance Transparency Protocol
ProtocolISIS = 124 // ISIS over IPv4
ProtocolFIRE = 125 // FIRE
ProtocolCRTP = 126 // Combat Radio Transport Protocol
ProtocolCRUDP = 127 // Combat Radio User Datagram
ProtocolSSCOPMCE = 128 // SSCOPMCE
ProtocolIPLT = 129 // IPLT
ProtocolSPS = 130 // Secure Packet Shield
ProtocolPIPE = 131 // Private IP Encapsulation within IP
ProtocolSCTP = 132 // Stream Control Transmission Protocol
ProtocolFC = 133 // Fibre Channel
ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
ProtocolMobilityHeader = 135 // Mobility Header
ProtocolUDPLite = 136 // UDPLite
ProtocolMPLSinIP = 137 // MPLS-in-IP
ProtocolMANET = 138 // MANET Protocols
ProtocolHIP = 139 // Host Identity Protocol
ProtocolShim6 = 140 // Shim6 Protocol
ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
ProtocolROHC = 142 // Robust Header Compression
ProtocolReserved = 255 // Reserved
)
// Address Family Numbers, Updated: 2018-04-02
const (
AddrFamilyIPv4 = 1 // IP (IP version 4)
AddrFamilyIPv6 = 2 // IP6 (IP version 6)
AddrFamilyNSAP = 3 // NSAP
AddrFamilyHDLC = 4 // HDLC (8-bit multidrop)
AddrFamilyBBN1822 = 5 // BBN 1822
AddrFamily802 = 6 // 802 (includes all 802 media plus Ethernet "canonical format")
AddrFamilyE163 = 7 // E.163
AddrFamilyE164 = 8 // E.164 (SMDS, Frame Relay, ATM)
AddrFamilyF69 = 9 // F.69 (Telex)
AddrFamilyX121 = 10 // X.121 (X.25, Frame Relay)
AddrFamilyIPX = 11 // IPX
AddrFamilyAppletalk = 12 // Appletalk
AddrFamilyDecnetIV = 13 // Decnet IV
AddrFamilyBanyanVines = 14 // Banyan Vines
AddrFamilyE164withSubaddress = 15 // E.164 with NSAP format subaddress
AddrFamilyDNS = 16 // DNS (Domain Name System)
AddrFamilyDistinguishedName = 17 // Distinguished Name
AddrFamilyASNumber = 18 // AS Number
AddrFamilyXTPoverIPv4 = 19 // XTP over IP version 4
AddrFamilyXTPoverIPv6 = 20 // XTP over IP version 6
AddrFamilyXTPnativemodeXTP = 21 // XTP native mode XTP
AddrFamilyFibreChannelWorldWidePortName = 22 // Fibre Channel World-Wide Port Name
AddrFamilyFibreChannelWorldWideNodeName = 23 // Fibre Channel World-Wide Node Name
AddrFamilyGWID = 24 // GWID
AddrFamilyL2VPN = 25 // AFI for L2VPN information
AddrFamilyMPLSTPSectionEndpointID = 26 // MPLS-TP Section Endpoint Identifier
AddrFamilyMPLSTPLSPEndpointID = 27 // MPLS-TP LSP Endpoint Identifier
AddrFamilyMPLSTPPseudowireEndpointID = 28 // MPLS-TP Pseudowire Endpoint Identifier
AddrFamilyMTIPv4 = 29 // MT IP: Multi-Topology IP version 4
AddrFamilyMTIPv6 = 30 // MT IPv6: Multi-Topology IP version 6
AddrFamilyEIGRPCommonServiceFamily = 16384 // EIGRP Common Service Family
AddrFamilyEIGRPIPv4ServiceFamily = 16385 // EIGRP IPv4 Service Family
AddrFamilyEIGRPIPv6ServiceFamily = 16386 // EIGRP IPv6 Service Family
AddrFamilyLISPCanonicalAddressFormat = 16387 // LISP Canonical Address Format (LCAF)
AddrFamilyBGPLS = 16388 // BGP-LS
AddrFamily48bitMAC = 16389 // 48-bit MAC
AddrFamily64bitMAC = 16390 // 64-bit MAC
AddrFamilyOUI = 16391 // OUI
AddrFamilyMACFinal24bits = 16392 // MAC/24
AddrFamilyMACFinal40bits = 16393 // MAC/40
AddrFamilyIPv6Initial64bits = 16394 // IPv6/64
AddrFamilyRBridgePortID = 16395 // RBridge Port ID
AddrFamilyTRILLNickname = 16396 // TRILL Nickname
)

View File

@ -1,383 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
//go:generate go run gen.go
// This program generates internet protocol constants and tables by
// reading IANA protocol registries.
package main
import (
"bytes"
"encoding/xml"
"fmt"
"go/format"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
)
var registries = []struct {
url string
parse func(io.Writer, io.Reader) error
}{
{
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
parseDSCPRegistry,
},
{
"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
parseProtocolNumbers,
},
{
"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
parseAddrFamilyNumbers,
},
}
func main() {
var bb bytes.Buffer
fmt.Fprintf(&bb, "// go generate gen.go\n")
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
for _, r := range registries {
resp, err := http.Get(r.url)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
os.Exit(1)
}
if err := r.parse(&bb, resp.Body); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Fprintf(&bb, "\n")
}
b, err := format.Source(bb.Bytes())
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var dr dscpRegistry
if err := dec.Decode(&dr); err != nil {
return err
}
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
fmt.Fprintf(w, "const (\n")
for _, dr := range dr.escapeDSCP() {
fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
fmt.Fprintf(w, "// %s\n", dr.OrigName)
}
for _, er := range dr.escapeECN() {
fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
fmt.Fprintf(w, "// %s\n", er.OrigDescr)
}
fmt.Fprintf(w, ")\n")
return nil
}
type dscpRegistry struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
Note string `xml:"note"`
Registries []struct {
Title string `xml:"title"`
Registries []struct {
Title string `xml:"title"`
Records []struct {
Name string `xml:"name"`
Space string `xml:"space"`
} `xml:"record"`
} `xml:"registry"`
Records []struct {
Value string `xml:"value"`
Descr string `xml:"description"`
} `xml:"record"`
} `xml:"registry"`
}
type canonDSCPRecord struct {
OrigName string
Name string
Value int
}
func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
var drs []canonDSCPRecord
for _, preg := range drr.Registries {
if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
continue
}
for _, reg := range preg.Registries {
if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
continue
}
drs = make([]canonDSCPRecord, len(reg.Records))
sr := strings.NewReplacer(
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, dr := range reg.Records {
s := strings.TrimSpace(dr.Name)
drs[i].OrigName = s
drs[i].Name = sr.Replace(s)
n, err := strconv.ParseUint(dr.Space, 2, 8)
if err != nil {
continue
}
drs[i].Value = int(n) << 2
}
}
}
return drs
}
type canonECNRecord struct {
OrigDescr string
Descr string
Value int
}
func (drr *dscpRegistry) escapeECN() []canonECNRecord {
var ers []canonECNRecord
for _, reg := range drr.Registries {
if !strings.Contains(reg.Title, "ECN Field") {
continue
}
ers = make([]canonECNRecord, len(reg.Records))
sr := strings.NewReplacer(
"Capable", "",
"Not-ECT", "",
"ECT(1)", "",
"ECT(0)", "",
"CE", "",
"(", "",
")", "",
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, er := range reg.Records {
s := strings.TrimSpace(er.Descr)
ers[i].OrigDescr = s
ss := strings.Split(s, " ")
if len(ss) > 1 {
ers[i].Descr = strings.Join(ss[1:], " ")
} else {
ers[i].Descr = ss[0]
}
ers[i].Descr = sr.Replace(er.Descr)
n, err := strconv.ParseUint(er.Value, 2, 8)
if err != nil {
continue
}
ers[i].Value = int(n)
}
}
return ers
}
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var pn protocolNumbers
if err := dec.Decode(&pn); err != nil {
return err
}
prs := pn.escape()
prs = append([]canonProtocolRecord{{
Name: "IP",
Descr: "IPv4 encapsulation, pseudo protocol number",
Value: 0,
}}, prs...)
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
fmt.Fprintf(w, "const (\n")
for _, pr := range prs {
if pr.Name == "" {
continue
}
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
s := pr.Descr
if s == "" {
s = pr.OrigName
}
fmt.Fprintf(w, "// %s\n", s)
}
fmt.Fprintf(w, ")\n")
return nil
}
type protocolNumbers struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
RegTitle string `xml:"registry>title"`
Note string `xml:"registry>note"`
Records []struct {
Value string `xml:"value"`
Name string `xml:"name"`
Descr string `xml:"description"`
} `xml:"registry>record"`
}
type canonProtocolRecord struct {
OrigName string
Name string
Descr string
Value int
}
func (pn *protocolNumbers) escape() []canonProtocolRecord {
prs := make([]canonProtocolRecord, len(pn.Records))
sr := strings.NewReplacer(
"-in-", "in",
"-within-", "within",
"-over-", "over",
"+", "P",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, pr := range pn.Records {
if strings.Contains(pr.Name, "Deprecated") ||
strings.Contains(pr.Name, "deprecated") {
continue
}
prs[i].OrigName = pr.Name
s := strings.TrimSpace(pr.Name)
switch pr.Name {
case "ISIS over IPv4":
prs[i].Name = "ISIS"
case "manet":
prs[i].Name = "MANET"
default:
prs[i].Name = sr.Replace(s)
}
ss := strings.Split(pr.Descr, "\n")
for i := range ss {
ss[i] = strings.TrimSpace(ss[i])
}
if len(ss) > 1 {
prs[i].Descr = strings.Join(ss, " ")
} else {
prs[i].Descr = ss[0]
}
prs[i].Value, _ = strconv.Atoi(pr.Value)
}
return prs
}
func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var afn addrFamilylNumbers
if err := dec.Decode(&afn); err != nil {
return err
}
afrs := afn.escape()
fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
fmt.Fprintf(w, "const (\n")
for _, afr := range afrs {
if afr.Name == "" {
continue
}
fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
fmt.Fprintf(w, "// %s\n", afr.Descr)
}
fmt.Fprintf(w, ")\n")
return nil
}
type addrFamilylNumbers struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
RegTitle string `xml:"registry>title"`
Note string `xml:"registry>note"`
Records []struct {
Value string `xml:"value"`
Descr string `xml:"description"`
} `xml:"registry>record"`
}
type canonAddrFamilyRecord struct {
Name string
Descr string
Value int
}
func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
afrs := make([]canonAddrFamilyRecord, len(afn.Records))
sr := strings.NewReplacer(
"IP version 4", "IPv4",
"IP version 6", "IPv6",
"Identifier", "ID",
"-", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, afr := range afn.Records {
if strings.Contains(afr.Descr, "Unassigned") ||
strings.Contains(afr.Descr, "Reserved") {
continue
}
afrs[i].Descr = afr.Descr
s := strings.TrimSpace(afr.Descr)
switch s {
case "IP (IP version 4)":
afrs[i].Name = "IPv4"
case "IP6 (IP version 6)":
afrs[i].Name = "IPv6"
case "AFI for L2VPN information":
afrs[i].Name = "L2VPN"
case "E.164 with NSAP format subaddress":
afrs[i].Name = "E164withSubaddress"
case "MT IP: Multi-Topology IP version 4":
afrs[i].Name = "MTIPv4"
case "MAC/24":
afrs[i].Name = "MACFinal24bits"
case "MAC/40":
afrs[i].Name = "MACFinal40bits"
case "IPv6/64":
afrs[i].Name = "IPv6Initial64bits"
default:
n := strings.Index(s, "(")
if n > 0 {
s = s[:n]
}
n = strings.Index(s, ":")
if n > 0 {
s = s[:n]
}
afrs[i].Name = sr.Replace(s)
}
afrs[i].Value, _ = strconv.Atoi(afr.Value)
}
return afrs
}

View File

@ -1,11 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
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) }

View File

@ -1,13 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd netbsd openbsd
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}

View File

@ -1,14 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64
// +build solaris
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}

View File

@ -1,17 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
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) {}

View File

@ -1,47 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type mmsghdr C.struct_mmsghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,44 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,44 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,44 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,49 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <linux/in.h>
#include <linux/in6.h>
#define _GNU_SOURCE
#include <sys/socket.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type mmsghdr C.struct_mmsghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,47 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type mmsghdr C.struct_mmsghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,44 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,44 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)

View File

@ -1,7 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin,go1.12
// This exists solely so we can linkname in symbols from syscall.

View File

@ -1,31 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
import "syscall"
var (
errEAGAIN error = syscall.EAGAIN
errEINVAL error = syscall.EINVAL
errENOENT error = syscall.ENOENT
)
// errnoErr returns common boxed Errno values, to prevent allocations
// at runtime.
func errnoErr(errno syscall.Errno) error {
switch errno {
case 0:
return nil
case syscall.EAGAIN:
return errEAGAIN
case syscall.EINVAL:
return errEINVAL
case syscall.ENOENT:
return errENOENT
}
return errno
}

View File

@ -1,26 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socket
import "syscall"
var (
errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING
errEINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent allocations
// at runtime.
func errnoErr(errno syscall.Errno) error {
switch errno {
case 0:
return nil
case syscall.ERROR_IO_PENDING:
return errERROR_IO_PENDING
case syscall.EINVAL:
return errEINVAL
}
return errno
}

View File

@ -1,19 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm mips mipsle 386
// +build darwin dragonfly freebsd linux netbsd openbsd
package socket
import "unsafe"
func (v *iovec) set(b []byte) {
l := len(b)
if l == 0 {
return
}
v.Base = (*byte)(unsafe.Pointer(&b[0]))
v.Len = uint32(l)
}

View File

@ -1,19 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build aix darwin dragonfly freebsd linux netbsd openbsd
package socket
import "unsafe"
func (v *iovec) set(b []byte) {
l := len(b)
if l == 0 {
return
}
v.Base = (*byte)(unsafe.Pointer(&b[0]))
v.Len = uint64(l)
}

View File

@ -1,19 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64
// +build solaris
package socket
import "unsafe"
func (v *iovec) set(b []byte) {
l := len(b)
if l == 0 {
return
}
v.Base = (*int8)(unsafe.Pointer(&b[0]))
v.Len = uint64(l)
}

View File

@ -1,11 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket
type iovec struct{}
func (v *iovec) set(b []byte) {}

View File

@ -1,21 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !aix,!linux,!netbsd
package socket
import "net"
type mmsghdr struct{}
type mmsghdrs []mmsghdr
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
return nil
}
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
return nil
}

View File

@ -1,42 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix linux netbsd
package socket
import "net"
type mmsghdrs []mmsghdr
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
for i := range hs {
vs := make([]iovec, len(ms[i].Buffers))
var sa []byte
if parseFn != nil {
sa = make([]byte, sizeofSockaddrInet6)
}
if marshalFn != nil {
sa = marshalFn(ms[i].Addr)
}
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
}
return nil
}
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
for i := range hs {
ms[i].N = int(hs[i].Len)
ms[i].NN = hs[i].Hdr.controllen()
ms[i].Flags = hs[i].Hdr.flags()
if parseFn != nil {
var err error
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint)
if err != nil {
return err
}
}
}
return nil
}

View File

@ -1,39 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd netbsd openbsd
package socket
import "unsafe"
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
for i := range vs {
vs[i].set(bs[i])
}
h.setIov(vs)
if len(oob) > 0 {
h.Control = (*byte)(unsafe.Pointer(&oob[0]))
h.Controllen = uint32(len(oob))
}
if sa != nil {
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
h.Namelen = uint32(len(sa))
}
}
func (h *msghdr) name() []byte {
if h.Name != nil && h.Namelen > 0 {
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
}
return nil
}
func (h *msghdr) controllen() int {
return int(h.Controllen)
}
func (h *msghdr) flags() int {
return int(h.Flags)
}

View File

@ -1,16 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd netbsd
package socket
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = int32(l)
}

View File

@ -1,36 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socket
import "unsafe"
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
for i := range vs {
vs[i].set(bs[i])
}
h.setIov(vs)
if len(oob) > 0 {
h.setControl(oob)
}
if sa != nil {
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
h.Namelen = uint32(len(sa))
}
}
func (h *msghdr) name() []byte {
if h.Name != nil && h.Namelen > 0 {
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
}
return nil
}
func (h *msghdr) controllen() int {
return int(h.Controllen)
}
func (h *msghdr) flags() int {
return int(h.Flags)
}

View File

@ -1,24 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm mips mipsle 386
// +build linux
package socket
import "unsafe"
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = uint32(l)
}
func (h *msghdr) setControl(b []byte) {
h.Control = (*byte)(unsafe.Pointer(&b[0]))
h.Controllen = uint32(len(b))
}

View File

@ -1,24 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build linux
package socket
import "unsafe"
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = uint64(l)
}
func (h *msghdr) setControl(b []byte) {
h.Control = (*byte)(unsafe.Pointer(&b[0]))
h.Controllen = uint64(len(b))
}

View File

@ -1,14 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socket
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = uint32(l)
}

View File

@ -1,36 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64
// +build solaris
package socket
import "unsafe"
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
for i := range vs {
vs[i].set(bs[i])
}
if len(vs) > 0 {
h.Iov = &vs[0]
h.Iovlen = int32(len(vs))
}
if len(oob) > 0 {
h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
h.Accrightslen = int32(len(oob))
}
if sa != nil {
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
h.Namelen = uint32(len(sa))
}
}
func (h *msghdr) controllen() int {
return int(h.Accrightslen)
}
func (h *msghdr) flags() int {
return int(NativeEndian.Uint32(h.Pad_cgo_2[:]))
}

Some files were not shown because too many files have changed in this diff Show More