dns: fix memoryleak by upgrading outdated miekg/dns (#6748)

* Add updated github.com/miekg/dns to go modules
* Add updated github.com/miekg/dns to vendor
* Fix github.com/miekg/dns api breakage
* Decrease size when trimming UDP packets
Need more room for the header(?), if we don't decrease the size we get an
"overflow unpacking uint32" from the dns library
* Fix dns truncate tests with api changes
* Make windows build working again. Upgrade x/sys and x/crypto and vendor
This upgrade is needed because of API breakage in x/sys introduced
by the minimal x/sys dependency of miekg/dns

This API breakage has been fixed in commit
855e68c859
pull/6958/head
Wim 2019-12-16 22:31:27 +01:00 committed by Hans Hasselberg
parent 7d0f72c60a
commit 4f5d5020b8
263 changed files with 12220 additions and 7029 deletions

View File

@ -1019,7 +1019,7 @@ func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) {
// uncompresses them. // uncompresses them.
// Even when size is too big for one single record, try to send it anyway // Even when size is too big for one single record, try to send it anyway
// (useful for 512 bytes messages) // (useful for 512 bytes messages)
for len(resp.Answer) > 1 && resp.Len() > maxSize { for len(resp.Answer) > 1 && resp.Len() > maxSize-7 {
// More than 100 bytes, find with a binary search // More than 100 bytes, find with a binary search
if resp.Len()-maxSize > 100 { if resp.Len()-maxSize > 100 {
bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra) bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
@ -1034,7 +1034,6 @@ func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) {
// For 512 non-eDNS responses, while we compute size non-compressed, // For 512 non-eDNS responses, while we compute size non-compressed,
// we send result compressed // we send result compressed
resp.Compress = compress resp.Compress = compress
return len(resp.Answer) < numAnswers return len(resp.Answer) < numAnswers
} }
@ -1735,7 +1734,7 @@ func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) {
// If we still have recursors to forward the query to, // If we still have recursors to forward the query to,
// we move forward onto the next one else the loop ends // we move forward onto the next one else the loop ends
continue continue
} else if err == nil || err == dns.ErrTruncated { } else if err == nil || (r != nil && r.Truncated) {
// Compress the response; we don't know if the incoming // Compress the response; we don't know if the incoming
// response was compressed or not, so by not compressing // response was compressed or not, so by not compressing
// we might generate an invalid packet on the way out. // we might generate an invalid packet on the way out.

View File

@ -3267,7 +3267,7 @@ func TestDNS_Recurse_Truncation(t *testing.T) {
c := new(dns.Client) c := new(dns.Client)
in, _, err := c.Exchange(m, a.DNSAddr()) in, _, err := c.Exchange(m, a.DNSAddr())
if err != dns.ErrTruncated { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if in.Truncated != true { if in.Truncated != true {
@ -3952,10 +3952,17 @@ func TestDNS_TCP_and_UDP_Truncate(t *testing.T) {
c.Net = protocol c.Net = protocol
m.Compress = compress m.Compress = compress
in, _, err := c.Exchange(m, a.DNSAddr()) in, _, err := c.Exchange(m, a.DNSAddr())
if err != nil && err != dns.ErrTruncated { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
// actually check if we need to have the truncate bit
resbuf, err := in.Pack()
if err != nil {
t.Fatalf("Error while packing answer: %s", err)
}
if !in.Truncated && len(resbuf) > int(maxSz) {
t.Fatalf("should have truncate bit %#v %#v", in, len(in.Answer))
}
// Check for the truncate bit // Check for the truncate bit
buf, err := m.Pack() buf, err := m.Pack()
info := fmt.Sprintf("service %s question:=%s (%s) (%d total records) sz:= %d in %v", info := fmt.Sprintf("service %s question:=%s (%s) (%d total records) sz:= %d in %v",
@ -4033,7 +4040,7 @@ func TestDNS_ServiceLookup_Truncate(t *testing.T) {
c := new(dns.Client) c := new(dns.Client)
in, _, err := c.Exchange(m, a.DNSAddr()) in, _, err := c.Exchange(m, a.DNSAddr())
if err != nil && err != dns.ErrTruncated { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
@ -4105,10 +4112,14 @@ func TestDNS_ServiceLookup_LargeResponses(t *testing.T) {
c := new(dns.Client) c := new(dns.Client)
in, _, err := c.Exchange(m, a.DNSAddr()) in, _, err := c.Exchange(m, a.DNSAddr())
if err != nil && err != dns.ErrTruncated { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if !in.Truncated {
t.Fatalf("should have truncate bit")
}
// Make sure the response size is RFC 1035-compliant for UDP messages // Make sure the response size is RFC 1035-compliant for UDP messages
if in.Len() > 512 { if in.Len() > 512 {
t.Fatalf("Bad: %d", in.Len()) t.Fatalf("Bad: %d", in.Len())

8
go.mod
View File

@ -56,7 +56,7 @@ require (
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
github.com/imdario/mergo v0.3.6 github.com/imdario/mergo v0.3.6
github.com/kr/text v0.1.0 github.com/kr/text v0.1.0
github.com/miekg/dns v1.0.14 github.com/miekg/dns v1.1.22
github.com/mitchellh/cli v1.0.0 github.com/mitchellh/cli v1.0.0
github.com/mitchellh/copystructure v1.0.0 github.com/mitchellh/copystructure v1.0.0
github.com/mitchellh/go-testing-interface v1.0.0 github.com/mitchellh/go-testing-interface v1.0.0
@ -73,10 +73,10 @@ require (
github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/pflag v1.0.3 // indirect
github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/net v0.0.0-20190923162816-aa69164e4478
golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
google.golang.org/grpc v1.23.0 google.golang.org/grpc v1.23.0
gopkg.in/square/go-jose.v2 v2.3.1 gopkg.in/square/go-jose.v2 v2.3.1

15
go.sum
View File

@ -241,6 +241,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc=
github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
@ -349,6 +351,10 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4 h1:PDpCLFAH/YIX0QpHPf2eO7L4rC2OOirBrKtXTLLiNTY=
golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -368,6 +374,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -392,6 +400,11 @@ golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5 h1:sM3evRHxE/1RuMe1FYAL3j7C7
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII=
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -407,6 +420,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w=
google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=

View File

@ -2,14 +2,12 @@ language: go
sudo: false sudo: false
go: go:
- 1.10.x
- 1.11.x - 1.11.x
- 1.12.x
- tip - tip
before_install: env:
# don't use the miekg/dns when testing forks - GO111MODULE=on
- mkdir -p $GOPATH/src/github.com/miekg
- 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 -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...

View File

@ -1,57 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
name = "golang.org/x/crypto"
packages = [
"ed25519",
"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]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"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-version = 1

View File

@ -1,38 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
branch = "master"
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

@ -7,10 +7,10 @@
> Less is more. > Less is more.
Complete and usable DNS library. All widely used Resource Records are supported, including the Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there
programmer there isn't a convenience function for it. Server side and client side programming is isn't a convenience function for it. Server side and client side programming is supported, i.e. you
supported, i.e. you can build servers and resolvers with it. 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,10 +42,9 @@ 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
@ -56,7 +55,7 @@ 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 (JD.COM) * https://github.com/ipdcode/hades <https://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/
@ -68,29 +67,30 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/rs/dnstrace * https://github.com/rs/dnstrace
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss)) * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
* https://github.com/semihalev/sdns * https://github.com/semihalev/sdns
* https://render.com
* https://github.com/peterzen/goresolver
* https://github.com/folbricht/routedns
Send pull request if you want to be listed here. 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
* Reply speed around ~ 80K qps (faster hardware results in more qps); * Server side programming (mimicking the net/http package)
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds; * Client side programming
* Server side programming (mimicking the net/http package); * DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
* Client side programming; * EDNS0, NSID, Cookies
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519; * AXFR/IXFR
* EDNS0, NSID, Cookies; * TSIG, SIG(0)
* AXFR/IXFR; * DNS over TLS (DoT): encrypted connection between client and server over TCP
* TSIG, SIG(0); * DNS name compression
* 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
@ -102,8 +102,8 @@ work:
## Examples ## Examples
A short "how to use the API" is at the beginning of doc.go (this also will show A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
when you call `godoc github.com/miekg/dns`). 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.
@ -153,6 +153,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6844 - CAA record * 6844 - CAA record
* 6891 - EDNS0 update * 6891 - EDNS0 update
* 6895 - DNS IANA considerations * 6895 - DNS IANA considerations
* 6944 - DNSSEC DNSKEY Algorithm Status
* 6975 - Algorithm Understanding in DNSSEC * 6975 - Algorithm Understanding in DNSSEC
* 7043 - EUI48/EUI64 records * 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option * 7314 - DNS (EDNS) EXPIRE Option
@ -161,12 +162,13 @@ 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 (draft-ietf-dnsop-cookies) * 7873 - Domain Name System (DNS) Cookies
* 8080 - EdDSA for DNSSEC * 8080 - EdDSA for DNSSEC
* 8499 - DNS Terminology
## Loosely based upon ## Loosely Based Upon
* `ldns` * ldns - <https://nlnetlabs.nl/projects/ldns/about/>
* `NSD` * NSD - <https://nlnetlabs.nl/projects/nsd/about/>
* `Net::DNS` * Net::DNS - <http://www.net-dns.org/>
* `GRONG` * GRONG - <https://github.com/bortzmeyer/grong>

54
vendor/github.com/miekg/dns/acceptfunc.go generated vendored Normal file
View File

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

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

@ -3,15 +3,12 @@ package dns
// A client implementation. // A client implementation.
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net" "net"
"net/http"
"strings" "strings"
"time" "time"
) )
@ -19,8 +16,6 @@ import (
const ( const (
dnsTimeout time.Duration = 2 * time.Second dnsTimeout time.Duration = 2 * time.Second
tcpIdleTimeout time.Duration = 8 * time.Second tcpIdleTimeout time.Duration = 8 * time.Second
dohMimeType = "application/dns-message"
) )
// A Conn represents a connection to a DNS server. // A Conn represents a connection to a DNS server.
@ -44,7 +39,6 @@ type Client struct {
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
HTTPClient *http.Client // The http.Client to use for DNS-over-HTTPS
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
group singleflight group singleflight
@ -132,33 +126,18 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// attribute appropriately // attribute appropriately
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) { func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight { if !c.SingleInflight {
if c.Net == "https" {
// TODO(tmthrgd): pipe timeouts into exchangeDOH
return c.exchangeDOH(context.TODO(), m, address)
}
return c.exchange(m, address) return c.exchange(m, address)
} }
t := "nop" q := m.Question[0]
if t1, ok := TypeToString[m.Question[0].Qtype]; ok { key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
t = t1 r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
}
cl := "nop"
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
cl = cl1
}
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
if c.Net == "https" {
// TODO(tmthrgd): pipe timeouts into exchangeDOH
return c.exchangeDOH(context.TODO(), m, address)
}
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
} }
@ -199,67 +178,6 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
return r, rtt, err return r, rtt, err
} }
func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
p, err := m.Pack()
if err != nil {
return nil, 0, err
}
req, err := http.NewRequest(http.MethodPost, a, bytes.NewReader(p))
if err != nil {
return nil, 0, err
}
req.Header.Set("Content-Type", dohMimeType)
req.Header.Set("Accept", dohMimeType)
hc := http.DefaultClient
if c.HTTPClient != nil {
hc = c.HTTPClient
}
if ctx != context.Background() && ctx != context.TODO() {
req = req.WithContext(ctx)
}
t := time.Now()
resp, err := hc.Do(req)
if err != nil {
return nil, 0, err
}
defer closeHTTPBody(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, 0, fmt.Errorf("dns: server returned HTTP %d error: %q", resp.StatusCode, resp.Status)
}
if ct := resp.Header.Get("Content-Type"); ct != dohMimeType {
return nil, 0, fmt.Errorf("dns: unexpected Content-Type %q; expected %q", ct, dohMimeType)
}
p, err = ioutil.ReadAll(resp.Body)
if err != nil {
return nil, 0, err
}
rtt = time.Since(t)
r = new(Msg)
if err := r.Unpack(p); err != nil {
return r, 0, err
}
// TODO: TSIG? Is it even supported over DoH?
return r, rtt, nil
}
func closeHTTPBody(r io.ReadCloser) error {
io.Copy(ioutil.Discard, io.LimitReader(r, 8<<20))
return r.Close()
}
// ReadMsg reads a message from the connection co. // 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 signature
// is verified. This method always tries to return the message, however if an // is verified. This method always tries to return the message, however if an
@ -298,24 +216,21 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
err error err error
) )
switch t := co.Conn.(type) { if _, ok := co.Conn.(net.PacketConn); ok {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
// First two bytes specify the length of the entire message.
l, err := tcpMsgLen(r)
if err != nil {
return nil, err
}
p = make([]byte, l)
n, err = tcpRead(r, p)
default:
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
} else { } else {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
} else {
var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return nil, err
}
p = make([]byte, length)
n, err = io.ReadFull(co.Conn, p)
} }
if err != nil { if err != nil {
@ -335,78 +250,26 @@ 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 {
if _, ok := co.Conn.(net.PacketConn); ok {
// UDP connection
return co.Conn.Read(p)
}
var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return 0, err
}
if int(length) > len(p) {
return 0, io.ErrShortBuffer return 0, io.ErrShortBuffer
} }
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
l, err := tcpMsgLen(r) return io.ReadFull(co.Conn, p[:length])
if err != nil {
return 0, err
}
if l > len(p) {
return int(l), io.ErrShortBuffer
}
return tcpRead(r, p[:l])
}
// UDP connection
n, err = co.Conn.Read(p)
if err != nil {
return n, err
}
return n, err
} }
// WriteMsg sends a message through the connection co. // WriteMsg sends a message through the connection co.
@ -428,33 +291,25 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
if err != nil { if err != nil {
return err return err
} }
if _, err = co.Write(out); err != nil { _, err = co.Write(out)
return err 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) (int, error) {
switch t := co.Conn.(type) { if len(p) > MaxMsgSize {
case *net.TCPConn, *tls.Conn: return 0, &Error{err: "message too large"}
w := t.(io.Writer)
lp := len(p)
if lp < 2 {
return 0, io.ErrShortBuffer
}
if lp > MaxMsgSize {
return 0, &Error{err: "message too large"}
}
l := make([]byte, 2, lp+2)
binary.BigEndian.PutUint16(l, uint16(lp))
p = append(l, p...)
n, err := io.Copy(w, bytes.NewReader(p))
return int(n), err
} }
n, err = co.Conn.Write(p)
return n, err if _, ok := co.Conn.(net.PacketConn); ok {
return co.Conn.Write(p)
}
l := make([]byte, 2)
binary.BigEndian.PutUint16(l, uint16(len(p)))
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
return int(n), err
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
@ -497,7 +352,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
// ExchangeConn performs a synchronous query. It sends the message m via the connection // 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.
// This function is going away, but can easily be mimicked: // Deprecated: This function is going away, but can easily be mimicked:
// //
// co := &dns.Conn{Conn: c} // c is your net.Conn // co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m) // co.WriteMsg(m)
@ -521,11 +376,7 @@ 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}}
conn, err = client.Dial(address) return 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.
@ -534,12 +385,7 @@ 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}
conn, err = client.Dial(address) return 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.
@ -548,21 +394,13 @@ 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}
conn, err = client.Dial(address) return 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
// context, if present. If there is both a context deadline and a configured // context, if present. If there is both a context deadline and a configured
// timeout on the client, the earliest of the two takes effect. // timeout on the client, the earliest of the two takes effect.
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) { func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight && c.Net == "https" {
return c.exchangeDOH(ctx, m, a)
}
var timeout time.Duration var timeout time.Duration
if deadline, ok := ctx.Deadline(); !ok { if deadline, ok := ctx.Deadline(); !ok {
timeout = 0 timeout = 0
@ -571,7 +409,7 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg,
} }
// 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): this is a race condition // 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,14 +68,10 @@ 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 = make([]string, len(f)-1) c.Search = append([]string(nil), 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 i := 1; i < len(f); i++ { for _, s := range f[1:] {
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:])

View File

@ -1,198 +0,0 @@
//+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 = `
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
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, initLen int) int {\n")
fmt.Fprint(b, "currentLen := initLen\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, "currentLen -= len(x.%s) + 1\n", st.Field(i).Name())
fmt.Fprintf(b, "currentLen += compressionLenHelper(c, x.%s, currentLen)\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 {
currentLen -= len(x.%s[i]) + 1
}
`, st.Field(i).Name(), st.Field(i).Name())
fmt.Fprintf(b, `for i := range x.%s {
currentLen += compressionLenHelper(c, x.%s[i], currentLen)
}
`, 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, "}\nreturn currentLen - initLen\n}\n\n")
// compressionLenSearchType - search cdomain-tags types for compressible names.
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {\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, sz%d := compressionLenSearch(c, x.%s)\n", j, 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"
sz := "sz1"
for i := 2; i < j; i++ {
k += fmt.Sprintf(" + k%d", i)
ok += fmt.Sprintf(" && ok%d", i)
sz += fmt.Sprintf(" + sz%d", i)
}
fmt.Fprintf(b, "return %s, %s, %s\n", k, ok, sz)
}
fmt.Fprintln(b, "}\nreturn 0, false, 0\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,6 +4,7 @@ import (
"errors" "errors"
"net" "net"
"strconv" "strconv"
"strings"
) )
const hexDigit = "0123456789abcdef" const hexDigit = "0123456789abcdef"
@ -145,10 +146,9 @@ 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 {
// EDNS0 is at the end of the additional section, start there. // RFC 6891, Section 6.1.1 allows the OPT record to appear
// We might want to change this to *only* look at the last two // anywhere in the additional record section, but it's usually at
// records. So we see TSIG and/or OPT - this a slightly bigger // the end so start there.
// 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,17 +157,93 @@ 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, but there is no length check for the entire // label fits in 63 characters and that the entire name will fit into the 255
// string s. I.e. a domain name longer than 255 characters is considered valid. // octet wire format limit.
func IsDomainName(s string) (labels int, ok bool) { func IsDomainName(s string) (labels int, ok bool) {
_, labels, err := packDomainName(s, nil, 0, nil, false) // XXX: The logic in this function was copied from packDomainName and
return labels, err == nil // should be kept in sync with that function.
const lenmsg = 256
if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata.
return 0, false
}
s = Fqdn(s)
// Each dot ends a segment of the name. Except for escaped dots (\.), which
// are normal dots.
var (
off int
begin int
wasDot bool
)
for i := 0; i < len(s); i++ {
switch s[i] {
case '\\':
if off+1 > lenmsg {
return labels, false
}
// check for \DDD
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
i += 3
begin += 3
} else {
i++
begin++
}
wasDot = false
case '.':
if wasDot {
// two dots back to back is not legal
return labels, false
}
wasDot = true
labelLen := i - begin
if labelLen >= 1<<6 { // top two bits of length must be clear
return labels, false
}
// off can already (we're in a loop) be bigger than lenmsg
// this happens when a name isn't fully qualified
off += 1 + labelLen
if off > lenmsg {
return labels, false
}
labels++
begin = i + 1
default:
wasDot = false
}
}
return labels, true
} }
// IsSubDomain checks if child is indeed a child of the parent. If child and parent // IsSubDomain checks if child is indeed a child of the parent. If child and parent
@ -181,7 +257,7 @@ func IsSubDomain(parent, child string) bool {
// The checking is performed on the binary payload. // The checking is performed on the binary payload.
func IsMsg(buf []byte) error { func IsMsg(buf []byte) error {
// Header // Header
if len(buf) < 12 { if len(buf) < headerSize {
return errors.New("dns: bad message header") return errors.New("dns: bad message header")
} }
// Header: Opcode // Header: Opcode
@ -191,11 +267,18 @@ 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 {
l := len(s) s2 := strings.TrimSuffix(s, ".")
if l == 0 { if s == s2 {
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.
@ -244,12 +327,19 @@ 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 ip.To4() != nil { if v4 := ip.To4(); v4 != nil {
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." + buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil // Add it, in reverse, to the buffer
for i := len(v4) - 1; i >= 0; i-- {
buf = strconv.AppendInt(buf, int64(v4[i]), 10)
buf = append(buf, '.')
}
// Append "in-addr.arpa." and return (buf already has the final .)
buf = append(buf, "in-addr.arpa."...)
return string(buf), nil
} }
// Must be IPv6 // Must be IPv6
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa.")) buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
// Add it, in reverse, to the buffer // 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]

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

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

View File

@ -67,9 +67,6 @@ 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
@ -102,9 +99,6 @@ 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
@ -147,8 +141,8 @@ func (k *DNSKEY) KeyTag() uint16 {
switch k.Algorithm { switch k.Algorithm {
case RSAMD5: case RSAMD5:
// Look at the bottom two bytes of the modules, which the last // Look at the bottom two bytes of the modules, which the last
// item in the pubkey. We could do this faster by looking directly // item in the pubkey.
// at the base64 values. But I'm lazy. // This algorithm has been deprecated, but keep this key-tag calculation.
modulus, _ := fromBase64([]byte(k.PublicKey)) modulus, _ := fromBase64([]byte(k.PublicKey))
if len(modulus) > 1 { if len(modulus) > 1 {
x := binary.BigEndian.Uint16(modulus[len(modulus)-2:]) x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
@ -268,16 +262,17 @@ 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 = rrset[0].Header().Name rr.Hdr.Name = h0.Name
rr.Hdr.Class = rrset[0].Header().Class rr.Hdr.Class = h0.Class
if rr.OrigTtl == 0 { // If set don't override if rr.OrigTtl == 0 { // If set don't override
rr.OrigTtl = rrset[0].Header().Ttl rr.OrigTtl = h0.Ttl
} }
rr.TypeCovered = rrset[0].Header().Rrtype rr.TypeCovered = h0.Rrtype
rr.Labels = uint8(CountLabel(rrset[0].Header().Name)) rr.Labels = uint8(CountLabel(h0.Name))
if strings.HasPrefix(rrset[0].Header().Name, "*") { if strings.HasPrefix(h0.Name, "*") {
rr.Labels-- // wildcard, remove from label count rr.Labels-- // wildcard, remove from label count
} }
@ -323,6 +318,9 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
case RSAMD5, DSA, DSANSEC3SHA1:
// See RFC 6944.
return ErrAlg
default: default:
h := hash.New() h := hash.New()
h.Write(signdata) h.Write(signdata)
@ -401,7 +399,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.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) { if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
return ErrKey return ErrKey
} }
if k.Protocol != 3 { if k.Protocol != 3 {
@ -411,10 +409,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
// IsRRset checked that we have at least one RR and that the RRs in // 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 rrset[0].Header().Class != rr.Hdr.Class { if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
return ErrRRset
}
if rrset[0].Header().Rrtype != rr.TypeCovered {
return ErrRRset return ErrRRset
} }
@ -563,20 +558,19 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
pubkey := new(rsa.PublicKey) pubkey := new(rsa.PublicKey)
expo := uint64(0) var expo uint64
for i := 0; i < int(explen); i++ { // The exponent of length explen is between keyoff and modoff.
for _, v := range keybuf[keyoff:modoff] {
expo <<= 8 expo <<= 8
expo |= uint64(keybuf[keyoff+i]) expo |= uint64(v)
} }
if expo > 1<<31-1 { if expo > 1<<31-1 {
// Larger exponent than supported by the crypto package. // Larger exponent than supported by the crypto package.
return nil return nil
} }
pubkey.E = int(expo) pubkey.E = int(expo)
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
pubkey.N = big.NewInt(0)
pubkey.N.SetBytes(keybuf[modoff:])
return pubkey return pubkey
} }
@ -601,10 +595,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
return nil return nil
} }
} }
pubkey.X = big.NewInt(0) pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
pubkey.X.SetBytes(keybuf[:len(keybuf)/2]) pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
pubkey.Y = big.NewInt(0)
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
return pubkey return pubkey
} }
@ -625,10 +617,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 = big.NewInt(0).SetBytes(q) pubkey.Parameters.Q = new(big.Int).SetBytes(q)
pubkey.Parameters.P = big.NewInt(0).SetBytes(p) pubkey.Parameters.P = new(big.Int).SetBytes(p)
pubkey.Parameters.G = big.NewInt(0).SetBytes(g) pubkey.Parameters.G = new(big.Int).SetBytes(g)
pubkey.Y = big.NewInt(0).SetBytes(y) pubkey.Y = new(big.Int).SetBytes(y)
return pubkey return pubkey
} }
@ -658,15 +650,16 @@ 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()
r1.Header().Ttl = s.OrigTtl h := r1.Header()
labels := SplitDomainName(r1.Header().Name) h.Ttl = s.OrigTtl
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
r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
} }
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
r1.Header().Name = strings.ToLower(r1.Header().Name) h.Name = strings.ToLower(h.Name)
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase. // 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,
@ -724,7 +717,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, r1.len()+1) // +1 to be safe(r) wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
off, err1 := PackRR(r1, wire, 0, nil, false) off, err1 := PackRR(r1, wire, 0, nil, false)
if err1 != nil { if err1 != nil {
return nil, err1 return nil, err1

View File

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

View File

@ -3,7 +3,6 @@ package dns
import ( import (
"bufio" "bufio"
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"io" "io"
@ -44,19 +43,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
return nil, ErrPrivKey return nil, ErrPrivKey
} }
switch uint8(algo) { switch uint8(algo) {
case DSA: case RSAMD5, DSA, DSANSEC3SHA1:
priv, err := readPrivateKeyDSA(m) return nil, ErrAlg
if err != nil {
return nil, err
}
pub := k.publicKeyDSA()
if pub == nil {
return nil, ErrKey
}
priv.PublicKey = *pub
return priv, nil
case RSAMD5:
fallthrough
case RSASHA1: case RSASHA1:
fallthrough fallthrough
case RSASHA1NSEC3SHA1: case RSASHA1NSEC3SHA1:
@ -109,21 +97,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
} }
switch k { switch k {
case "modulus": case "modulus":
p.PublicKey.N = big.NewInt(0) p.PublicKey.N = new(big.Int).SetBytes(v1)
p.PublicKey.N.SetBytes(v1)
case "publicexponent": case "publicexponent":
i := big.NewInt(0) i := new(big.Int).SetBytes(v1)
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 = big.NewInt(0) p.D = new(big.Int).SetBytes(v1)
p.D.SetBytes(v1)
case "prime1": case "prime1":
p.Primes[0] = big.NewInt(0) p.Primes[0] = new(big.Int).SetBytes(v1)
p.Primes[0].SetBytes(v1)
case "prime2": case "prime2":
p.Primes[1] = big.NewInt(0) p.Primes[1] = new(big.Int).SetBytes(v1)
p.Primes[1].SetBytes(v1)
} }
case "exponent1", "exponent2", "coefficient": case "exponent1", "exponent2", "coefficient":
// not used in Go (yet) // not used in Go (yet)
@ -134,27 +117,9 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
return p, nil return p, nil
} }
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
p := new(dsa.PrivateKey)
p.X = big.NewInt(0)
for k, v := range m {
switch k {
case "private_value(x)":
v1, err := fromBase64([]byte(v))
if err != nil {
return nil, err
}
p.X.SetBytes(v1)
case "created", "publish", "activate":
/* not used in Go (yet) */
}
}
return p, nil
}
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) { func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
p := new(ecdsa.PrivateKey) p := new(ecdsa.PrivateKey)
p.D = big.NewInt(0) p.D = new(big.Int)
// 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 {
@ -322,6 +287,11 @@ func (kl *klexer) Next() (lex, bool) {
commt = false commt = false
} }
if kl.key && str.Len() == 0 {
// ignore empty lines
break
}
kl.key = true kl.key = true
l.value = zValue l.value = zValue

View File

@ -13,6 +13,8 @@ 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
@ -31,12 +33,11 @@ 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
one := big.NewInt(1) p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
p1 := big.NewInt(0).Sub(p.Primes[0], one) q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
q1 := big.NewInt(0).Sub(p.Primes[1], one) exp1 := new(big.Int).Mod(p.D, p1)
exp1 := big.NewInt(0).Mod(p.D, p1) exp2 := new(big.Int).Mod(p.D, q1)
exp2 := big.NewInt(0).Mod(p.D, q1) coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
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())

107
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.
Server- and client-side programming is supported. Both server- and client-side programming is supported. The package allows
The package allows complete control over what is sent out to the DNS. The package complete control over what is sent out to the DNS. The API follows the
API follows the less-is-more principle, by presenting a small, clean interface. less-is-more principle, by presenting a small, clean interface.
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers, It supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing. 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. Resource records are native types. They are not stored in wire format. Basic
Basic usage pattern for creating a new resource record: 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, r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
Class: dns.ClassINET, Ttl: 3600}
r.Preference = 10 r.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 In the DNS messages are exchanged, these messages contain resource records
records (sets). Use pattern for creating a message: (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 message m is now a message with the question section set to ask the MX
the MX records for the miek.nl. zone. 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,9 +51,8 @@ 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. After creating a message it can be sent. Basic use pattern for synchronous
Basic use pattern for synchronous querying the DNS at a querying the DNS at a server configured on 127.0.0.1 and port 53:
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")
@ -99,25 +98,24 @@ 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 Both domain names and TXT character strings are converted to presentation form
form both when unpacked and when converted to strings. 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 converted to \t, \r and \n respectively. Back slashes and quotations marks will
will be escaped. Bytes below 32 and above 127 will be converted to \DDD be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
form.
For domain names, in addition to the above rules brackets, periods, For domain names, in addition to the above rules brackets, periods, spaces,
spaces, semicolons and the at symbol are escaped. semicolons and the at symbol are escaped.
DNSSEC DNSSEC
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
uses public key cryptography to sign resource records. The public key cryptography to sign resource records. The public keys are stored in
public keys are stored in DNSKEY records and the signatures in RRSIG records. DNSKEY records and the signatures in RRSIG records.
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
to a request. bit to a request.
m := new(dns.Msg) m := new(dns.Msg)
m.SetEdns0(4096, true) m.SetEdns0(4096, true)
@ -126,9 +124,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 Dynamic updates reuses the DNS message format, but renames three of the
the sections. Question is Zone, Answer is Prerequisite, Authority is sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
Update, only the Additional is not renamed. See RFC 2136 for the gory details. 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
@ -145,10 +143,9 @@ 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. The prerequisite section can also be left empty. If you have decided on the
If you have decided on the prerequisites you can tell what RRs should prerequisites you can tell what RRs should be added or deleted. The next table
be added or deleted. The next table shows the options you have and shows the options you have and what functions to call.
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
@ -181,10 +178,10 @@ changes to the RRset after calling SetTsig() the signature will be incorrect.
... ...
// When sending the TSIG RR is calculated and filled in before sending // When sending the TSIG RR is calculated and filled in before sending
When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with When requesting an zone transfer (almost all TSIG usage is when requesting zone
TSIG, this is the basic use pattern. In this example we request an AXFR for transfers), with TSIG, this is the basic use pattern. In this example we
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A==" request an AXFR for miek.nl. with TSIG key named "axfr." and secret
and using the server 176.58.119.54: "so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
t := new(dns.Transfer) t := new(dns.Transfer)
m := new(dns.Msg) m := new(dns.Msg)
@ -194,8 +191,8 @@ and using the server 176.58.119.54:
c, err := t.In(m, "176.58.119.54:53") 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 is checked with TSIG. You can now read the records from the transfer as they come in. Each envelope
If something is not correct an error is returned. is checked with TSIG. If something is not correct an error is returned.
Basic use pattern validating and replying to a message that has TSIG set. Basic use pattern validating and replying to a message that has TSIG set.
@ -220,29 +217,30 @@ 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 RFC 6895 sets aside a range of type codes for private use. This range is 65,280
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these - 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 http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more See https://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
information. information.
EDNS0 EDNS0
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely 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) The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
interfaces. Currently only a few have been standardized: EDNS0_NSID Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
that these options may be combined in an OPT RR. may be combined in an OPT RR. Basic use pattern for a server to check if (and
Basic use pattern for a server to check if (and which) options are set: which) options are set:
// o is a dns.OPT // o is a dns.OPT
for _, s := range o.Option { for _, s := range o.Option {
@ -262,10 +260,9 @@ 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 the shared It works like TSIG, except that SIG(0) uses public key cryptography, instead of
secret approach in TSIG. the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
RSASHA512.
Signing subsequent messages in multi-message sessions is not implemented. Signing subsequent messages in multi-message sessions is not implemented.
*/ */

View File

@ -7,19 +7,32 @@ package dns
// is so, otherwise false. // is so, otherwise false.
// It's is a protocol violation to have identical RRs in a message. // It's is a protocol violation to have identical RRs in a message.
func IsDuplicate(r1, r2 RR) bool { func IsDuplicate(r1, r2 RR) bool {
if r1.Header().Class != r2.Header().Class { // Check whether the record header is identical.
if !r1.Header().isDuplicate(r2.Header()) {
return false return false
} }
if r1.Header().Rrtype != r2.Header().Rrtype {
// 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 return false
} }
if !isDulicateName(r1.Header().Name, r2.Header().Name) { if r1.Class != r2.Class {
return false
}
if r1.Rrtype != r2.Rrtype {
return false
}
if !isDuplicateName(r1.Name, r2.Name) {
return false return false
} }
// ignore TTL // ignore TTL
return true
return isDuplicateRdata(r1, r2)
} }
// isDulicateName checks if the domain names s1 and s2 are equal. // isDuplicateName checks if the domain names s1 and s2 are equal.
func isDulicateName(s1, s2 string) bool { return equal(s1, s2) } func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }

View File

@ -57,10 +57,7 @@ func main() {
continue continue
} }
if name == "PrivateRR" || name == "RFC3597" { if name == "PrivateRR" || name == "OPT" {
continue
}
if name == "OPT" || name == "ANY" || name == "IXFR" || name == "AXFR" {
continue continue
} }
@ -70,22 +67,6 @@ func main() {
b := &bytes.Buffer{} b := &bytes.Buffer{}
b.WriteString(packageHdr) b.WriteString(packageHdr)
// Generate the giant switch that calls the correct function for each type.
fmt.Fprint(b, "// isDuplicateRdata calls the rdata specific functions\n")
fmt.Fprint(b, "func isDuplicateRdata(r1, r2 RR) bool {\n")
fmt.Fprint(b, "switch r1.Header().Rrtype {\n")
for _, name := range namedTypes {
o := scope.Lookup(name)
_, isEmbedded := getTypeStruct(o.Type(), scope)
if isEmbedded {
continue
}
fmt.Fprintf(b, "case Type%s:\nreturn isDuplicate%s(r1.(*%s), r2.(*%s))\n", name, name, name, name)
}
fmt.Fprintf(b, "}\nreturn false\n}\n")
// Generate the duplicate check for each type. // Generate the duplicate check for each type.
fmt.Fprint(b, "// isDuplicate() functions\n\n") fmt.Fprint(b, "// isDuplicate() functions\n\n")
for _, name := range namedTypes { for _, name := range namedTypes {
@ -95,7 +76,10 @@ func main() {
if isEmbedded { if isEmbedded {
continue continue
} }
fmt.Fprintf(b, "func isDuplicate%s(r1, r2 *%s) bool {\n", name, name) 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++ { for i := 1; i < st.NumFields(); i++ {
field := st.Field(i).Name() field := st.Field(i).Name()
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) } o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
@ -103,12 +87,12 @@ func main() {
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are // 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). // *indirectly* defined as a slice in the net package).
if _, ok := st.Field(i).Type().(*types.Slice); ok || st.Tag(i) == `dns:"a"` || st.Tag(i) == `dns:"aaaa"` { if _, ok := st.Field(i).Type().(*types.Slice); ok {
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}") o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` { if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
o3(`for i := 0; i < len(r1.%s); i++ { o3(`for i := 0; i < len(r1.%s); i++ {
if !isDulicateName(r1.%s[i], r2.%s[i]) { if !isDuplicateName(r1.%s[i], r2.%s[i]) {
return false return false
} }
}`) }`)
@ -128,8 +112,10 @@ func main() {
switch st.Tag(i) { switch st.Tag(i) {
case `dns:"-"`: case `dns:"-"`:
// ignored // ignored
case `dns:"a"`, `dns:"aaaa"`:
o2("if !r1.%s.Equal(r2.%s) {\nreturn false\n}")
case `dns:"cdomain-name"`, `dns:"domain-name"`: case `dns:"cdomain-name"`, `dns:"domain-name"`:
o2("if !isDulicateName(r1.%s, r2.%s) {\nreturn false\n}") o2("if !isDuplicateName(r1.%s, r2.%s) {\nreturn false\n}")
default: default:
o2("if r1.%s != r2.%s {\nreturn false\n}") o2("if r1.%s != r2.%s {\nreturn false\n}")
} }

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

@ -78,16 +78,22 @@ func (rr *OPT) String() string {
return s return s
} }
func (rr *OPT) len() int { func (rr *OPT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
for i := 0; i < len(rr.Option); i++ { for _, o := range rr.Option {
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, _ := rr.Option[i].pack() lo, _ := o.pack()
l += len(lo) l += len(lo)
} }
return l return l
} }
func (rr *OPT) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on OPT")
}
func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
// return the old value -> delete SetVersion? // 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.
@ -102,15 +108,14 @@ func (rr *OPT) SetVersion(v uint8) {
// 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) + 15 return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
} }
// SetExtendedRcode sets the EDNS extended RCODE field. // SetExtendedRcode sets the EDNS extended RCODE field.
func (rr *OPT) SetExtendedRcode(v uint8) { //
if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have! // If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
return func (rr *OPT) SetExtendedRcode(v uint16) {
} rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v-15)<<24
} }
// UDPSize returns the UDP buffer size. // UDPSize returns the UDP buffer size.
@ -154,6 +159,8 @@ 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
@ -184,7 +191,8 @@ 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 string(e.Nsid) } func (e *EDNS0_NSID) String() string { return e.Nsid }
func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver // 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
@ -274,22 +282,16 @@ 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([]byte, net.IPv4len) addr := make(net.IP, net.IPv4len)
for i := 0; i < net.IPv4len && 4+i < len(b); i++ { copy(addr, b[4:])
addr[i] = b[4+i] e.Address = addr.To16()
}
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([]byte, net.IPv6len) addr := make(net.IP, net.IPv6len)
for i := 0; i < net.IPv6len && 4+i < len(b); i++ { copy(addr, b[4:])
addr[i] = b[4+i] e.Address = addr
}
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")
} }
@ -308,6 +310,16 @@ 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)
@ -343,6 +355,7 @@ 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
@ -364,6 +377,7 @@ 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) {
@ -418,10 +432,13 @@ 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(uint64(e.Id), 10) + " " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(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. // EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
type EDNS0_DAU struct { type EDNS0_DAU struct {
@ -436,15 +453,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 i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := AlgorithmToString[e.AlgCode[i]]; ok { if a, ok := AlgorithmToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
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. // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
type EDNS0_DHU struct { type EDNS0_DHU struct {
@ -459,15 +477,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 i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := HashToString[e.AlgCode[i]]; ok { if a, ok := HashToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
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. // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
type EDNS0_N3U struct { type EDNS0_N3U struct {
@ -483,15 +502,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 i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := HashToString[e.AlgCode[i]]; ok { if a, ok := HashToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
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. // EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct { type EDNS0_EXPIRE struct {
@ -502,13 +522,11 @@ 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)
b[0] = byte(e.Expire >> 24) binary.BigEndian.PutUint32(b, e.Expire)
b[1] = byte(e.Expire >> 16)
b[2] = byte(e.Expire >> 8)
b[3] = byte(e.Expire)
return b, nil return b, nil
} }
@ -543,6 +561,11 @@ 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))
@ -615,6 +638,7 @@ 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
@ -628,3 +652,8 @@ 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 k := d.Kind(); k { switch d.Kind() {
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,6 +31,9 @@ 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()),
@ -42,6 +45,9 @@ 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

@ -49,11 +49,15 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
if err != nil { if err != nil {
return zp.setParseError("bad stop in $GENERATE range", l) return zp.setParseError("bad stop in $GENERATE range", l)
} }
if end < 0 || start < 0 || end < start { if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
return zp.setParseError("bad range in $GENERATE range", l) return zp.setParseError("bad range in $GENERATE range", l)
} }
zp.c.Next() // _BLANK // _BLANK
l, ok := zp.c.Next()
if !ok || l.value != zBlank {
return zp.setParseError("garbage after $GENERATE range", l)
}
// Create a complete new string, which we then parse again. // Create a complete new string, which we then parse again.
var s string var s string

12
vendor/github.com/miekg/dns/go.mod generated vendored Normal file
View File

@ -0,0 +1,12 @@
module github.com/miekg/dns
go 1.12
require (
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
golang.org/x/net v0.0.0-20190923162816-aa69164e4478
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 // indirect
)

33
vendor/github.com/miekg/dns/go.sum generated vendored Normal file
View File

@ -0,0 +1,33 @@
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4 h1:Vk3wNqEZwyGyei9yq5ekj7frek2u7HUfffJ1/opblzc=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3 h1:dgd4x4kJt7G4k4m93AYLzM8Ni6h2qLTfh9n9vXJT3/0=
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611 h1:O33LKL7WyJgjN9CvxfTIomjIClbd/Kq86/iipowHQU0=
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

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 s[len(s)-1] == '.' { if IsFqdn(s) {
fqdnEnd = len(s) - 1 fqdnEnd = len(s) - 1
} else { } else {
fqdnEnd = len(s) fqdnEnd = len(s)
@ -28,16 +28,13 @@ func SplitDomainName(s string) (labels []string) {
case 1: case 1:
// no-op // no-op
default: default:
end := 0 for _, end := range idx[1:] {
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
} }
} }
labels = append(labels, s[begin:fqdnEnd]) return append(labels, s[begin:fqdnEnd])
return labels
} }
// CompareDomainName compares the names s1 and s2 and // CompareDomainName compares the names s1 and s2 and

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

File diff suppressed because it is too large Load Diff

View File

@ -80,13 +80,7 @@ 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 map[string]int, compress bool) (int, error) {\n", name) fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err 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())
@ -106,7 +100,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, compress)\n") o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n")
default: default:
log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
} }
@ -116,9 +110,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"`:
@ -154,7 +148,8 @@ 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) == "":
@ -176,8 +171,6 @@ 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")
} }
@ -186,14 +179,8 @@ 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 unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name) fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name)
fmt.Fprintf(b, "rr := new(%s)\n", name) fmt.Fprint(b, `rdStart := off
fmt.Fprint(b, "rr.Hdr = h\n")
fmt.Fprint(b, `if noRdata(h) {
return rr, off, nil
}
var err error
rdStart := off
_ = rdStart _ = rdStart
`) `)
@ -201,7 +188,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 rr, off, err return off, err
} }
`) `)
} }
@ -221,7 +208,7 @@ return rr, 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 rr, off, err return off, err
} }
`) `)
continue continue
@ -264,6 +251,8 @@ return rr, 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 "":
@ -287,22 +276,13 @@ return rr, 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 rr, off, nil return off, nil
} }
`) `)
} }
} }
fmt.Fprintf(b, "return rr, off, err }\n\n") fmt.Fprintf(b, "return off, nil }\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

@ -25,12 +25,13 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataA(a net.IP, msg []byte, off int) (int, error) { 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:
@ -51,12 +52,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) { 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:
@ -99,14 +100,14 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
return hdr, off, msg, err return hdr, off, msg, err
} }
// pack packs an RR header, returning the offset to the end of the header. // packHeader packs an RR header, returning the offset to the end of the header.
// See PackDomainName for documentation about the compression. // See PackDomainName for documentation about the compression.
func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) { func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
if off == len(msg) { 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
} }
@ -122,7 +123,7 @@ func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compr
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
off, err = packUint16(hdr.Rdlength, msg, off) off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
@ -177,14 +178,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 uint8(msg[off]), off + 1, nil return 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] = byte(i) msg[off] = i
return off + 1, nil return off + 1, nil
} }
@ -223,8 +224,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"} 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(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 | i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
uint64(msg[off+4])<<8 | uint64(msg[off+5])) uint64(msg[off+4])<<8 | uint64(msg[off+5])
off += 6 off += 6
return i, off, nil return i, off, nil
} }
@ -264,24 +265,36 @@ func unpackString(msg []byte, off int) (string, int, error) {
return "", off, &Error{err: "overflow unpacking txt"} return "", off, &Error{err: "overflow unpacking txt"}
} }
l := int(msg[off]) l := int(msg[off])
if off+l+1 > len(msg) { off++
if off+l > len(msg) {
return "", off, &Error{err: "overflow unpacking txt"} return "", off, &Error{err: "overflow unpacking txt"}
} }
var s strings.Builder var s strings.Builder
s.Grow(l) consumed := 0
for _, b := range msg[off+1 : off+1+l] { for i, b := range msg[off : off+l] {
switch { switch {
case b == '"' || b == '\\': case b == '"' || b == '\\':
if consumed == 0 {
s.Grow(l * 2)
}
s.Write(msg[off+consumed : off+i])
s.WriteByte('\\') s.WriteByte('\\')
s.WriteByte(b) s.WriteByte(b)
consumed = i + 1
case b < ' ' || b > '~': // unprintable case b < ' ' || b > '~': // unprintable
writeEscapedByte(&s, b) if consumed == 0 {
default: s.Grow(l * 2)
s.WriteByte(b) }
s.Write(msg[off+consumed : off+i])
s.WriteString(escapeByte(b))
consumed = i + 1
} }
} }
off += 1 + l if consumed == 0 { // no escaping needed
return s.String(), off, nil return string(msg[off : off+l]), off + l, nil
}
s.Write(msg[off+consumed : off+l])
return s.String(), off + l, nil
} }
func packString(s string, msg []byte, off int) (int, error) { func packString(s string, msg []byte, off int) (int, error) {
@ -363,6 +376,22 @@ 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 {
@ -383,7 +412,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:
code := uint16(0) var code uint16
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"}
} }
@ -478,7 +507,7 @@ Option:
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) { func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
for _, el := range options { for _, el := range options {
b, err := el.pack() b, err := el.pack()
if err != nil || off+3 > len(msg) { if err != nil || off+4 > len(msg) {
return len(msg), &Error{err: "overflow packing opt"} return len(msg), &Error{err: "overflow packing opt"}
} }
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
@ -537,8 +566,7 @@ 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 := 0; j < length; j++ { for j, b := range msg[off : off+length] {
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))
@ -571,13 +599,35 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
return nsec, off, nil return nsec, off, nil
} }
// typeBitMapLen is a helper function which computes the "maximum" length of
// a the NSEC Type BitMap field.
func typeBitMapLen(bitmap []uint16) int {
var l int
var lastwindow, lastlength uint16
for _, t := range bitmap {
window := t / 256
length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
l += int(lastlength) + 2
lastlength = 0
}
if window < lastwindow || length < lastlength {
// packDataNsec would return Error{err: "nsec bits out of order"} here, but
// when computing the length, we want do be liberal.
continue
}
lastwindow, lastlength = window, length
}
l += int(lastlength) + 2
return l
}
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) { func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
if len(bitmap) == 0 { if len(bitmap) == 0 {
return off, nil return off, nil
} }
var lastwindow, lastlength uint16 var lastwindow, lastlength uint16
for j := 0; j < len(bitmap); j++ { for _, t := range bitmap {
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
@ -621,10 +671,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 map[string]int, compress bool) (int, error) { func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
var err error var err error
for j := 0; j < len(names); j++ { for _, name := range names {
off, err = PackDomainName(names[j], msg, off, compression, false && compress) off, err = packDomainName(name, msg, off, compression, compress)
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }

111
vendor/github.com/miekg/dns/msg_truncate.go generated vendored Normal file
View File

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

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

@ -2,49 +2,44 @@ package dns
import ( import (
"crypto/sha1" "crypto/sha1"
"hash" "encoding/hex"
"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 {
saltwire := new(saltWireFmt) if ha != SHA1 {
saltwire.Salt = salt return ""
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 ""
} }
wire = wire[:n] wireSalt = wireSalt[: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(wire) s.Write(wireSalt)
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(wire) s.Write(wireSalt)
nsec3 = s.Sum(nsec3[:0]) nsec3 = s.Sum(nsec3[:0])
} }
return toBase32(nsec3) return toBase32(nsec3)
} }
@ -63,8 +58,10 @@ func (rr *NSEC3) Cover(name string) bool {
} }
nextHash := rr.NextDomain nextHash := rr.NextDomain
if ownerHash == nextHash { // empty interval
return false // if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash
if ownerHash == nextHash && nameHash != ownerHash { // empty interval
return true
} }
if ownerHash > nextHash { // end of zone if 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
@ -96,11 +93,3 @@ 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

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

View File

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

View File

@ -12,6 +12,20 @@ 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

@ -15,10 +15,11 @@ 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 _, ok := m[key]; ok { if mr, ok := m[key]; ok {
// Shortest TTL wins. // Shortest TTL wins.
if m[key].Header().Ttl > r.Header().Ttl { rh, mrh := r.Header(), mr.Header()
m[key].Header().Ttl = r.Header().Ttl if mrh.Ttl > rh.Ttl {
mrh.Ttl = rh.Ttl
} }
continue continue
} }

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

@ -79,13 +79,12 @@ func (e *ParseError) Error() (s string) {
} }
type lex struct { type lex struct {
token string // text of the token token string // text of the token
err bool // when true, token text has lexer error err bool // when true, token text has lexer error
value uint8 // value: zString, _BLANK, etc. value uint8 // value: zString, _BLANK, etc.
torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
line int // line in the file line int // line in the file
column int // column in the file column int // column in the file
comment string // any comment text seen
} }
// Token holds the token that are returned when a zone file is parsed. // Token holds the token that are returned when a zone file is parsed.
@ -135,7 +134,7 @@ func ReadRR(r io.Reader, file string) (RR, error) {
} }
// ParseZone reads a RFC 1035 style zonefile from r. It returns // ParseZone reads a RFC 1035 style zonefile from r. It returns
// *Tokens on the returned channel, each consisting of either a // Tokens on the returned channel, each consisting of either a
// parsed RR and optional comment or a nil RR and an error. The // parsed RR and optional comment or a nil RR and an error. The
// channel is closed by ParseZone when the end of r is reached. // channel is closed by ParseZone when the end of r is reached.
// //
@ -144,7 +143,8 @@ func ReadRR(r io.Reader, file string) (RR, error) {
// origin, as if the file would start with an $ORIGIN directive. // origin, as if the file would start with an $ORIGIN directive.
// //
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
// supported. // supported. Note that $GENERATE's range support up to a maximum of
// of 65535 steps.
// //
// Basic usage pattern when reading from a string (z) containing the // Basic usage pattern when reading from a string (z) containing the
// zone data: // zone data:
@ -204,6 +204,7 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) {
// //
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
// supported. Although $INCLUDE is disabled by default. // supported. Although $INCLUDE is disabled by default.
// Note that $GENERATE's range support up to a maximum of 65535 steps.
// //
// Basic usage pattern when reading from a string (z) containing the // Basic usage pattern when reading from a string (z) containing the
// zone data: // zone data:
@ -244,8 +245,6 @@ type ZoneParser struct {
sub *ZoneParser sub *ZoneParser
osFile *os.File osFile *os.File
com string
includeDepth uint8 includeDepth uint8
includeAllowed bool includeAllowed bool
@ -318,12 +317,19 @@ func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) {
// Comment returns an optional text comment that occurred alongside // Comment returns an optional text comment that occurred alongside
// the RR. // the RR.
func (zp *ZoneParser) Comment() string { func (zp *ZoneParser) Comment() string {
return zp.com if zp.parseErr != nil {
return ""
}
if zp.sub != nil {
return zp.sub.Comment()
}
return zp.c.Comment()
} }
func (zp *ZoneParser) subNext() (RR, bool) { func (zp *ZoneParser) subNext() (RR, bool) {
if rr, ok := zp.sub.Next(); ok { if rr, ok := zp.sub.Next(); ok {
zp.com = zp.sub.com
return rr, true return rr, true
} }
@ -347,8 +353,6 @@ func (zp *ZoneParser) subNext() (RR, bool) {
// error. After Next returns (nil, false), the Err method will return // error. After Next returns (nil, false), the Err method will return
// any error that occurred during parsing. // any error that occurred during parsing.
func (zp *ZoneParser) Next() (RR, bool) { func (zp *ZoneParser) Next() (RR, bool) {
zp.com = ""
if zp.parseErr != nil { if zp.parseErr != nil {
return nil, false return nil, false
} }
@ -501,9 +505,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError("expecting $TTL value, not this...", l) return zp.setParseError("expecting $TTL value, not this...", l)
} }
if e, _ := slurpRemainder(zp.c, zp.file); e != nil { if err := slurpRemainder(zp.c); err != nil {
zp.parseErr = e return zp.setParseError(err.err, err.lex)
return nil, false
} }
ttl, ok := stringToTTL(l.token) ttl, ok := stringToTTL(l.token)
@ -525,9 +528,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError("expecting $ORIGIN value, not this...", l) return zp.setParseError("expecting $ORIGIN value, not this...", l)
} }
if e, _ := slurpRemainder(zp.c, zp.file); e != nil { if err := slurpRemainder(zp.c); err != nil {
zp.parseErr = e return zp.setParseError(err.err, err.lex)
return nil, false
} }
name, ok := toAbsoluteName(l.token, zp.origin) name, ok := toAbsoluteName(l.token, zp.origin)
@ -648,20 +650,44 @@ func (zp *ZoneParser) Next() (RR, bool) {
st = zExpectRdata st = zExpectRdata
case zExpectRdata: case zExpectRdata:
r, e, c1 := setRR(*h, zp.c, zp.origin, zp.file) var rr RR
if e != nil { if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) {
// If e.lex is nil than we have encounter a unknown RR type rr = newFn()
// in that case we substitute our current lex token *rr.Header() = *h
if e.lex.token == "" && e.lex.value == 0 { } else {
e.lex = l // Uh, dirty rr = &RFC3597{Hdr: *h}
}
zp.parseErr = e
return nil, false
} }
zp.com = c1 _, isPrivate := rr.(*PrivateRR)
return r, true if !isPrivate && zp.c.Peek().token == "" {
// This is a dynamic update rr.
// TODO(tmthrgd): Previously slurpRemainder was only called
// for certain RR types, which may have been important.
if err := slurpRemainder(zp.c); err != nil {
return zp.setParseError(err.err, err.lex)
}
return rr, true
} else if l.value == zNewline {
return zp.setParseError("unexpected newline", l)
}
if err := rr.parse(zp.c, zp.origin); err != nil {
// err is a concrete *ParseError without the file field set.
// The setParseError call below will construct a new
// *ParseError with file set to zp.file.
// If err.lex is nil than we have encounter an unknown RR type
// in that case we substitute our current lex token.
if err.lex == (lex{}) {
return zp.setParseError(err.err, l)
}
return zp.setParseError(err.err, err.lex)
}
return rr, true
} }
} }
@ -670,6 +696,18 @@ func (zp *ZoneParser) Next() (RR, bool) {
return nil, false return nil, false
} }
// canParseAsRR returns true if the record type can be parsed as a
// concrete RR. It blacklists certain record types that must be parsed
// according to RFC 3597 because they lack a presentation format.
func canParseAsRR(rrtype uint16) bool {
switch rrtype {
case TypeANY, TypeNULL, TypeOPT, TypeTSIG:
return false
default:
return true
}
}
type zlexer struct { type zlexer struct {
br io.ByteReader br io.ByteReader
@ -678,9 +716,11 @@ type zlexer struct {
line int line int
column int column int
com string comBuf string
comment string
l lex l lex
cachedL *lex
brace int brace int
quote bool quote bool
@ -746,13 +786,37 @@ func (zl *zlexer) readByte() (byte, bool) {
return c, true return c, true
} }
func (zl *zlexer) Peek() lex {
if zl.nextL {
return zl.l
}
l, ok := zl.Next()
if !ok {
return l
}
if zl.nextL {
// Cache l. Next returns zl.cachedL then zl.l.
zl.cachedL = &l
} else {
// In this case l == zl.l, so we just tell Next to return zl.l.
zl.nextL = true
}
return l
}
func (zl *zlexer) Next() (lex, bool) { func (zl *zlexer) Next() (lex, bool) {
l := &zl.l l := &zl.l
if zl.nextL { switch {
case zl.cachedL != nil:
l, zl.cachedL = zl.cachedL, nil
return *l, true
case zl.nextL:
zl.nextL = false zl.nextL = false
return *l, true return *l, true
} case l.err:
if l.err {
// Parsing errors should be sticky. // Parsing errors should be sticky.
return lex{value: zEOF}, false return lex{value: zEOF}, false
} }
@ -767,14 +831,15 @@ func (zl *zlexer) Next() (lex, bool) {
escape bool escape bool
) )
if zl.com != "" { if zl.comBuf != "" {
comi = copy(com[:], zl.com) comi = copy(com[:], zl.comBuf)
zl.com = "" zl.comBuf = ""
} }
zl.comment = ""
for x, ok := zl.readByte(); ok; x, ok = zl.readByte() { for x, ok := zl.readByte(); ok; x, ok = zl.readByte() {
l.line, l.column = zl.line, zl.column l.line, l.column = zl.line, zl.column
l.comment = ""
if stri >= len(str) { if stri >= len(str) {
l.token = "token length insufficient for parsing" l.token = "token length insufficient for parsing"
@ -898,20 +963,25 @@ func (zl *zlexer) Next() (lex, bool) {
} }
zl.commt = true zl.commt = true
zl.com = "" zl.comBuf = ""
if comi > 1 { if comi > 1 {
// A newline was previously seen inside a comment that // A newline was previously seen inside a comment that
// was inside braces and we delayed adding it until now. // was inside braces and we delayed adding it until now.
com[comi] = ' ' // convert newline to space com[comi] = ' ' // convert newline to space
comi++ comi++
if comi >= len(com) {
l.token = "comment length insufficient for parsing"
l.err = true
return *l, true
}
} }
com[comi] = ';' com[comi] = ';'
comi++ comi++
if stri > 0 { if stri > 0 {
zl.com = string(com[:comi]) zl.comBuf = string(com[:comi])
l.value = zString l.value = zString
l.token = string(str[:stri]) l.token = string(str[:stri])
@ -947,11 +1017,11 @@ func (zl *zlexer) Next() (lex, bool) {
l.value = zNewline l.value = zNewline
l.token = "\n" l.token = "\n"
l.comment = string(com[:comi]) zl.comment = string(com[:comi])
return *l, true return *l, true
} }
zl.com = string(com[:comi]) zl.comBuf = string(com[:comi])
break break
} }
@ -977,9 +1047,9 @@ func (zl *zlexer) Next() (lex, bool) {
l.value = zNewline l.value = zNewline
l.token = "\n" l.token = "\n"
l.comment = zl.com
zl.com = "" zl.comment = zl.comBuf
zl.comBuf = ""
zl.rrtype = false zl.rrtype = false
zl.owner = true zl.owner = true
@ -1115,7 +1185,7 @@ func (zl *zlexer) Next() (lex, bool) {
// Send remainder of com // Send remainder of com
l.value = zNewline l.value = zNewline
l.token = "\n" l.token = "\n"
l.comment = string(com[:comi]) zl.comment = string(com[:comi])
if retL != (lex{}) { if retL != (lex{}) {
zl.nextL = true zl.nextL = true
@ -1126,7 +1196,6 @@ func (zl *zlexer) Next() (lex, bool) {
} }
if zl.brace != 0 { if zl.brace != 0 {
l.comment = "" // in case there was left over string and comment
l.token = "unbalanced brace" l.token = "unbalanced brace"
l.err = true l.err = true
return *l, true return *l, true
@ -1135,6 +1204,14 @@ func (zl *zlexer) Next() (lex, bool) {
return lex{value: zEOF}, false return lex{value: zEOF}, false
} }
func (zl *zlexer) Comment() string {
if zl.l.err {
return ""
}
return zl.comment
}
// Extract the class number from CLASSxx // Extract the class number from CLASSxx
func classToInt(token string) (uint16, bool) { func classToInt(token string) (uint16, bool) {
offset := 5 offset := 5
@ -1163,8 +1240,7 @@ func typeToInt(token string) (uint16, bool) {
// stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds. // stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds.
func stringToTTL(token string) (uint32, bool) { func stringToTTL(token string) (uint32, bool) {
s := uint32(0) var s, i uint32
i := uint32(0)
for _, c := range token { for _, c := range token {
switch c { switch c {
case 's', 'S': case 's', 'S':
@ -1252,7 +1328,7 @@ func toAbsoluteName(name, origin string) (absolute string, ok bool) {
} }
// check if name is already absolute // check if name is already absolute
if name[len(name)-1] == '.' { if IsFqdn(name) {
return name, true return name, true
} }
@ -1292,24 +1368,21 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) {
return longitude, false return longitude, false
} }
// "Eat" the rest of the "line". Return potential comments // "Eat" the rest of the "line"
func slurpRemainder(c *zlexer, f string) (*ParseError, string) { func slurpRemainder(c *zlexer) *ParseError {
l, _ := c.Next() l, _ := c.Next()
com := ""
switch l.value { switch l.value {
case zBlank: case zBlank:
l, _ = c.Next() l, _ = c.Next()
com = l.comment
if l.value != zNewline && l.value != zEOF { if l.value != zNewline && l.value != zEOF {
return &ParseError{f, "garbage after rdata", l}, "" return &ParseError{"", "garbage after rdata", l}
} }
case zNewline: case zNewline:
com = l.comment
case zEOF: case zEOF:
default: default:
return &ParseError{f, "garbage after rdata", l}, "" return &ParseError{"", "garbage after rdata", l}
} }
return nil, com return nil
} }
// Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64" // Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64"

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

File diff suppressed because it is too large Load Diff

View File

@ -36,33 +36,9 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
return nil return nil
} }
q = strings.ToLower(q)
var handler Handler 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) { for off, end := 0, false; !end; off, end = NextLabel(q, off) {
if h, ok := mux.z[q[off:]]; ok { if h, ok := mux.z[q[off:]]; ok {
if t != TypeDS { if t != TypeDS {

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

@ -3,7 +3,6 @@
package dns package dns
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
@ -12,26 +11,12 @@ import (
"net" "net"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
// Default maximum number of TCP queries before we close the socket. // Default maximum number of TCP queries before we close the socket.
const maxTCPQueries = 128 const maxTCPQueries = 128
// The maximum number of idle workers.
//
// This controls the maximum number of workers that are allowed to stay
// idle waiting for incoming requests before being torn down.
//
// If this limit is reached, the server will just keep spawning new
// workers (goroutines) for each incoming request. In this case, each
// worker will only be used for a single request.
const maxIdleWorkersCount = 10000
// The maximum length of time a worker may idle for before being destroyed.
const idleWorkerTimeout = 10 * time.Second
// aLongTimeAgo is a non-zero time, far in the past, used for // aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations. // immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0) var aLongTimeAgo = time.Unix(1, 0)
@ -81,7 +66,7 @@ type ConnectionStater interface {
} }
type response struct { type response struct {
msg []byte closed bool // connection has been closed
hijacked bool // connection has been hijacked by handler hijacked bool // connection has been hijacked by handler
tsigTimersOnly bool tsigTimersOnly bool
tsigStatus error tsigStatus error
@ -91,7 +76,6 @@ type response struct {
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
writer Writer // writer to output the raw DNS bits writer Writer // writer to output the raw DNS bits
wg *sync.WaitGroup // for gracefull shutdown
} }
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
@ -161,11 +145,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)
} }
@ -202,9 +186,6 @@ 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.
@ -216,11 +197,9 @@ type Server struct {
// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address. // 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. // It is only supported on go1.11+ and when using ListenAndServe.
ReusePort bool ReusePort bool
// AcceptMsgFunc will check the incoming message and will reject it early in the process.
// UDP packet or TCP connection queue // By default DefaultMsgAcceptFunc will be used.
queue chan *response MsgAcceptFunc MsgAcceptFunc
// Workers count
workersCount int32
// Shutdown handling // Shutdown handling
lock sync.RWMutex lock sync.RWMutex
@ -239,51 +218,6 @@ func (srv *Server) isStarted() bool {
return started return started
} }
func (srv *Server) worker(w *response) {
srv.serve(w)
for {
count := atomic.LoadInt32(&srv.workersCount)
if count > maxIdleWorkersCount {
return
}
if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) {
break
}
}
defer atomic.AddInt32(&srv.workersCount, -1)
inUse := false
timeout := time.NewTimer(idleWorkerTimeout)
defer timeout.Stop()
LOOP:
for {
select {
case w, ok := <-srv.queue:
if !ok {
break LOOP
}
inUse = true
srv.serve(w)
case <-timeout.C:
if !inUse {
break LOOP
}
inUse = false
timeout.Reset(idleWorkerTimeout)
}
}
}
func (srv *Server) spawnWorker(w *response) {
select {
case srv.queue <- w:
default:
go srv.worker(w)
}
}
func makeUDPBuffer(size int) func() interface{} { func makeUDPBuffer(size int) func() interface{} {
return func() interface{} { return func() interface{} {
return make([]byte, size) return make([]byte, size)
@ -291,14 +225,18 @@ func makeUDPBuffer(size int) func() interface{} {
} }
func (srv *Server) init() { func (srv *Server) init() {
srv.queue = make(chan *response)
srv.shutdown = make(chan struct{}) srv.shutdown = make(chan struct{})
srv.conns = make(map[net.Conn]struct{}) srv.conns = make(map[net.Conn]struct{})
if srv.UDPSize == 0 { if srv.UDPSize == 0 {
srv.UDPSize = MinMsgSize srv.UDPSize = MinMsgSize
} }
if srv.MsgAcceptFunc == nil {
srv.MsgAcceptFunc = DefaultMsgAcceptFunc
}
if srv.Handler == nil {
srv.Handler = DefaultServeMux
}
srv.udpPool.New = makeUDPBuffer(srv.UDPSize) srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
} }
@ -324,7 +262,6 @@ func (srv *Server) ListenAndServe() error {
} }
srv.init() srv.init()
defer close(srv.queue)
switch srv.Net { switch srv.Net {
case "tcp", "tcp4", "tcp6": case "tcp", "tcp4", "tcp6":
@ -379,7 +316,6 @@ func (srv *Server) ActivateAndServe() error {
} }
srv.init() srv.init()
defer close(srv.queue)
pConn := srv.PacketConn pConn := srv.PacketConn
l := srv.Listener l := srv.Listener
@ -459,11 +395,10 @@ 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 {
rtimeout = srv.ReadTimeout return srv.ReadTimeout
} }
return rtimeout return dnsTimeout
} }
// serveTCP starts a TCP listener for the server. // serveTCP starts a TCP listener for the server.
@ -496,11 +431,7 @@ func (srv *Server) serveTCP(l net.Listener) error {
srv.conns[rw] = struct{}{} srv.conns[rw] = struct{}{}
srv.lock.Unlock() srv.lock.Unlock()
wg.Add(1) wg.Add(1)
srv.spawnWorker(&response{ go srv.serveTCPConn(&wg, rw)
tsigSecret: srv.TsigSecret,
tcp: rw,
wg: &wg,
})
} }
return nil return nil
@ -514,7 +445,7 @@ 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)
} }
@ -545,46 +476,22 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
continue continue
} }
wg.Add(1) wg.Add(1)
srv.spawnWorker(&response{ go srv.serveUDPPacket(&wg, m, l, s)
msg: m,
tsigSecret: srv.TsigSecret,
udp: l,
udpSession: s,
wg: &wg,
})
} }
return nil return nil
} }
func (srv *Server) serve(w *response) { // Serve a new TCP connection.
func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
if srv.DecorateWriter != nil { if srv.DecorateWriter != nil {
w.writer = srv.DecorateWriter(w) w.writer = srv.DecorateWriter(w)
} else { } else {
w.writer = w w.writer = w
} }
if w.udp != nil { reader := Reader(defaultReader{srv})
// serve UDP
srv.serveDNS(w)
w.wg.Done()
return
}
defer func() {
if !w.hijacked {
w.Close()
}
srv.lock.Lock()
delete(srv.conns, w.tcp)
srv.lock.Unlock()
w.wg.Done()
}()
reader := Reader(&defaultReader{srv})
if srv.DecorateReader != nil { if srv.DecorateReader != nil {
reader = srv.DecorateReader(reader) reader = srv.DecorateReader(reader)
} }
@ -602,14 +509,13 @@ func (srv *Server) serve(w *response) {
} }
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ { for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
var err error m, err := reader.ReadTCP(w.tcp, timeout)
w.msg, err = reader.ReadTCP(w.tcp, timeout)
if err != nil { if err != nil {
// TODO(tmthrgd): handle error // TODO(tmthrgd): handle error
break break
} }
srv.serveDNS(w) srv.serveDNS(m, w)
if w.tcp == nil { if w.closed {
break // Close() was called break // Close() was called
} }
if w.hijacked { if w.hijacked {
@ -619,25 +525,67 @@ func (srv *Server) serve(w *response) {
// idle timeout. // idle timeout.
timeout = idleTimeout timeout = idleTimeout
} }
}
func (srv *Server) disposeBuffer(w *response) { if !w.hijacked {
if w.udp != nil && cap(w.msg) == srv.UDPSize { w.Close()
srv.udpPool.Put(w.msg[:srv.UDPSize])
} }
w.msg = nil
srv.lock.Lock()
delete(srv.conns, w.tcp)
srv.lock.Unlock()
wg.Done()
} }
func (srv *Server) serveDNS(w *response) { // 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)
err := req.Unpack(w.msg) req.setHdr(dh)
if err != nil { // Send a FormatError back
x := new(Msg) switch action := srv.MsgAcceptFunc(dh); action {
x.SetRcodeFormatError(req) case MsgAccept:
w.WriteMsg(x) if req.unpack(dh, m, off) == nil {
} break
if err != nil || !srv.Unsafe && req.Response { }
srv.disposeBuffer(w)
fallthrough
case MsgReject, MsgRejectNotImplemented:
opcode := req.Opcode
req.SetRcodeFormatError(req)
req.Zero = false
if action == MsgRejectNotImplemented {
req.Opcode = opcode
req.Rcode = RcodeNotImplemented
}
// Are we allowed to delete any OPT records here?
req.Ns, req.Answer, req.Extra = nil, nil, nil
w.WriteMsg(req)
fallthrough
case MsgIgnore:
if w.udp != nil && cap(m) == srv.UDPSize {
srv.udpPool.Put(m[:srv.UDPSize])
}
return return
} }
@ -645,7 +593,7 @@ func (srv *Server) serveDNS(w *response) {
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 { if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
w.tsigStatus = TsigVerify(w.msg, secret, "", false) w.tsigStatus = TsigVerify(m, secret, "", false)
} else { } else {
w.tsigStatus = ErrSecret w.tsigStatus = ErrSecret
} }
@ -654,14 +602,11 @@ func (srv *Server) serveDNS(w *response) {
} }
} }
srv.disposeBuffer(w) if w.udp != nil && cap(m) == srv.UDPSize {
srv.udpPool.Put(m[:srv.UDPSize])
handler := srv.Handler
if handler == nil {
handler = DefaultServeMux
} }
handler.ServeDNS(w, req) // Writes back to the client srv.Handler.ServeDNS(w, req) // Writes back to the client
} }
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
@ -675,36 +620,16 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
} }
srv.lock.RUnlock() srv.lock.RUnlock()
l := make([]byte, 2) var length uint16
n, err := conn.Read(l) if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
if err != nil || n != 2 { return nil, err
if err != nil {
return nil, err
}
return nil, ErrShortRead
} }
length := binary.BigEndian.Uint16(l)
if length == 0 { m := make([]byte, length)
return nil, ErrShortRead if _, err := io.ReadFull(conn, m); err != nil {
return nil, err
} }
m := make([]byte, int(length))
n, err = conn.Read(m[:int(length)])
if err != nil || n == 0 {
if err != nil {
return nil, err
}
return nil, ErrShortRead
}
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
} }
@ -728,6 +653,10 @@ 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 {
@ -749,26 +678,25 @@ 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:
n, err := WriteToSessionUDP(w.udp, m, w.udpSession) return WriteToSessionUDP(w.udp, m, w.udpSession)
return n, err
case w.tcp != nil: case w.tcp != nil:
lm := len(m) if len(m) > MaxMsgSize {
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...)
n, err := io.Copy(w.tcp, bytes.NewReader(m)) l := make([]byte, 2)
binary.BigEndian.PutUint16(l, uint16(len(m)))
n, err := (&net.Buffers{l, m}).WriteTo(w.tcp)
return int(n), err return int(n), err
default: default:
panic("dns: Write called after Close") panic("dns: internal error: udp and tcp both nil")
} }
} }
@ -780,7 +708,7 @@ func (w *response) LocalAddr() net.Addr {
case w.tcp != nil: case w.tcp != nil:
return w.tcp.LocalAddr() return w.tcp.LocalAddr()
default: default:
panic("dns: LocalAddr called after Close") panic("dns: internal error: udp and tcp both nil")
} }
} }
@ -792,7 +720,7 @@ func (w *response) RemoteAddr() net.Addr {
case w.tcp != nil: case w.tcp != nil:
return w.tcp.RemoteAddr() return w.tcp.RemoteAddr()
default: default:
panic("dns: RemoteAddr called after Close") panic("dns: internal error: udpSession and tcp both nil")
} }
} }
@ -807,13 +735,20 @@ 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 {
// Can't close the udp conn, as that is actually the listener. if w.closed {
if w.tcp != nil { return &Error{err: "connection already closed"}
e := w.tcp.Close() }
w.tcp = nil w.closed = true
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")
} }
return nil
} }
// ConnectionState() implements the ConnectionStater.ConnectionState() interface. // ConnectionState() implements the ConnectionStater.ConnectionState() interface.

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

@ -21,15 +21,11 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 { 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
buf := make([]byte, m.Len()+rr.len()) rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0}
rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0
buf := make([]byte, m.Len()+Len(rr))
mbuf, err := m.PackBuffer(buf) mbuf, err := m.PackBuffer(buf)
if err != nil { if err != nil {
return nil, err return nil, err
@ -107,7 +103,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 := 12 offset := headerSize
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)
@ -167,7 +163,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.ToLower(signername) != strings.ToLower(k.Header().Name) { if !strings.EqualFold(signername, 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
@ -185,10 +181,8 @@ 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 := big.NewInt(0) r := new(big.Int).SetBytes(sig[:len(sig)/2])
r.SetBytes(sig[:len(sig)/2]) s := new(big.Int).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
@ -202,10 +196,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
} }
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256, ECDSAP384SHA384:
pk := k.publicKeyECDSA() pk := k.publicKeyECDSA()
r := big.NewInt(0) r := new(big.Int).SetBytes(sig[:len(sig)/2])
r.SetBytes(sig[:len(sig)/2]) s := new(big.Int).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,6 +23,8 @@ 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
@ -49,9 +51,11 @@ func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v
c.val, c.rtt, c.err = fn() c.val, c.rtt, c.err = fn()
c.wg.Done() c.wg.Done()
g.Lock() if !g.dontDeleteForTesting {
delete(g.m, key) g.Lock()
g.Unlock() delete(g.m, key)
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,10 +14,7 @@ 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)
if err != nil { return err
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,10 +14,7 @@ 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)
if err != nil { return err
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,6 +54,10 @@ func (rr *TSIG) String() string {
return s return s
} }
func (rr *TSIG) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on TSIG")
}
// The following values must be put in wireformat, so that the MAC can be calculated. // 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 {
@ -113,13 +117,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, []byte(rawsecret)) h = hmac.New(md5.New, rawsecret)
case HmacSHA1: case HmacSHA1:
h = hmac.New(sha1.New, []byte(rawsecret)) h = hmac.New(sha1.New, rawsecret)
case HmacSHA256: case HmacSHA256:
h = hmac.New(sha256.New, []byte(rawsecret)) h = hmac.New(sha256.New, rawsecret)
case HmacSHA512: case HmacSHA512:
h = hmac.New(sha512.New, []byte(rawsecret)) h = hmac.New(sha512.New, rawsecret)
default: default:
return nil, "", ErrKeyAlg return nil, "", ErrKeyAlg
} }
@ -133,13 +137,12 @@ 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, t.len()) tbuf := make([]byte, Len(t))
if off, err := PackRR(t, tbuf, 0, nil, false); err == nil { off, err := PackRR(t, tbuf, 0, nil, false)
tbuf = tbuf[:off] // reset to actual size used if err != nil {
} else {
return nil, "", err return nil, "", err
} }
mbuf = append(mbuf, tbuf...) mbuf = append(mbuf, tbuf[:off]...)
// 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))

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

@ -205,9 +205,6 @@ 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
@ -218,8 +215,10 @@ type Question struct {
Qclass uint16 Qclass uint16
} }
func (q *Question) len() int { func (q *Question) len(off int, compression map[string]struct{}) int {
return len(q.Name) + 1 + 2 + 2 l := domainNameLen(q.Name, off, compression, true)
l += 2 + 2
return l
} }
func (q *Question) String() (s string) { func (q *Question) String() (s string) {
@ -239,6 +238,25 @@ 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 string) *ParseError {
panic("dns: internal error: parse should never be called on ANY")
}
// NULL RR. See RFC 1035.
type NULL struct {
Hdr RR_Header
Data string `dns:"any"`
}
func (rr *NULL) String() string {
// There is no presentation format; prefix string with a comment.
return ";" + rr.Hdr.String() + rr.Data
}
func (rr *NULL) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on NULL")
}
// CNAME RR. See RFC 1034. // CNAME RR. See RFC 1034.
type CNAME struct { type CNAME struct {
Hdr RR_Header Hdr RR_Header
@ -351,7 +369,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:"cdomain-name"` Host string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
} }
func (rr *RT) String() string { func (rr *RT) String() string {
@ -386,7 +404,7 @@ type RP struct {
} }
func (rr *RP) String() string { func (rr *RP) String() string {
return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt}) return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
} }
// SOA RR. See RFC 1035. // SOA RR. See RFC 1035.
@ -420,25 +438,54 @@ 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 var dst strings.Builder
dst.Grow(len(s))
for i := 0; i < len(s); { for i := 0; i < len(s); {
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
dst.WriteString(s[i : i+2]) if dst.Len() != 0 {
dst.WriteString(s[i : i+2])
}
i += 2 i += 2
continue continue
} }
b, n := nextByte(s, i) b, n := nextByte(s, i)
switch { if n == 0 {
case n == 0: i++
i++ // dangling back slash continue
case b == '.': }
dst.WriteByte('.') if b == '.' {
if dst.Len() != 0 {
dst.WriteByte('.')
}
i += n
continue
}
switch b {
case ' ', '\'', '@', ';', '(', ')', '"', '\\': // additional chars to escape
if dst.Len() == 0 {
dst.Grow(len(s) * 2)
dst.WriteString(s[:i])
}
dst.WriteByte('\\')
dst.WriteByte(b)
default: default:
writeDomainNameByte(&dst, b) if ' ' <= b && b <= '~' {
if dst.Len() != 0 {
dst.WriteByte(b)
}
} else {
if dst.Len() == 0 {
dst.Grow(len(s) * 2)
dst.WriteString(s[:i])
}
dst.WriteString(escapeByte(b))
}
} }
i += n i += n
} }
if dst.Len() == 0 {
return s
}
return dst.String() return dst.String()
} }
@ -460,7 +507,7 @@ func sprintTxtOctet(s string) string {
case b == '.': case b == '.':
dst.WriteByte('.') dst.WriteByte('.')
case b < ' ' || b > '~': case b < ' ' || b > '~':
writeEscapedByte(&dst, b) dst.WriteString(escapeByte(b))
default: default:
dst.WriteByte(b) dst.WriteByte(b)
} }
@ -492,36 +539,50 @@ func sprintTxt(txt []string) string {
return out.String() return out.String()
} }
func writeDomainNameByte(s *strings.Builder, b byte) {
switch b {
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
s.WriteByte('\\')
s.WriteByte(b)
default:
writeTXTStringByte(s, b)
}
}
func writeTXTStringByte(s *strings.Builder, b byte) { func writeTXTStringByte(s *strings.Builder, b byte) {
switch { switch {
case b == '"' || b == '\\': case b == '"' || b == '\\':
s.WriteByte('\\') s.WriteByte('\\')
s.WriteByte(b) s.WriteByte(b)
case b < ' ' || b > '~': case b < ' ' || b > '~':
writeEscapedByte(s, b) s.WriteString(escapeByte(b))
default: default:
s.WriteByte(b) s.WriteByte(b)
} }
} }
func writeEscapedByte(s *strings.Builder, b byte) { const (
var buf [3]byte escapedByteSmall = "" +
bufs := strconv.AppendInt(buf[:0], int64(b), 10) `\000\001\002\003\004\005\006\007\008\009` +
s.WriteByte('\\') `\010\011\012\013\014\015\016\017\018\019` +
for i := len(bufs); i < 3; i++ { `\020\021\022\023\024\025\026\027\028\029` +
s.WriteByte('0') `\030\031`
escapedByteLarge = `\127\128\129` +
`\130\131\132\133\134\135\136\137\138\139` +
`\140\141\142\143\144\145\146\147\148\149` +
`\150\151\152\153\154\155\156\157\158\159` +
`\160\161\162\163\164\165\166\167\168\169` +
`\170\171\172\173\174\175\176\177\178\179` +
`\180\181\182\183\184\185\186\187\188\189` +
`\190\191\192\193\194\195\196\197\198\199` +
`\200\201\202\203\204\205\206\207\208\209` +
`\210\211\212\213\214\215\216\217\218\219` +
`\220\221\222\223\224\225\226\227\228\229` +
`\230\231\232\233\234\235\236\237\238\239` +
`\240\241\242\243\244\245\246\247\248\249` +
`\250\251\252\253\254\255`
)
// escapeByte returns the \DDD escaping of b which must
// satisfy b < ' ' || b > '~'.
func escapeByte(b byte) string {
if b < ' ' {
return escapedByteSmall[b*4 : b*4+4]
} }
s.Write(bufs)
b -= '~' + 1
// The cast here is needed as b*4 may overflow byte.
return escapedByteLarge[int(b)*4 : int(b)*4+4]
} }
func nextByte(s string, offset int) (byte, int) { func nextByte(s string, offset int) (byte, int) {
@ -803,22 +864,16 @@ 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 i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
func (rr *NSEC) len() int { func (rr *NSEC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() + len(rr.NextDomain) + 1 l := rr.Hdr.len(off, compression)
lastwindow := uint32(2 ^ 32 + 1) l += domainNameLen(rr.NextDomain, off+l, compression, false)
for _, t := range rr.TypeBitMap { l += typeBitMapLen(rr.TypeBitMap)
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }
@ -968,22 +1023,16 @@ 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 i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
func (rr *NSEC3) len() int { func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1 l := rr.Hdr.len(off, compression)
lastwindow := uint32(2 ^ 32 + 1) l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
for _, t := range rr.TypeBitMap { l += typeBitMapLen(rr.TypeBitMap)
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }
@ -1022,10 +1071,16 @@ 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 := "\n;; TKEY PSEUDOSECTION:\n" s := ";" + rr.Hdr.String() +
s += rr.Hdr.String() + " " + rr.Algorithm + " " + " " + rr.Algorithm +
strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " + " " + TimeToString(rr.Inception) +
strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData " " + TimeToString(rr.Expiration) +
" " + strconv.Itoa(int(rr.Mode)) +
" " + strconv.Itoa(int(rr.Error)) +
" " + strconv.Itoa(int(rr.KeySize)) +
" " + rr.Key +
" " + strconv.Itoa(int(rr.OtherLen)) +
" " + rr.OtherData
return s return s
} }
@ -1285,22 +1340,16 @@ 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 i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
func (rr *CSYNC) len() int { func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() + 4 + 2 l := rr.Hdr.len(off, compression)
lastwindow := uint32(2 ^ 32 + 1) l += 4 + 2
for _, t := range rr.TypeBitMap { l += typeBitMapLen(rr.TypeBitMap)
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }

View File

@ -153,8 +153,8 @@ func main() {
if isEmbedded { if isEmbedded {
continue continue
} }
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name) fmt.Fprintf(b, "func (rr *%s) len(off int, compression map[string]struct{}) int {\n", name)
fmt.Fprintf(b, "l := rr.Hdr.len()\n") fmt.Fprintf(b, "l := rr.Hdr.len(off, compression)\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,7 +162,11 @@ func main() {
switch st.Tag(i) { switch st.Tag(i) {
case `dns:"-"`: case `dns:"-"`:
// ignored // ignored
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`: case `dns:"cdomain-name"`:
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))
@ -173,8 +177,10 @@ func main() {
switch { switch {
case st.Tag(i) == `dns:"-"`: case st.Tag(i) == `dns:"-"`:
// ignored // ignored
case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`: case st.Tag(i) == `dns:"cdomain-name"`:
o("l += len(rr.%s) + 1\n") o("l += domainNameLen(rr.%s, off+l, compression, true)\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`):
@ -183,14 +189,14 @@ func main() {
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 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") o("l += len(rr.%s)/2\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
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\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("l += net.IPv4len // %s\n") o("if len(rr.%s) != 0 { l += net.IPv4len }\n")
case st.Tag(i) == `dns:"aaaa"`: case st.Tag(i) == `dns:"aaaa"`:
o("l += net.IPv6len // %s\n") o("if len(rr.%s) != 0 { l += net.IPv6len }\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"`:
@ -236,6 +242,13 @@ 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)

View File

@ -20,15 +20,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
if err != nil { if err != nil {
return n, nil, err return n, nil, err
} }
session := &SessionUDP{raddr.(*net.UDPAddr)} return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
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. // 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) {
n, err := conn.WriteTo(b, session.raddr) return conn.WriteTo(b, session.raddr)
return n, err
} }
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods // TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods

View File

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

View File

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

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

@ -35,30 +35,36 @@ 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)
go func() { switch q.Question[0].Qtype {
if q.Question[0].Qtype == TypeAXFR { case TypeAXFR:
go t.inAxfr(q, env) go t.inAxfr(q, env)
return case TypeIXFR:
} go t.inIxfr(q, env)
if q.Question[0].Qtype == TypeIXFR { }
go t.inIxfr(q, env)
return
}
}()
return env, nil return env, nil
} }
@ -111,7 +117,7 @@ func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
} }
func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) { func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
serial := uint32(0) // The first serial seen is the current server serial var serial uint32 // The first serial seen is the current server serial
axfr := true axfr := true
n := 0 n := 0
qser := q.Ns[0].(*SOA).Serial qser := q.Ns[0].(*SOA).Serial
@ -192,11 +198,14 @@ func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
r.Authoritative = true r.Authoritative = true
// assume it fits TODO(miek): fix // assume it fits TODO(miek): fix
r.Answer = append(r.Answer, x.RR...) r.Answer = append(r.Answer, x.RR...)
if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
}
if err := w.WriteMsg(r); err != nil { if err := w.WriteMsg(r); err != nil {
return err return err
} }
w.TsigTimersOnly(true)
} }
w.TsigTimersOnly(true)
return nil return nil
} }
@ -237,24 +246,18 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
if err != nil { if err != nil {
return err return err
} }
if _, err = t.Write(out); err != nil { _, err = t.Write(out)
return err return err
}
return nil
} }
func isSOAFirst(in *Msg) bool { func isSOAFirst(in *Msg) bool {
if len(in.Answer) > 0 { return len(in.Answer) > 0 &&
return in.Answer[0].Header().Rrtype == TypeSOA in.Answer[0].Header().Rrtype == TypeSOA
}
return false
} }
func isSOALast(in *Msg) bool { func isSOALast(in *Msg) bool {
if len(in.Answer) > 0 { return len(in.Answer) > 0 &&
return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
}
return false
} }
const errXFR = "bad xfr rcode: %d" const errXFR = "bad xfr rcode: %d"

View File

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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

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

@ -54,6 +54,7 @@ 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) },
@ -209,6 +210,7 @@ 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 }
@ -236,144 +238,150 @@ 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() int { func (rr *A) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += net.IPv4len // A if len(rr.A) != 0 {
l += net.IPv4len
}
return l return l
} }
func (rr *AAAA) len() int { func (rr *AAAA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += net.IPv6len // AAAA if len(rr.AAAA) != 0 {
l += net.IPv6len
}
return l return l
} }
func (rr *AFSDB) len() int { func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Subtype l += 2 // Subtype
l += len(rr.Hostname) + 1 l += domainNameLen(rr.Hostname, off+l, compression, false)
return l return l
} }
func (rr *ANY) len() int { func (rr *ANY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
return l return l
} }
func (rr *AVC) len() int { func (rr *AVC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *CAA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *CERT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *CNAME) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Target) + 1 l += domainNameLen(rr.Target, off+l, compression, true)
return l return l
} }
func (rr *DHCID) len() int { func (rr *DHCID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += base64.StdEncoding.DecodedLen(len(rr.Digest)) l += base64.StdEncoding.DecodedLen(len(rr.Digest))
return l return l
} }
func (rr *DNAME) len() int { func (rr *DNAME) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Target) + 1 l += domainNameLen(rr.Target, off+l, compression, false)
return l return l
} }
func (rr *DNSKEY) len() int { func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *DS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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
return l return l
} }
func (rr *EID) len() int { func (rr *EID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Endpoint)/2 + 1 l += len(rr.Endpoint) / 2
return l return l
} }
func (rr *EUI48) len() int { func (rr *EUI48) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 6 // Address l += 6 // Address
return l return l
} }
func (rr *EUI64) len() int { func (rr *EUI64) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 8 // Address l += 8 // Address
return l return l
} }
func (rr *GID) len() int { func (rr *GID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 4 // Gid l += 4 // Gid
return l return l
} }
func (rr *GPOS) len() int { func (rr *GPOS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *HINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *HIP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // HitLength l++ // HitLength
l++ // PublicKeyAlgorithm l++ // PublicKeyAlgorithm
l += 2 // PublicKeyLength l += 2 // PublicKeyLength
l += len(rr.Hit) / 2 l += len(rr.Hit) / 2
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 += len(x) + 1 l += domainNameLen(x, off+l, compression, false)
} }
return l return l
} }
func (rr *KX) len() int { func (rr *KX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += len(rr.Exchanger) + 1 l += domainNameLen(rr.Exchanger, off+l, compression, false)
return l return l
} }
func (rr *L32) len() int { func (rr *L32) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += net.IPv4len // Locator32 if len(rr.Locator32) != 0 {
l += net.IPv4len
}
return l return l
} }
func (rr *L64) len() int { func (rr *L64) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += 8 // Locator64 l += 8 // Locator64
return l return l
} }
func (rr *LOC) len() int { func (rr *LOC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // Version l++ // Version
l++ // Size l++ // Size
l++ // HorizPre l++ // HorizPre
@ -383,89 +391,89 @@ func (rr *LOC) len() int {
l += 4 // Altitude l += 4 // Altitude
return l return l
} }
func (rr *LP) len() int { func (rr *LP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += len(rr.Fqdn) + 1 l += domainNameLen(rr.Fqdn, off+l, compression, false)
return l return l
} }
func (rr *MB) len() int { func (rr *MB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Mb) + 1 l += domainNameLen(rr.Mb, off+l, compression, true)
return l return l
} }
func (rr *MD) len() int { func (rr *MD) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Md) + 1 l += domainNameLen(rr.Md, off+l, compression, true)
return l return l
} }
func (rr *MF) len() int { func (rr *MF) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Mf) + 1 l += domainNameLen(rr.Mf, off+l, compression, true)
return l return l
} }
func (rr *MG) len() int { func (rr *MG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Mg) + 1 l += domainNameLen(rr.Mg, off+l, compression, true)
return l return l
} }
func (rr *MINFO) len() int { func (rr *MINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Rmail) + 1 l += domainNameLen(rr.Rmail, off+l, compression, true)
l += len(rr.Email) + 1 l += domainNameLen(rr.Email, off+l, compression, true)
return l return l
} }
func (rr *MR) len() int { func (rr *MR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Mr) + 1 l += domainNameLen(rr.Mr, off+l, compression, true)
return l return l
} }
func (rr *MX) len() int { func (rr *MX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += len(rr.Mx) + 1 l += domainNameLen(rr.Mx, off+l, compression, true)
return l return l
} }
func (rr *NAPTR) len() int { func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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 += len(rr.Replacement) + 1 l += domainNameLen(rr.Replacement, off+l, compression, false)
return l return l
} }
func (rr *NID) len() int { func (rr *NID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += 8 // NodeID l += 8 // NodeID
return l return l
} }
func (rr *NIMLOC) len() int { func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Locator)/2 + 1 l += len(rr.Locator) / 2
return l return l
} }
func (rr *NINFO) len() int { func (rr *NINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *NS) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Ns) + 1 l += domainNameLen(rr.Ns, off+l, compression, true)
return l return l
} }
func (rr *NSAPPTR) len() int { func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Ptr) + 1 l += domainNameLen(rr.Ptr, off+l, compression, false)
return l return l
} }
func (rr *NSEC3PARAM) len() int { func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // Hash l++ // Hash
l++ // Flags l++ // Flags
l += 2 // Iterations l += 2 // Iterations
@ -473,44 +481,49 @@ func (rr *NSEC3PARAM) len() int {
l += len(rr.Salt) / 2 l += len(rr.Salt) / 2
return l return l
} }
func (rr *OPENPGPKEY) len() int { func (rr *NULL) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Data)
return l
}
func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
return l return l
} }
func (rr *PTR) len() int { func (rr *PTR) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Ptr) + 1 l += domainNameLen(rr.Ptr, off+l, compression, true)
return l return l
} }
func (rr *PX) len() int { func (rr *PX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += len(rr.Map822) + 1 l += domainNameLen(rr.Map822, off+l, compression, false)
l += len(rr.Mapx400) + 1 l += domainNameLen(rr.Mapx400, off+l, compression, false)
return l return l
} }
func (rr *RFC3597) len() int { func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Rdata)/2 + 1 l += len(rr.Rdata) / 2
return l return l
} }
func (rr *RKEY) len() int { func (rr *RKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *RP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Mbox) + 1 l += domainNameLen(rr.Mbox, off+l, compression, false)
l += len(rr.Txt) + 1 l += domainNameLen(rr.Txt, off+l, compression, false)
return l return l
} }
func (rr *RRSIG) len() int { func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // TypeCovered l += 2 // TypeCovered
l++ // Algorithm l++ // Algorithm
l++ // Labels l++ // Labels
@ -518,28 +531,28 @@ func (rr *RRSIG) len() int {
l += 4 // Expiration l += 4 // Expiration
l += 4 // Inception l += 4 // Inception
l += 2 // KeyTag l += 2 // KeyTag
l += len(rr.SignerName) + 1 l += domainNameLen(rr.SignerName, off+l, compression, false)
l += base64.StdEncoding.DecodedLen(len(rr.Signature)) l += base64.StdEncoding.DecodedLen(len(rr.Signature))
return l return l
} }
func (rr *RT) len() int { func (rr *RT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += len(rr.Host) + 1 l += domainNameLen(rr.Host, off+l, compression, false)
return l return l
} }
func (rr *SMIMEA) len() int { func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate) / 2
return l return l
} }
func (rr *SOA) len() int { func (rr *SOA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Ns) + 1 l += domainNameLen(rr.Ns, off+l, compression, true)
l += len(rr.Mbox) + 1 l += domainNameLen(rr.Mbox, off+l, compression, true)
l += 4 // Serial l += 4 // Serial
l += 4 // Refresh l += 4 // Refresh
l += 4 // Retry l += 4 // Retry
@ -547,45 +560,45 @@ func (rr *SOA) len() int {
l += 4 // Minttl l += 4 // Minttl
return l return l
} }
func (rr *SPF) len() int { func (rr *SPF) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *SRV) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 2 // Priority l += 2 // Priority
l += 2 // Weight l += 2 // Weight
l += 2 // Port l += 2 // Port
l += len(rr.Target) + 1 l += domainNameLen(rr.Target, off+l, compression, false)
return l return l
} }
func (rr *SSHFP) len() int { func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // Algorithm l++ // Algorithm
l++ // Type l++ // Type
l += len(rr.FingerPrint)/2 + 1 l += len(rr.FingerPrint) / 2
return l return l
} }
func (rr *TA) len() int { func (rr *TA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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
return l return l
} }
func (rr *TALINK) len() int { func (rr *TALINK) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.PreviousName) + 1 l += domainNameLen(rr.PreviousName, off+l, compression, false)
l += len(rr.NextName) + 1 l += domainNameLen(rr.NextName, off+l, compression, false)
return l return l
} }
func (rr *TKEY) len() int { func (rr *TKEY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Algorithm) + 1 l += domainNameLen(rr.Algorithm, off+l, compression, false)
l += 4 // Inception l += 4 // Inception
l += 4 // Expiration l += 4 // Expiration
l += 2 // Mode l += 2 // Mode
@ -596,17 +609,17 @@ func (rr *TKEY) len() int {
l += len(rr.OtherData) / 2 l += len(rr.OtherData) / 2
return l return l
} }
func (rr *TLSA) len() int { func (rr *TLSA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate) / 2
return l return l
} }
func (rr *TSIG) len() int { func (rr *TSIG) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Algorithm) + 1 l += domainNameLen(rr.Algorithm, off+l, compression, false)
l += 6 // TimeSigned l += 6 // TimeSigned
l += 2 // Fudge l += 2 // Fudge
l += 2 // MACSize l += 2 // MACSize
@ -617,32 +630,32 @@ func (rr *TSIG) len() int {
l += len(rr.OtherData) / 2 l += len(rr.OtherData) / 2
return l return l
} }
func (rr *TXT) len() int { func (rr *TXT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *UID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += 4 // Uid l += 4 // Uid
return l return l
} }
func (rr *UINFO) len() int { func (rr *UINFO) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.Uinfo) + 1 l += len(rr.Uinfo) + 1
return l return l
} }
func (rr *URI) len() int { func (rr *URI) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
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() int { func (rr *X25) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len() l := rr.Hdr.len(off, compression)
l += len(rr.PSDNAddress) + 1 l += len(rr.PSDNAddress) + 1
return l return l
} }
@ -783,12 +796,17 @@ func (rr *NSEC3) copy() RR {
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, 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, rr.PublicKey}
} }
func (rr *OPT) copy() RR { func (rr *OPT) copy() RR {
Option := make([]EDNS0, len(rr.Option)) Option := make([]EDNS0, len(rr.Option))
copy(Option, rr.Option) for i, e := range rr.Option {
Option[i] = e.copy()
}
return &OPT{rr.Hdr, Option} return &OPT{rr.Hdr, Option}
} }
func (rr *PTR) copy() RR { func (rr *PTR) copy() RR {

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !ppc64le,!arm64,!s390x arm64,!go1.11 gccgo appengine // +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo appengine
package chacha20 package chacha20

View File

@ -6,7 +6,9 @@
package chacha20 package chacha20
import "encoding/binary" import (
"encoding/binary"
)
const ( const (
bufSize = 256 bufSize = 256
@ -14,14 +16,15 @@ const (
) )
//go:noescape //go:noescape
func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[8]uint32, counter *uint32) func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
// This implementation can handle buffers that aren't multiples of
// 256.
if len(src) >= bufSize { if len(src) >= bufSize {
chaCha20_ctr32_vmx(&dst[0], &src[0], len(src)-len(src)%bufSize, &c.key, &c.counter) chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
} } else if len(src)%bufSize != 0 {
if len(src)%bufSize != 0 { chaCha20_ctr32_vsx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter)
chaCha20_ctr32_vmx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter)
start := len(src) - len(src)%bufSize start := len(src) - len(src)%bufSize
ts, td, tb := src[start:], dst[start:], c.buf[:] ts, td, tb := src[start:], dst[start:], c.buf[:]
// Unroll loop to XOR 32 bytes per iteration. // Unroll loop to XOR 32 bytes per iteration.
@ -46,7 +49,6 @@ func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
td[i] = tb[i] ^ v td[i] = tb[i] ^ v
} }
c.len = bufSize - (len(src) % bufSize) c.len = bufSize - (len(src) % bufSize)
} }
} }

View File

@ -58,6 +58,14 @@ var serverForbiddenKexAlgos = map[string]struct{}{
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
} }
// preferredKexAlgos specifies the default preference for key-exchange algorithms
// in preference order.
var preferredKexAlgos = []string{
kexAlgoCurve25519SHA256,
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
kexAlgoDH14SHA1,
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order. // of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{ var supportedHostKeyAlgos = []string{
@ -246,7 +254,7 @@ func (c *Config) SetDefaults() {
c.Ciphers = ciphers c.Ciphers = ciphers
if c.KeyExchanges == nil { if c.KeyExchanges == nil {
c.KeyExchanges = supportedKexAlgos c.KeyExchanges = preferredKexAlgos
} }
if c.MACs == nil { if c.MACs == nil {

View File

@ -150,7 +150,7 @@ func appendIndexed(dst []byte, i uint64) []byte {
// extended buffer. // extended buffer.
// //
// If f.Sensitive is true, "Never Indexed" representation is used. If // If f.Sensitive is true, "Never Indexed" representation is used. If
// f.Sensitive is false and indexing is true, "Inremental Indexing" // f.Sensitive is false and indexing is true, "Incremental Indexing"
// representation is used. // representation is used.
func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) dst = append(dst, encodeTypeByte(indexing, f.Sensitive))

View File

@ -52,10 +52,11 @@ import (
) )
const ( const (
prefaceTimeout = 10 * time.Second prefaceTimeout = 10 * time.Second
firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
handlerChunkWriteSize = 4 << 10 handlerChunkWriteSize = 4 << 10
defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
maxQueuedControlFrames = 10000
) )
var ( var (
@ -163,6 +164,15 @@ func (s *Server) maxConcurrentStreams() uint32 {
return defaultMaxStreams return defaultMaxStreams
} }
// maxQueuedControlFrames is the maximum number of control frames like
// SETTINGS, PING and RST_STREAM that will be queued for writing before
// the connection is closed to prevent memory exhaustion attacks.
func (s *Server) maxQueuedControlFrames() int {
// TODO: if anybody asks, add a Server field, and remember to define the
// behavior of negative values.
return maxQueuedControlFrames
}
type serverInternalState struct { type serverInternalState struct {
mu sync.Mutex mu sync.Mutex
activeConns map[*serverConn]struct{} activeConns map[*serverConn]struct{}
@ -312,7 +322,7 @@ type ServeConnOpts struct {
} }
func (o *ServeConnOpts) context() context.Context { func (o *ServeConnOpts) context() context.Context {
if o.Context != nil { if o != nil && o.Context != nil {
return o.Context return o.Context
} }
return context.Background() return context.Background()
@ -506,6 +516,7 @@ type serverConn struct {
sawFirstSettings bool // got the initial SETTINGS frame after the preface sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs? unackedSettings int // how many SETTINGS have we sent without ACKs?
queuedControlFrames int // control frames in the writeSched queue
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
curClientStreams uint32 // number of open streams initiated by the client curClientStreams uint32 // number of open streams initiated by the client
@ -894,6 +905,14 @@ func (sc *serverConn) serve() {
} }
} }
// If the peer is causing us to generate a lot of control frames,
// but not reading them from us, assume they are trying to make us
// run out of memory.
if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() {
sc.vlogf("http2: too many control frames in send queue, closing connection")
return
}
// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
// with no error code (graceful shutdown), don't start the timer until // with no error code (graceful shutdown), don't start the timer until
// all open streams have been completed. // all open streams have been completed.
@ -1093,6 +1112,14 @@ func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
} }
if !ignoreWrite { if !ignoreWrite {
if wr.isControl() {
sc.queuedControlFrames++
// For extra safety, detect wraparounds, which should not happen,
// and pull the plug.
if sc.queuedControlFrames < 0 {
sc.conn.Close()
}
}
sc.writeSched.Push(wr) sc.writeSched.Push(wr)
} }
sc.scheduleFrameWrite() sc.scheduleFrameWrite()
@ -1210,10 +1237,8 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
// If a frame is already being written, nothing happens. This will be called again // If a frame is already being written, nothing happens. This will be called again
// when the frame is done being written. // when the frame is done being written.
// //
// If a frame isn't being written we need to send one, the best frame // If a frame isn't being written and we need to send one, the best frame
// to send is selected, preferring first things that aren't // to send is selected by writeSched.
// stream-specific (e.g. ACKing settings), and then finding the
// highest priority stream.
// //
// If a frame isn't being written and there's nothing else to send, we // If a frame isn't being written and there's nothing else to send, we
// flush the write buffer. // flush the write buffer.
@ -1241,6 +1266,9 @@ func (sc *serverConn) scheduleFrameWrite() {
} }
if !sc.inGoAway || sc.goAwayCode == ErrCodeNo { if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
if wr, ok := sc.writeSched.Pop(); ok { if wr, ok := sc.writeSched.Pop(); ok {
if wr.isControl() {
sc.queuedControlFrames--
}
sc.startFrameWrite(wr) sc.startFrameWrite(wr)
continue continue
} }
@ -1533,6 +1561,8 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
if err := f.ForeachSetting(sc.processSetting); err != nil { if err := f.ForeachSetting(sc.processSetting); err != nil {
return err return err
} }
// TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be
// acknowledged individually, even if multiple are received before the ACK.
sc.needToSendSettingsAck = true sc.needToSendSettingsAck = true
sc.scheduleFrameWrite() sc.scheduleFrameWrite()
return nil return nil
@ -2494,7 +2524,7 @@ const TrailerPrefix = "Trailer:"
// trailers. That worked for a while, until we found the first major // trailers. That worked for a while, until we found the first major
// user of Trailers in the wild: gRPC (using them only over http2), // user of Trailers in the wild: gRPC (using them only over http2),
// and gRPC libraries permit setting trailers mid-stream without // and gRPC libraries permit setting trailers mid-stream without
// predeclarnig them. So: change of plans. We still permit the old // predeclaring them. So: change of plans. We still permit the old
// way, but we also permit this hack: if a Header() key begins with // way, but we also permit this hack: if a Header() key begins with
// "Trailer:", the suffix of that key is a Trailer. Because ':' is an // "Trailer:", the suffix of that key is a Trailer. Because ':' is an
// invalid token byte anyway, there is no ambiguity. (And it's already // invalid token byte anyway, there is no ambiguity. (And it's already
@ -2794,7 +2824,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
// PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
// is in either the "open" or "half-closed (remote)" state. // is in either the "open" or "half-closed (remote)" state.
if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote {
// responseWriter.Push checks that the stream is peer-initiaed. // responseWriter.Push checks that the stream is peer-initiated.
msg.done <- errStreamClosed msg.done <- errStreamClosed
return return
} }

View File

@ -992,7 +992,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
req.Method != "HEAD" { req.Method != "HEAD" {
// Request gzip only, not deflate. Deflate is ambiguous and // Request gzip only, not deflate. Deflate is ambiguous and
// not as universally supported anyway. // not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38 // See: https://zlib.net/zlib_faq.html#faq39
// //
// Note that we don't request this for HEAD requests, // Note that we don't request this for HEAD requests,
// due to a bug in nginx: // due to a bug in nginx:
@ -1216,6 +1216,8 @@ var (
// abort request body write, but send stream reset of cancel. // abort request body write, but send stream reset of cancel.
errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
errReqBodyTooLong = errors.New("http2: request body larger than specified content length")
) )
func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) {
@ -1238,10 +1240,32 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
req := cs.req req := cs.req
hasTrailers := req.Trailer != nil hasTrailers := req.Trailer != nil
remainLen := actualContentLength(req)
hasContentLen := remainLen != -1
var sawEOF bool var sawEOF bool
for !sawEOF { for !sawEOF {
n, err := body.Read(buf) n, err := body.Read(buf[:len(buf)-1])
if hasContentLen {
remainLen -= int64(n)
if remainLen == 0 && err == nil {
// The request body's Content-Length was predeclared and
// we just finished reading it all, but the underlying io.Reader
// returned the final chunk with a nil error (which is one of
// the two valid things a Reader can do at EOF). Because we'd prefer
// to send the END_STREAM bit early, double-check that we're actually
// at EOF. Subsequent reads should return (0, EOF) at this point.
// If either value is different, we return an error in one of two ways below.
var n1 int
n1, err = body.Read(buf[n:])
remainLen -= int64(n1)
}
if remainLen < 0 {
err = errReqBodyTooLong
cc.writeStreamReset(cs.ID, ErrCodeCancel, err)
return err
}
}
if err == io.EOF { if err == io.EOF {
sawEOF = true sawEOF = true
err = nil err = nil

View File

@ -32,7 +32,7 @@ type WriteScheduler interface {
// Pop dequeues the next frame to write. Returns false if no frames can // Pop dequeues the next frame to write. Returns false if no frames can
// be written. Frames with a given wr.StreamID() are Pop'd in the same // be written. Frames with a given wr.StreamID() are Pop'd in the same
// order they are Push'd. // order they are Push'd. No frames should be discarded except by CloseStream.
Pop() (wr FrameWriteRequest, ok bool) Pop() (wr FrameWriteRequest, ok bool)
} }
@ -76,6 +76,12 @@ func (wr FrameWriteRequest) StreamID() uint32 {
return wr.stream.id return wr.stream.id
} }
// isControl reports whether wr is a control frame for MaxQueuedControlFrames
// purposes. That includes non-stream frames and RST_STREAM frames.
func (wr FrameWriteRequest) isControl() bool {
return wr.stream == nil
}
// DataSize returns the number of flow control bytes that must be consumed // DataSize returns the number of flow control bytes that must be consumed
// to write this entire frame. This is 0 for non-DATA frames. // to write this entire frame. This is 0 for non-DATA frames.
func (wr FrameWriteRequest) DataSize() int { func (wr FrameWriteRequest) DataSize() int {

View File

@ -149,7 +149,7 @@ func (n *priorityNode) addBytes(b int64) {
} }
// walkReadyInOrder iterates over the tree in priority order, calling f for each node // walkReadyInOrder iterates over the tree in priority order, calling f for each node
// with a non-empty write queue. When f returns true, this funcion returns true and the // with a non-empty write queue. When f returns true, this function returns true and the
// walk halts. tmp is used as scratch space for sorting. // walk halts. tmp is used as scratch space for sorting.
// //
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true

View File

@ -31,7 +31,6 @@ type sockaddrInet6 C.struct_sockaddr_in6
const ( const (
sizeofIovec = C.sizeof_struct_iovec sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in sizeofSockaddrInet = C.sizeof_struct_sockaddr_in

View File

@ -33,7 +33,6 @@ type sockaddrInet6 C.struct_sockaddr_in6
const ( const (
sizeofIovec = C.sizeof_struct_iovec sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in sizeofSockaddrInet = C.sizeof_struct_sockaddr_in

View File

@ -31,7 +31,6 @@ type sockaddrInet6 C.struct_sockaddr_in6
const ( const (
sizeofIovec = C.sizeof_struct_iovec sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in sizeofSockaddrInet = C.sizeof_struct_sockaddr_in

View File

@ -53,7 +53,6 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x30 sizeofMsghdr = 0x30
sizeofMmsghdr = 0x38
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -47,7 +47,6 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -50,7 +50,6 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -49,9 +49,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -47,9 +47,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -50,9 +50,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x30 sizeofMsghdr = 0x30
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -47,9 +47,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -52,7 +52,6 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x30 sizeofMsghdr = 0x30
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -127,7 +127,7 @@ type Dialer struct {
// establishing the transport connection. // establishing the transport connection.
ProxyDial func(context.Context, string, string) (net.Conn, error) ProxyDial func(context.Context, string, string) (net.Conn, error)
// AuthMethods specifies the list of request authention // AuthMethods specifies the list of request authentication
// methods. // methods.
// If empty, SOCKS client requests only AuthMethodNotRequired. // If empty, SOCKS client requests only AuthMethodNotRequired.
AuthMethods []AuthMethod AuthMethods []AuthMethod

View File

@ -5,26 +5,56 @@
package cpu package cpu
import ( import (
"encoding/binary"
"runtime" "runtime"
) )
// byteOrder is a subset of encoding/binary.ByteOrder.
type byteOrder interface {
Uint32([]byte) uint32
Uint64([]byte) uint64
}
type littleEndian struct{}
type bigEndian struct{}
func (littleEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
func (bigEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
func (bigEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}
// hostByteOrder returns binary.LittleEndian on little-endian machines and // hostByteOrder returns binary.LittleEndian on little-endian machines and
// binary.BigEndian on big-endian machines. // binary.BigEndian on big-endian machines.
func hostByteOrder() binary.ByteOrder { func hostByteOrder() byteOrder {
switch runtime.GOARCH { switch runtime.GOARCH {
case "386", "amd64", "amd64p32", case "386", "amd64", "amd64p32",
"arm", "arm64", "arm", "arm64",
"mipsle", "mips64le", "mips64p32le", "mipsle", "mips64le", "mips64p32le",
"ppc64le", "ppc64le",
"riscv", "riscv64": "riscv", "riscv64":
return binary.LittleEndian return littleEndian{}
case "armbe", "arm64be", case "armbe", "arm64be",
"mips", "mips64", "mips64p32", "mips", "mips64", "mips64p32",
"ppc", "ppc64", "ppc", "ppc64",
"s390", "s390x", "s390", "s390x",
"sparc", "sparc64": "sparc", "sparc64":
return binary.BigEndian return bigEndian{}
} }
panic("unknown architecture") panic("unknown architecture")
} }

36
vendor/golang.org/x/sys/cpu/cpu.go generated vendored
View File

@ -78,6 +78,42 @@ var ARM64 struct {
_ CacheLinePad _ CacheLinePad
} }
// ARM contains the supported CPU features of the current ARM (32-bit) platform.
// All feature flags are false if:
// 1. the current platform is not arm, or
// 2. the current operating system is not Linux.
var ARM struct {
_ CacheLinePad
HasSWP bool // SWP instruction support
HasHALF bool // Half-word load and store support
HasTHUMB bool // ARM Thumb instruction set
Has26BIT bool // Address space limited to 26-bits
HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support
HasFPA bool // Floating point arithmetic support
HasVFP bool // Vector floating point support
HasEDSP bool // DSP Extensions support
HasJAVA bool // Java instruction set
HasIWMMXT bool // Intel Wireless MMX technology support
HasCRUNCH bool // MaverickCrunch context switching and handling
HasTHUMBEE bool // Thumb EE instruction set
HasNEON bool // NEON instruction set
HasVFPv3 bool // Vector floating point version 3 support
HasVFPv3D16 bool // Vector floating point version 3 D8-D15
HasTLS bool // Thread local storage support
HasVFPv4 bool // Vector floating point version 4 support
HasIDIVA bool // Integer divide instruction support in ARM mode
HasIDIVT bool // Integer divide instruction support in Thumb mode
HasVFPD32 bool // Vector floating point version 3 D15-D31
HasLPAE bool // Large Physical Address Extensions
HasEVTSTRM bool // Event stream support
HasAES bool // AES hardware implementation
HasPMULL bool // Polynomial multiplication instruction set
HasSHA1 bool // SHA1 hardware implementation
HasSHA2 bool // SHA2 hardware implementation
HasCRC32 bool // CRC32 hardware implementation
_ CacheLinePad
}
// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. // PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
// If the current platform is not ppc64/ppc64le then all feature flags are false. // If the current platform is not ppc64/ppc64le then all feature flags are false.
// //

View File

@ -6,4 +6,35 @@ package cpu
const cacheLineSize = 32 const cacheLineSize = 32
func doinit() {} // HWCAP/HWCAP2 bits.
// These are specific to Linux.
const (
hwcap_SWP = 1 << 0
hwcap_HALF = 1 << 1
hwcap_THUMB = 1 << 2
hwcap_26BIT = 1 << 3
hwcap_FAST_MULT = 1 << 4
hwcap_FPA = 1 << 5
hwcap_VFP = 1 << 6
hwcap_EDSP = 1 << 7
hwcap_JAVA = 1 << 8
hwcap_IWMMXT = 1 << 9
hwcap_CRUNCH = 1 << 10
hwcap_THUMBEE = 1 << 11
hwcap_NEON = 1 << 12
hwcap_VFPv3 = 1 << 13
hwcap_VFPv3D16 = 1 << 14
hwcap_TLS = 1 << 15
hwcap_VFPv4 = 1 << 16
hwcap_IDIVA = 1 << 17
hwcap_IDIVT = 1 << 18
hwcap_VFPD32 = 1 << 19
hwcap_LPAE = 1 << 20
hwcap_EVTSTRM = 1 << 21
hwcap2_AES = 1 << 0
hwcap2_PMULL = 1 << 1
hwcap2_SHA1 = 1 << 2
hwcap2_SHA2 = 1 << 3
hwcap2_CRC32 = 1 << 4
)

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//+build !amd64,!amd64p32,!386 // +build !amd64,!amd64p32,!386
package cpu package cpu

39
vendor/golang.org/x/sys/cpu/cpu_linux_arm.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// 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.
package cpu
func doinit() {
ARM.HasSWP = isSet(hwCap, hwcap_SWP)
ARM.HasHALF = isSet(hwCap, hwcap_HALF)
ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB)
ARM.Has26BIT = isSet(hwCap, hwcap_26BIT)
ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT)
ARM.HasFPA = isSet(hwCap, hwcap_FPA)
ARM.HasVFP = isSet(hwCap, hwcap_VFP)
ARM.HasEDSP = isSet(hwCap, hwcap_EDSP)
ARM.HasJAVA = isSet(hwCap, hwcap_JAVA)
ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT)
ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH)
ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE)
ARM.HasNEON = isSet(hwCap, hwcap_NEON)
ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3)
ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16)
ARM.HasTLS = isSet(hwCap, hwcap_TLS)
ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4)
ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA)
ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT)
ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32)
ARM.HasLPAE = isSet(hwCap, hwcap_LPAE)
ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM)
ARM.HasAES = isSet(hwCap2, hwcap2_AES)
ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL)
ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1)
ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2)
ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32)
}
func isSet(hwc uint, value uint) bool {
return hwc&value != 0
}

View File

@ -7,6 +7,7 @@
package unix package unix
import ( import (
"math/bits"
"unsafe" "unsafe"
) )
@ -79,50 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool {
func (s *CPUSet) Count() int { func (s *CPUSet) Count() int {
c := 0 c := 0
for _, b := range s { for _, b := range s {
c += onesCount64(uint64(b)) c += bits.OnesCount64(uint64(b))
} }
return c return c
} }
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
// Once this package can require Go 1.9, we can delete this
// and update the caller to use bits.OnesCount64.
func onesCount64(x uint64) int {
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
// Unused in this function, but definitions preserved for
// documentation purposes:
//
// const m3 = 0x00ff00ff00ff00ff // etc.
// const m4 = 0x0000ffff0000ffff
//
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
//
// x = x>>1&(m0&m) + x&(m0&m)
// x = x>>2&(m1&m) + x&(m1&m)
// x = x>>4&(m2&m) + x&(m2&m)
// x = x>>8&(m3&m) + x&(m3&m)
// x = x>>16&(m4&m) + x&(m4&m)
// x = x>>32&(m5&m) + x&(m5&m)
// return int(x)
//
// Masking (& operations) can be left away when there's no
// danger that a field's sum will carry over into the next
// field: Since the result cannot be > 64, 8 bits is enough
// and we can ignore the masks for the shifts by 8 and up.
// Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave
// it alone for clarity.
const m = 1<<64 - 1
x = x>>1&(m0&m) + x&(m0&m)
x = x>>2&(m1&m) + x&(m1&m)
x = (x>>4 + x) & (m2 & m)
x += x >> 8
x += x >> 16
x += x >> 32
return int(x) & (1<<7 - 1)
}

View File

@ -23,6 +23,7 @@ const (
HCI_CHANNEL_USER = 1 HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2 HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3 HCI_CHANNEL_CONTROL = 3
HCI_CHANNEL_LOGGING = 4
) )
// Socketoption Level // Socketoption Level

29
vendor/golang.org/x/sys/unix/fdset.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix
// Set adds fd to the set fds.
func (fds *FdSet) Set(fd int) {
fds.Bits[fd/NFDBITS] |= (1 << (uintptr(fd) % NFDBITS))
}
// Clear removes fd from the set fds.
func (fds *FdSet) Clear(fd int) {
fds.Bits[fd/NFDBITS] &^= (1 << (uintptr(fd) % NFDBITS))
}
// IsSet returns whether fd is in the set fds.
func (fds *FdSet) IsSet(fd int) bool {
return fds.Bits[fd/NFDBITS]&(1<<(uintptr(fd)%NFDBITS)) != 0
}
// Zero clears the set fds.
func (fds *FdSet) Zero() {
for i := range fds.Bits {
fds.Bits[i] = 0
}
}

View File

@ -6,7 +6,19 @@
package unix package unix
import "runtime" import (
"runtime"
"unsafe"
)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
@ -14,7 +26,7 @@ import "runtime"
func IoctlSetWinsize(fd int, req uint, value *Winsize) error { func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
// TODO: if we get the chance, remove the req parameter and // TODO: if we get the chance, remove the req parameter and
// hardcode TIOCSWINSZ. // hardcode TIOCSWINSZ.
err := ioctlSetWinsize(fd, req, value) err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
@ -24,7 +36,30 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
// The req value will usually be TCSETA or TIOCSETA. // The req value will usually be TCSETA or TIOCSETA.
func IoctlSetTermios(fd int, req uint, value *Termios) error { func IoctlSetTermios(fd int, req uint, value *Termios) error {
// TODO: if we get the chance, remove the req parameter. // TODO: if we get the chance, remove the req parameter.
err := ioctlSetTermios(fd, req, value) err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
//
// A few ioctl requests use the return value as an output parameter;
// for those, IoctlRetInt should be used instead of this function.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}

View File

@ -212,9 +212,11 @@ esac
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
elif [ "$GOOS" == "darwin" ]; then elif [ "$GOOS" == "darwin" ]; then
# pre-1.12, direct syscalls # pre-1.12, direct syscalls
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go"; echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
# 1.12 and later, syscalls via libSystem # 1.12 and later, syscalls via libSystem
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
# 1.13 and later, syscalls via libSystem (including syscallPtr)
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
else else
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
fi fi

View File

@ -17,6 +17,34 @@ import (
"strings" "strings"
) )
func writeASMFile(in string, fileName string, buildTags string) {
trampolines := map[string]bool{}
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "// +build %s\n", buildTags)
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
continue
}
fn := line[5 : len(line)-13]
if !trampolines[fn] {
trampolines[fn] = true
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write %s: %s", fileName, err)
}
}
func main() { func main() {
in1, err := ioutil.ReadFile("syscall_darwin.go") in1, err := ioutil.ReadFile("syscall_darwin.go")
if err != nil { if err != nil {
@ -33,29 +61,18 @@ func main() {
} }
in := string(in1) + string(in2) + string(in3) in := string(in1) + string(in2) + string(in3)
trampolines := map[string]bool{} writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.s", arch), "go1.12")
var out bytes.Buffer in1, err = ioutil.ReadFile("syscall_darwin.1_13.go")
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "// +build go1.12\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
continue
}
fn := line[5 : len(line)-13]
if !trampolines[fn] {
trampolines[fn] = true
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
if err != nil { if err != nil {
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) log.Fatalf("can't open syscall_darwin.1_13.go: %s", err)
} }
in2, err = ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.1_13.go", arch))
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.1_13.go: %s", arch, err)
}
in = string(in1) + string(in2)
writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.1_13.s", arch), "go1.13")
} }

View File

@ -60,6 +60,7 @@ includes_Darwin='
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -80,6 +81,7 @@ includes_Darwin='
includes_DragonFly=' includes_DragonFly='
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -103,6 +105,7 @@ includes_FreeBSD='
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -179,24 +182,32 @@ struct ltchars {
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/select.h>
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/can.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cryptouser.h>
#include <linux/devlink.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/icmpv6.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_addr.h>
#include <linux/if_alg.h> #include <linux/if_alg.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_ppp.h> #include <linux/if_ppp.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/if_addr.h> #include <linux/if_xdp.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/loop.h> #include <linux/loop.h>
@ -206,26 +217,23 @@ struct ltchars {
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/net_namespace.h> #include <linux/net_namespace.h>
#include <linux/nsfs.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/ptrace.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/seccomp.h> #include <linux/seccomp.h>
#include <linux/sockios.h>
#include <linux/wait.h>
#include <linux/icmpv6.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/can.h> #include <linux/sockios.h>
#include <linux/vm_sockets.h>
#include <linux/taskstats.h> #include <linux/taskstats.h>
#include <linux/genetlink.h> #include <linux/tipc.h>
#include <linux/vm_sockets.h>
#include <linux/wait.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/hdreg.h>
#include <linux/rtc.h>
#include <linux/if_xdp.h>
#include <linux/cryptouser.h>
#include <mtd/ubi-user.h> #include <mtd/ubi-user.h>
#include <net/route.h> #include <net/route.h>
@ -264,6 +272,11 @@ struct ltchars {
#define FS_KEY_DESC_PREFIX "fscrypt:" #define FS_KEY_DESC_PREFIX "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE 8 #define FS_KEY_DESC_PREFIX_SIZE 8
#define FS_MAX_KEY_SIZE 64 #define FS_MAX_KEY_SIZE 64
// The code generator produces -0x1 for (~0), but an unsigned value is necessary
// for the tipc_subscr timeout __u32 field.
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff
' '
includes_NetBSD=' includes_NetBSD='
@ -273,6 +286,7 @@ includes_NetBSD='
#include <sys/extattr.h> #include <sys/extattr.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -299,6 +313,7 @@ includes_OpenBSD='
#include <sys/event.h> #include <sys/event.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -335,6 +350,7 @@ includes_OpenBSD='
includes_SunOS=' includes_SunOS='
#include <limits.h> #include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -427,6 +443,7 @@ ccflags="$@"
$2 == "XCASE" || $2 == "XCASE" ||
$2 == "ALTWERASE" || $2 == "ALTWERASE" ||
$2 == "NOKERNINFO" || $2 == "NOKERNINFO" ||
$2 == "NFDBITS" ||
$2 ~ /^PAR/ || $2 ~ /^PAR/ ||
$2 ~ /^SIG[^_]/ || $2 ~ /^SIG[^_]/ ||
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
@ -451,6 +468,7 @@ ccflags="$@"
$2 ~ /^SYSCTL_VERS/ || $2 ~ /^SYSCTL_VERS/ ||
$2 !~ "MNT_BITS" && $2 !~ "MNT_BITS" &&
$2 ~ /^(MS|MNT|UMOUNT)_/ || $2 ~ /^(MS|MNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
$2 ~ /^KEXEC_/ || $2 ~ /^KEXEC_/ ||
@ -506,6 +524,8 @@ ccflags="$@"
$2 ~ /^XDP_/ || $2 ~ /^XDP_/ ||
$2 ~ /^(HDIO|WIN|SMART)_/ || $2 ~ /^(HDIO|WIN|SMART)_/ ||
$2 ~ /^CRYPTO_/ || $2 ~ /^CRYPTO_/ ||
$2 ~ /^TIPC_/ ||
$2 ~ /^DEVLINK_/ ||
$2 !~ "WMESGLEN" && $2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ || $2 ~ /^W[A-Z0-9]+$/ ||
$2 ~/^PPPIOC/ || $2 ~/^PPPIOC/ ||

View File

@ -121,7 +121,7 @@ func main() {
} }
libc := false libc := false
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") { if goos == "darwin" && (strings.Contains(buildTags(), ",go1.12") || strings.Contains(buildTags(), ",go1.13")) {
libc = true libc = true
} }
trampolines := map[string]bool{} trampolines := map[string]bool{}
@ -292,11 +292,6 @@ func main() {
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_ sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
sysname = strings.ToLower(sysname) // lowercase sysname = strings.ToLower(sysname) // lowercase
if sysname == "getdirentries64" {
// Special case - libSystem name and
// raw syscall name don't match.
sysname = "__getdirentries64"
}
libcFn = sysname libcFn = sysname
sysname = "funcPC(libc_" + sysname + "_trampoline)" sysname = "funcPC(libc_" + sysname + "_trampoline)"
} }

16
vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// 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.
package unix
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
if SizeofPtr == 8 && !supportsABI(_dragonflyABIChangeVersion) {
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
salign = 4
}
return (salen + salign - 1) & ^(salign - 1)
}

View File

@ -17,7 +17,7 @@ func UnixCredentials(ucred *Ucred) []byte {
h.Level = SOL_SOCKET h.Level = SOL_SOCKET
h.Type = SCM_CREDENTIALS h.Type = SCM_CREDENTIALS
h.SetLen(CmsgLen(SizeofUcred)) h.SetLen(CmsgLen(SizeofUcred))
*((*Ucred)(cmsgData(h))) = *ucred *(*Ucred)(h.data(0)) = *ucred
return b return b
} }

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