Compare commits

..

2 Commits

Author SHA1 Message Date
bloved bc2470e344 updated vendor dependencies and golang to 1.15 2021-09-16 14:18:18 +02:00
bloved e2a625a92e if the DNS response Rcode contains an error the cache expires after just 10 seconds.
this should limit the cache in case of temporary upstream DNS errors.
2021-09-16 09:40:03 +02:00
569 changed files with 52839 additions and 119406 deletions

View File

@ -13,7 +13,7 @@ import (
type cacheItem struct { type cacheItem struct {
Query []byte Query []byte
Date time.Time ExpireDate time.Time
} }
//DomainCache stores a domain name inside the cache //DomainCache stores a domain name inside the cache
@ -28,7 +28,17 @@ func DomainCache(s string, resp *dns.Msg) {
if err != nil { if err != nil {
fmt.Println("Problems packing the response: ", err.Error()) fmt.Println("Problems packing the response: ", err.Error())
} }
domain2cache.Date = time.Now() if resp.Rcode == dns.RcodeSuccess{
// on success stores response normally
domain2cache.ExpireDate = time.Now().Add((time.Duration(ZabovCacheTTL) * time.Hour))
}else
{
// on failure stores response for a very short time
if ZabovDebug {
fmt.Println("DomainCache(): DNS error Rcode: ", resp.Rcode, s, "cache time reduced to 10 seconds...")
}
domain2cache.ExpireDate = time.Now().Add((time.Duration(10) * time.Second))
}
err = enc.Encode(domain2cache) err = enc.Encode(domain2cache)
@ -65,7 +75,7 @@ func GetDomainFromCache(s string) *dns.Msg {
conf, errDB = MyZabovCDB.Get([]byte(s), nil) conf, errDB = MyZabovCDB.Get([]byte(s), nil)
if errDB != nil { if errDB != nil {
fmt.Println("Cant READ DB :" , errDB.Error() ) fmt.Println("Cant READ DB:" , errDB.Error() )
return nil return nil
} }
@ -77,7 +87,10 @@ func GetDomainFromCache(s string) *dns.Msg {
return nil return nil
} }
if time.Since(record.Date) > (time.Duration(ZabovCacheTTL) * time.Hour) { if time.Now().After(record.ExpireDate) {
if ZabovDebug {
fmt.Println("GetDomainFromCache(): entry expired:", s)
}
return nil return nil
} }

7
go.mod
View File

@ -1,8 +1,11 @@
module zabov module zabov
go 1.13 go 1.15
require ( require (
github.com/miekg/dns v1.1.27 github.com/golang/snappy v0.0.4
github.com/miekg/dns v1.1.43
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164
) )

36
go.sum
View File

@ -1,35 +1,33 @@
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

View File

@ -8,8 +8,11 @@
# Please keep the list sorted. # Please keep the list sorted.
Amazon.com, Inc
Damian Gryski <dgryski@gmail.com> Damian Gryski <dgryski@gmail.com>
Eric Buth <eric@topos.com>
Google Inc. Google Inc.
Jan Mercl <0xjnml@gmail.com> Jan Mercl <0xjnml@gmail.com>
Klaus Post <klauspost@gmail.com>
Rodolfo Carvalho <rhcarvalho@gmail.com> Rodolfo Carvalho <rhcarvalho@gmail.com>
Sebastien Binet <seb.binet@gmail.com> Sebastien Binet <seb.binet@gmail.com>

View File

@ -26,9 +26,13 @@
# Please keep the list sorted. # Please keep the list sorted.
Alex Legg <alexlegg@google.com>
Damian Gryski <dgryski@gmail.com> Damian Gryski <dgryski@gmail.com>
Eric Buth <eric@topos.com>
Jan Mercl <0xjnml@gmail.com> Jan Mercl <0xjnml@gmail.com>
Jonathan Swinney <jswinney@amazon.com>
Kai Backman <kaib@golang.org> Kai Backman <kaib@golang.org>
Klaus Post <klauspost@gmail.com>
Marc-Antoine Ruel <maruel@chromium.org> Marc-Antoine Ruel <maruel@chromium.org>
Nigel Tao <nigeltao@golang.org> Nigel Tao <nigeltao@golang.org>
Rob Pike <r@golang.org> Rob Pike <r@golang.org>

View File

@ -52,6 +52,8 @@ const (
// Otherwise, a newly allocated slice will be returned. // Otherwise, a newly allocated slice will be returned.
// //
// The dst and src must not overlap. It is valid to pass a nil dst. // The dst and src must not overlap. It is valid to pass a nil dst.
//
// Decode handles the Snappy block format, not the Snappy stream format.
func Decode(dst, src []byte) ([]byte, error) { func Decode(dst, src []byte) ([]byte, error) {
dLen, s, err := decodedLen(src) dLen, s, err := decodedLen(src)
if err != nil { if err != nil {
@ -83,6 +85,8 @@ func NewReader(r io.Reader) *Reader {
} }
// Reader is an io.Reader that can read Snappy-compressed bytes. // Reader is an io.Reader that can read Snappy-compressed bytes.
//
// Reader handles the Snappy stream format, not the Snappy block format.
type Reader struct { type Reader struct {
r io.Reader r io.Reader
err error err error
@ -114,32 +118,23 @@ func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) {
return true return true
} }
// Read satisfies the io.Reader interface. func (r *Reader) fill() error {
func (r *Reader) Read(p []byte) (int, error) { for r.i >= r.j {
if r.err != nil {
return 0, r.err
}
for {
if r.i < r.j {
n := copy(p, r.decoded[r.i:r.j])
r.i += n
return n, nil
}
if !r.readFull(r.buf[:4], true) { if !r.readFull(r.buf[:4], true) {
return 0, r.err return r.err
} }
chunkType := r.buf[0] chunkType := r.buf[0]
if !r.readHeader { if !r.readHeader {
if chunkType != chunkTypeStreamIdentifier { if chunkType != chunkTypeStreamIdentifier {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
r.readHeader = true r.readHeader = true
} }
chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16
if chunkLen > len(r.buf) { if chunkLen > len(r.buf) {
r.err = ErrUnsupported r.err = ErrUnsupported
return 0, r.err return r.err
} }
// The chunk types are specified at // The chunk types are specified at
@ -149,11 +144,11 @@ func (r *Reader) Read(p []byte) (int, error) {
// Section 4.2. Compressed data (chunk type 0x00). // Section 4.2. Compressed data (chunk type 0x00).
if chunkLen < checksumSize { if chunkLen < checksumSize {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
buf := r.buf[:chunkLen] buf := r.buf[:chunkLen]
if !r.readFull(buf, false) { if !r.readFull(buf, false) {
return 0, r.err return r.err
} }
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
buf = buf[checksumSize:] buf = buf[checksumSize:]
@ -161,19 +156,19 @@ func (r *Reader) Read(p []byte) (int, error) {
n, err := DecodedLen(buf) n, err := DecodedLen(buf)
if err != nil { if err != nil {
r.err = err r.err = err
return 0, r.err return r.err
} }
if n > len(r.decoded) { if n > len(r.decoded) {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
if _, err := Decode(r.decoded, buf); err != nil { if _, err := Decode(r.decoded, buf); err != nil {
r.err = err r.err = err
return 0, r.err return r.err
} }
if crc(r.decoded[:n]) != checksum { if crc(r.decoded[:n]) != checksum {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
r.i, r.j = 0, n r.i, r.j = 0, n
continue continue
@ -182,25 +177,25 @@ func (r *Reader) Read(p []byte) (int, error) {
// Section 4.3. Uncompressed data (chunk type 0x01). // Section 4.3. Uncompressed data (chunk type 0x01).
if chunkLen < checksumSize { if chunkLen < checksumSize {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
buf := r.buf[:checksumSize] buf := r.buf[:checksumSize]
if !r.readFull(buf, false) { if !r.readFull(buf, false) {
return 0, r.err return r.err
} }
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
// Read directly into r.decoded instead of via r.buf. // Read directly into r.decoded instead of via r.buf.
n := chunkLen - checksumSize n := chunkLen - checksumSize
if n > len(r.decoded) { if n > len(r.decoded) {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
if !r.readFull(r.decoded[:n], false) { if !r.readFull(r.decoded[:n], false) {
return 0, r.err return r.err
} }
if crc(r.decoded[:n]) != checksum { if crc(r.decoded[:n]) != checksum {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
r.i, r.j = 0, n r.i, r.j = 0, n
continue continue
@ -209,15 +204,15 @@ func (r *Reader) Read(p []byte) (int, error) {
// Section 4.1. Stream identifier (chunk type 0xff). // Section 4.1. Stream identifier (chunk type 0xff).
if chunkLen != len(magicBody) { if chunkLen != len(magicBody) {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
if !r.readFull(r.buf[:len(magicBody)], false) { if !r.readFull(r.buf[:len(magicBody)], false) {
return 0, r.err return r.err
} }
for i := 0; i < len(magicBody); i++ { for i := 0; i < len(magicBody); i++ {
if r.buf[i] != magicBody[i] { if r.buf[i] != magicBody[i] {
r.err = ErrCorrupt r.err = ErrCorrupt
return 0, r.err return r.err
} }
} }
continue continue
@ -226,12 +221,44 @@ func (r *Reader) Read(p []byte) (int, error) {
if chunkType <= 0x7f { if chunkType <= 0x7f {
// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f).
r.err = ErrUnsupported r.err = ErrUnsupported
return 0, r.err return r.err
} }
// Section 4.4 Padding (chunk type 0xfe). // Section 4.4 Padding (chunk type 0xfe).
// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd).
if !r.readFull(r.buf[:chunkLen], false) { if !r.readFull(r.buf[:chunkLen], false) {
return 0, r.err return r.err
} }
} }
return nil
}
// Read satisfies the io.Reader interface.
func (r *Reader) Read(p []byte) (int, error) {
if r.err != nil {
return 0, r.err
}
if err := r.fill(); err != nil {
return 0, err
}
n := copy(p, r.decoded[r.i:r.j])
r.i += n
return n, nil
}
// ReadByte satisfies the io.ByteReader interface.
func (r *Reader) ReadByte() (byte, error) {
if r.err != nil {
return 0, r.err
}
if err := r.fill(); err != nil {
return 0, err
}
c := r.decoded[r.i]
r.i++
return c, nil
} }

494
vendor/github.com/golang/snappy/decode_arm64.s generated vendored Normal file
View File

@ -0,0 +1,494 @@
// Copyright 2020 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 !appengine
// +build gc
// +build !noasm
#include "textflag.h"
// The asm code generally follows the pure Go code in decode_other.go, except
// where marked with a "!!!".
// func decode(dst, src []byte) int
//
// All local variables fit into registers. The non-zero stack size is only to
// spill registers and push args when issuing a CALL. The register allocation:
// - R2 scratch
// - R3 scratch
// - R4 length or x
// - R5 offset
// - R6 &src[s]
// - R7 &dst[d]
// + R8 dst_base
// + R9 dst_len
// + R10 dst_base + dst_len
// + R11 src_base
// + R12 src_len
// + R13 src_base + src_len
// - R14 used by doCopy
// - R15 used by doCopy
//
// The registers R8-R13 (marked with a "+") are set at the start of the
// function, and after a CALL returns, and are not otherwise modified.
//
// The d variable is implicitly R7 - R8, and len(dst)-d is R10 - R7.
// The s variable is implicitly R6 - R11, and len(src)-s is R13 - R6.
TEXT ·decode(SB), NOSPLIT, $56-56
// Initialize R6, R7 and R8-R13.
MOVD dst_base+0(FP), R8
MOVD dst_len+8(FP), R9
MOVD R8, R7
MOVD R8, R10
ADD R9, R10, R10
MOVD src_base+24(FP), R11
MOVD src_len+32(FP), R12
MOVD R11, R6
MOVD R11, R13
ADD R12, R13, R13
loop:
// for s < len(src)
CMP R13, R6
BEQ end
// R4 = uint32(src[s])
//
// switch src[s] & 0x03
MOVBU (R6), R4
MOVW R4, R3
ANDW $3, R3
MOVW $1, R1
CMPW R1, R3
BGE tagCopy
// ----------------------------------------
// The code below handles literal tags.
// case tagLiteral:
// x := uint32(src[s] >> 2)
// switch
MOVW $60, R1
LSRW $2, R4, R4
CMPW R4, R1
BLS tagLit60Plus
// case x < 60:
// s++
ADD $1, R6, R6
doLit:
// This is the end of the inner "switch", when we have a literal tag.
//
// We assume that R4 == x and x fits in a uint32, where x is the variable
// used in the pure Go decode_other.go code.
// length = int(x) + 1
//
// Unlike the pure Go code, we don't need to check if length <= 0 because
// R4 can hold 64 bits, so the increment cannot overflow.
ADD $1, R4, R4
// Prepare to check if copying length bytes will run past the end of dst or
// src.
//
// R2 = len(dst) - d
// R3 = len(src) - s
MOVD R10, R2
SUB R7, R2, R2
MOVD R13, R3
SUB R6, R3, R3
// !!! Try a faster technique for short (16 or fewer bytes) copies.
//
// if length > 16 || len(dst)-d < 16 || len(src)-s < 16 {
// goto callMemmove // Fall back on calling runtime·memmove.
// }
//
// The C++ snappy code calls this TryFastAppend. It also checks len(src)-s
// against 21 instead of 16, because it cannot assume that all of its input
// is contiguous in memory and so it needs to leave enough source bytes to
// read the next tag without refilling buffers, but Go's Decode assumes
// contiguousness (the src argument is a []byte).
CMP $16, R4
BGT callMemmove
CMP $16, R2
BLT callMemmove
CMP $16, R3
BLT callMemmove
// !!! Implement the copy from src to dst as a 16-byte load and store.
// (Decode's documentation says that dst and src must not overlap.)
//
// This always copies 16 bytes, instead of only length bytes, but that's
// OK. If the input is a valid Snappy encoding then subsequent iterations
// will fix up the overrun. Otherwise, Decode returns a nil []byte (and a
// non-nil error), so the overrun will be ignored.
//
// Note that on arm64, it is legal and cheap to issue unaligned 8-byte or
// 16-byte loads and stores. This technique probably wouldn't be as
// effective on architectures that are fussier about alignment.
LDP 0(R6), (R14, R15)
STP (R14, R15), 0(R7)
// d += length
// s += length
ADD R4, R7, R7
ADD R4, R6, R6
B loop
callMemmove:
// if length > len(dst)-d || length > len(src)-s { etc }
CMP R2, R4
BGT errCorrupt
CMP R3, R4
BGT errCorrupt
// copy(dst[d:], src[s:s+length])
//
// This means calling runtime·memmove(&dst[d], &src[s], length), so we push
// R7, R6 and R4 as arguments. Coincidentally, we also need to spill those
// three registers to the stack, to save local variables across the CALL.
MOVD R7, 8(RSP)
MOVD R6, 16(RSP)
MOVD R4, 24(RSP)
MOVD R7, 32(RSP)
MOVD R6, 40(RSP)
MOVD R4, 48(RSP)
CALL runtime·memmove(SB)
// Restore local variables: unspill registers from the stack and
// re-calculate R8-R13.
MOVD 32(RSP), R7
MOVD 40(RSP), R6
MOVD 48(RSP), R4
MOVD dst_base+0(FP), R8
MOVD dst_len+8(FP), R9
MOVD R8, R10
ADD R9, R10, R10
MOVD src_base+24(FP), R11
MOVD src_len+32(FP), R12
MOVD R11, R13
ADD R12, R13, R13
// d += length
// s += length
ADD R4, R7, R7
ADD R4, R6, R6
B loop
tagLit60Plus:
// !!! This fragment does the
//
// s += x - 58; if uint(s) > uint(len(src)) { etc }
//
// checks. In the asm version, we code it once instead of once per switch case.
ADD R4, R6, R6
SUB $58, R6, R6
MOVD R6, R3
SUB R11, R3, R3
CMP R12, R3
BGT errCorrupt
// case x == 60:
MOVW $61, R1
CMPW R1, R4
BEQ tagLit61
BGT tagLit62Plus
// x = uint32(src[s-1])
MOVBU -1(R6), R4
B doLit
tagLit61:
// case x == 61:
// x = uint32(src[s-2]) | uint32(src[s-1])<<8
MOVHU -2(R6), R4
B doLit
tagLit62Plus:
CMPW $62, R4
BHI tagLit63
// case x == 62:
// x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
MOVHU -3(R6), R4
MOVBU -1(R6), R3
ORR R3<<16, R4
B doLit
tagLit63:
// case x == 63:
// x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
MOVWU -4(R6), R4
B doLit
// The code above handles literal tags.
// ----------------------------------------
// The code below handles copy tags.
tagCopy4:
// case tagCopy4:
// s += 5
ADD $5, R6, R6
// if uint(s) > uint(len(src)) { etc }
MOVD R6, R3
SUB R11, R3, R3
CMP R12, R3
BGT errCorrupt
// length = 1 + int(src[s-5])>>2
MOVD $1, R1
ADD R4>>2, R1, R4
// offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24)
MOVWU -4(R6), R5
B doCopy
tagCopy2:
// case tagCopy2:
// s += 3
ADD $3, R6, R6
// if uint(s) > uint(len(src)) { etc }
MOVD R6, R3
SUB R11, R3, R3
CMP R12, R3
BGT errCorrupt
// length = 1 + int(src[s-3])>>2
MOVD $1, R1
ADD R4>>2, R1, R4
// offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8)
MOVHU -2(R6), R5
B doCopy
tagCopy:
// We have a copy tag. We assume that:
// - R3 == src[s] & 0x03
// - R4 == src[s]
CMP $2, R3
BEQ tagCopy2
BGT tagCopy4
// case tagCopy1:
// s += 2
ADD $2, R6, R6
// if uint(s) > uint(len(src)) { etc }
MOVD R6, R3
SUB R11, R3, R3
CMP R12, R3
BGT errCorrupt
// offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]))
MOVD R4, R5
AND $0xe0, R5
MOVBU -1(R6), R3
ORR R5<<3, R3, R5
// length = 4 + int(src[s-2])>>2&0x7
MOVD $7, R1
AND R4>>2, R1, R4
ADD $4, R4, R4
doCopy:
// This is the end of the outer "switch", when we have a copy tag.
//
// We assume that:
// - R4 == length && R4 > 0
// - R5 == offset
// if offset <= 0 { etc }
MOVD $0, R1
CMP R1, R5
BLE errCorrupt
// if d < offset { etc }
MOVD R7, R3
SUB R8, R3, R3
CMP R5, R3
BLT errCorrupt
// if length > len(dst)-d { etc }
MOVD R10, R3
SUB R7, R3, R3
CMP R3, R4
BGT errCorrupt
// forwardCopy(dst[d:d+length], dst[d-offset:]); d += length
//
// Set:
// - R14 = len(dst)-d
// - R15 = &dst[d-offset]
MOVD R10, R14
SUB R7, R14, R14
MOVD R7, R15
SUB R5, R15, R15
// !!! Try a faster technique for short (16 or fewer bytes) forward copies.
//
// First, try using two 8-byte load/stores, similar to the doLit technique
// above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is
// still OK if offset >= 8. Note that this has to be two 8-byte load/stores
// and not one 16-byte load/store, and the first store has to be before the
// second load, due to the overlap if offset is in the range [8, 16).
//
// if length > 16 || offset < 8 || len(dst)-d < 16 {
// goto slowForwardCopy
// }
// copy 16 bytes
// d += length
CMP $16, R4
BGT slowForwardCopy
CMP $8, R5
BLT slowForwardCopy
CMP $16, R14
BLT slowForwardCopy
MOVD 0(R15), R2
MOVD R2, 0(R7)
MOVD 8(R15), R3
MOVD R3, 8(R7)
ADD R4, R7, R7
B loop
slowForwardCopy:
// !!! If the forward copy is longer than 16 bytes, or if offset < 8, we
// can still try 8-byte load stores, provided we can overrun up to 10 extra
// bytes. As above, the overrun will be fixed up by subsequent iterations
// of the outermost loop.
//
// The C++ snappy code calls this technique IncrementalCopyFastPath. Its
// commentary says:
//
// ----
//
// The main part of this loop is a simple copy of eight bytes at a time
// until we've copied (at least) the requested amount of bytes. However,
// if d and d-offset are less than eight bytes apart (indicating a
// repeating pattern of length < 8), we first need to expand the pattern in
// order to get the correct results. For instance, if the buffer looks like
// this, with the eight-byte <d-offset> and <d> patterns marked as
// intervals:
//
// abxxxxxxxxxxxx
// [------] d-offset
// [------] d
//
// a single eight-byte copy from <d-offset> to <d> will repeat the pattern
// once, after which we can move <d> two bytes without moving <d-offset>:
//
// ababxxxxxxxxxx
// [------] d-offset
// [------] d
//
// and repeat the exercise until the two no longer overlap.
//
// This allows us to do very well in the special case of one single byte
// repeated many times, without taking a big hit for more general cases.
//
// The worst case of extra writing past the end of the match occurs when
// offset == 1 and length == 1; the last copy will read from byte positions
// [0..7] and write to [4..11], whereas it was only supposed to write to
// position 1. Thus, ten excess bytes.
//
// ----
//
// That "10 byte overrun" worst case is confirmed by Go's
// TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy
// and finishSlowForwardCopy algorithm.
//
// if length > len(dst)-d-10 {
// goto verySlowForwardCopy
// }
SUB $10, R14, R14
CMP R14, R4
BGT verySlowForwardCopy
makeOffsetAtLeast8:
// !!! As above, expand the pattern so that offset >= 8 and we can use
// 8-byte load/stores.
//
// for offset < 8 {
// copy 8 bytes from dst[d-offset:] to dst[d:]
// length -= offset
// d += offset
// offset += offset
// // The two previous lines together means that d-offset, and therefore
// // R15, is unchanged.
// }
CMP $8, R5
BGE fixUpSlowForwardCopy
MOVD (R15), R3
MOVD R3, (R7)
SUB R5, R4, R4
ADD R5, R7, R7
ADD R5, R5, R5
B makeOffsetAtLeast8
fixUpSlowForwardCopy:
// !!! Add length (which might be negative now) to d (implied by R7 being
// &dst[d]) so that d ends up at the right place when we jump back to the
// top of the loop. Before we do that, though, we save R7 to R2 so that, if
// length is positive, copying the remaining length bytes will write to the
// right place.
MOVD R7, R2
ADD R4, R7, R7
finishSlowForwardCopy:
// !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative
// length means that we overrun, but as above, that will be fixed up by
// subsequent iterations of the outermost loop.
MOVD $0, R1
CMP R1, R4
BLE loop
MOVD (R15), R3
MOVD R3, (R2)
ADD $8, R15, R15
ADD $8, R2, R2
SUB $8, R4, R4
B finishSlowForwardCopy
verySlowForwardCopy:
// verySlowForwardCopy is a simple implementation of forward copy. In C
// parlance, this is a do/while loop instead of a while loop, since we know
// that length > 0. In Go syntax:
//
// for {
// dst[d] = dst[d - offset]
// d++
// length--
// if length == 0 {
// break
// }
// }
MOVB (R15), R3
MOVB R3, (R7)
ADD $1, R15, R15
ADD $1, R7, R7
SUB $1, R4, R4
CBNZ R4, verySlowForwardCopy
B loop
// The code above handles copy tags.
// ----------------------------------------
end:
// This is the end of the "for s < len(src)".
//
// if d != len(dst) { etc }
CMP R10, R7
BNE errCorrupt
// return 0
MOVD $0, ret+48(FP)
RET
errCorrupt:
// return decodeErrCodeCorrupt
MOVD $1, R2
MOVD R2, ret+48(FP)
RET

View File

@ -5,6 +5,7 @@
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !noasm // +build !noasm
// +build amd64 arm64
package snappy package snappy

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 appengine !gc noasm // +build !amd64,!arm64 appengine !gc noasm
package snappy package snappy
@ -85,14 +85,28 @@ func decode(dst, src []byte) int {
if offset <= 0 || d < offset || length > len(dst)-d { if offset <= 0 || d < offset || length > len(dst)-d {
return decodeErrCodeCorrupt return decodeErrCodeCorrupt
} }
// Copy from an earlier sub-slice of dst to a later sub-slice. Unlike // Copy from an earlier sub-slice of dst to a later sub-slice.
// the built-in copy function, this byte-by-byte copy always runs // If no overlap, use the built-in copy:
if offset >= length {
copy(dst[d:d+length], dst[d-offset:])
d += length
continue
}
// Unlike the built-in copy function, this byte-by-byte copy always runs
// forwards, even if the slices overlap. Conceptually, this is: // forwards, even if the slices overlap. Conceptually, this is:
// //
// d += forwardCopy(dst[d:d+length], dst[d-offset:]) // d += forwardCopy(dst[d:d+length], dst[d-offset:])
for end := d + length; d != end; d++ { //
dst[d] = dst[d-offset] // We align the slices into a and b and show the compiler they are the same size.
// This allows the loop to run without bounds checks.
a := dst[d : d+length]
b := dst[d-offset:]
b = b[:len(a)]
for i := range a {
a[i] = b[i]
} }
d += length
} }
if d != len(dst) { if d != len(dst) {
return decodeErrCodeCorrupt return decodeErrCodeCorrupt

View File

@ -15,6 +15,8 @@ import (
// Otherwise, a newly allocated slice will be returned. // Otherwise, a newly allocated slice will be returned.
// //
// The dst and src must not overlap. It is valid to pass a nil dst. // The dst and src must not overlap. It is valid to pass a nil dst.
//
// Encode handles the Snappy block format, not the Snappy stream format.
func Encode(dst, src []byte) []byte { func Encode(dst, src []byte) []byte {
if n := MaxEncodedLen(len(src)); n < 0 { if n := MaxEncodedLen(len(src)); n < 0 {
panic(ErrTooLarge) panic(ErrTooLarge)
@ -139,6 +141,8 @@ func NewBufferedWriter(w io.Writer) *Writer {
} }
// Writer is an io.Writer that can write Snappy-compressed bytes. // Writer is an io.Writer that can write Snappy-compressed bytes.
//
// Writer handles the Snappy stream format, not the Snappy block format.
type Writer struct { type Writer struct {
w io.Writer w io.Writer
err error err error

722
vendor/github.com/golang/snappy/encode_arm64.s generated vendored Normal file
View File

@ -0,0 +1,722 @@
// Copyright 2020 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 !appengine
// +build gc
// +build !noasm
#include "textflag.h"
// The asm code generally follows the pure Go code in encode_other.go, except
// where marked with a "!!!".
// ----------------------------------------------------------------------------
// func emitLiteral(dst, lit []byte) int
//
// All local variables fit into registers. The register allocation:
// - R3 len(lit)
// - R4 n
// - R6 return value
// - R8 &dst[i]
// - R10 &lit[0]
//
// The 32 bytes of stack space is to call runtime·memmove.
//
// The unusual register allocation of local variables, such as R10 for the
// source pointer, matches the allocation used at the call site in encodeBlock,
// which makes it easier to manually inline this function.
TEXT ·emitLiteral(SB), NOSPLIT, $32-56
MOVD dst_base+0(FP), R8
MOVD lit_base+24(FP), R10
MOVD lit_len+32(FP), R3
MOVD R3, R6
MOVW R3, R4
SUBW $1, R4, R4
CMPW $60, R4
BLT oneByte
CMPW $256, R4
BLT twoBytes
threeBytes:
MOVD $0xf4, R2
MOVB R2, 0(R8)
MOVW R4, 1(R8)
ADD $3, R8, R8
ADD $3, R6, R6
B memmove
twoBytes:
MOVD $0xf0, R2
MOVB R2, 0(R8)
MOVB R4, 1(R8)
ADD $2, R8, R8
ADD $2, R6, R6
B memmove
oneByte:
LSLW $2, R4, R4
MOVB R4, 0(R8)
ADD $1, R8, R8
ADD $1, R6, R6
memmove:
MOVD R6, ret+48(FP)
// copy(dst[i:], lit)
//
// This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push
// R8, R10 and R3 as arguments.
MOVD R8, 8(RSP)
MOVD R10, 16(RSP)
MOVD R3, 24(RSP)
CALL runtime·memmove(SB)
RET
// ----------------------------------------------------------------------------
// func emitCopy(dst []byte, offset, length int) int
//
// All local variables fit into registers. The register allocation:
// - R3 length
// - R7 &dst[0]
// - R8 &dst[i]
// - R11 offset
//
// The unusual register allocation of local variables, such as R11 for the
// offset, matches the allocation used at the call site in encodeBlock, which
// makes it easier to manually inline this function.
TEXT ·emitCopy(SB), NOSPLIT, $0-48
MOVD dst_base+0(FP), R8
MOVD R8, R7
MOVD offset+24(FP), R11
MOVD length+32(FP), R3
loop0:
// for length >= 68 { etc }
CMPW $68, R3
BLT step1
// Emit a length 64 copy, encoded as 3 bytes.
MOVD $0xfe, R2
MOVB R2, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
SUB $64, R3, R3
B loop0
step1:
// if length > 64 { etc }
CMP $64, R3
BLE step2
// Emit a length 60 copy, encoded as 3 bytes.
MOVD $0xee, R2
MOVB R2, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
SUB $60, R3, R3
step2:
// if length >= 12 || offset >= 2048 { goto step3 }
CMP $12, R3
BGE step3
CMPW $2048, R11
BGE step3
// Emit the remaining copy, encoded as 2 bytes.
MOVB R11, 1(R8)
LSRW $3, R11, R11
AND $0xe0, R11, R11
SUB $4, R3, R3
LSLW $2, R3
AND $0xff, R3, R3
ORRW R3, R11, R11
ORRW $1, R11, R11
MOVB R11, 0(R8)
ADD $2, R8, R8
// Return the number of bytes written.
SUB R7, R8, R8
MOVD R8, ret+40(FP)
RET
step3:
// Emit the remaining copy, encoded as 3 bytes.
SUB $1, R3, R3
AND $0xff, R3, R3
LSLW $2, R3, R3
ORRW $2, R3, R3
MOVB R3, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
// Return the number of bytes written.
SUB R7, R8, R8
MOVD R8, ret+40(FP)
RET
// ----------------------------------------------------------------------------
// func extendMatch(src []byte, i, j int) int
//
// All local variables fit into registers. The register allocation:
// - R6 &src[0]
// - R7 &src[j]
// - R13 &src[len(src) - 8]
// - R14 &src[len(src)]
// - R15 &src[i]
//
// The unusual register allocation of local variables, such as R15 for a source
// pointer, matches the allocation used at the call site in encodeBlock, which
// makes it easier to manually inline this function.
TEXT ·extendMatch(SB), NOSPLIT, $0-48
MOVD src_base+0(FP), R6
MOVD src_len+8(FP), R14
MOVD i+24(FP), R15
MOVD j+32(FP), R7
ADD R6, R14, R14
ADD R6, R15, R15
ADD R6, R7, R7
MOVD R14, R13
SUB $8, R13, R13
cmp8:
// As long as we are 8 or more bytes before the end of src, we can load and
// compare 8 bytes at a time. If those 8 bytes are equal, repeat.
CMP R13, R7
BHI cmp1
MOVD (R15), R3
MOVD (R7), R4
CMP R4, R3
BNE bsf
ADD $8, R15, R15
ADD $8, R7, R7
B cmp8
bsf:
// If those 8 bytes were not equal, XOR the two 8 byte values, and return
// the index of the first byte that differs.
// RBIT reverses the bit order, then CLZ counts the leading zeros, the
// combination of which finds the least significant bit which is set.
// The arm64 architecture is little-endian, and the shift by 3 converts
// a bit index to a byte index.
EOR R3, R4, R4
RBIT R4, R4
CLZ R4, R4
ADD R4>>3, R7, R7
// Convert from &src[ret] to ret.
SUB R6, R7, R7
MOVD R7, ret+40(FP)
RET
cmp1:
// In src's tail, compare 1 byte at a time.
CMP R7, R14
BLS extendMatchEnd
MOVB (R15), R3
MOVB (R7), R4
CMP R4, R3
BNE extendMatchEnd
ADD $1, R15, R15
ADD $1, R7, R7
B cmp1
extendMatchEnd:
// Convert from &src[ret] to ret.
SUB R6, R7, R7
MOVD R7, ret+40(FP)
RET
// ----------------------------------------------------------------------------
// func encodeBlock(dst, src []byte) (d int)
//
// All local variables fit into registers, other than "var table". The register
// allocation:
// - R3 . .
// - R4 . .
// - R5 64 shift
// - R6 72 &src[0], tableSize
// - R7 80 &src[s]
// - R8 88 &dst[d]
// - R9 96 sLimit
// - R10 . &src[nextEmit]
// - R11 104 prevHash, currHash, nextHash, offset
// - R12 112 &src[base], skip
// - R13 . &src[nextS], &src[len(src) - 8]
// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x
// - R15 120 candidate
// - R16 . hash constant, 0x1e35a7bd
// - R17 . &table
// - . 128 table
//
// The second column (64, 72, etc) is the stack offset to spill the registers
// when calling other functions. We could pack this slightly tighter, but it's
// simpler to have a dedicated spill map independent of the function called.
//
// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An
// extra 64 bytes, to call other functions, and an extra 64 bytes, to spill
// local variables (registers) during calls gives 32768 + 64 + 64 = 32896.
TEXT ·encodeBlock(SB), 0, $32896-56
MOVD dst_base+0(FP), R8
MOVD src_base+24(FP), R7
MOVD src_len+32(FP), R14
// shift, tableSize := uint32(32-8), 1<<8
MOVD $24, R5
MOVD $256, R6
MOVW $0xa7bd, R16
MOVKW $(0x1e35<<16), R16
calcShift:
// for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 {
// shift--
// }
MOVD $16384, R2
CMP R2, R6
BGE varTable
CMP R14, R6
BGE varTable
SUB $1, R5, R5
LSL $1, R6, R6
B calcShift
varTable:
// var table [maxTableSize]uint16
//
// In the asm code, unlike the Go code, we can zero-initialize only the
// first tableSize elements. Each uint16 element is 2 bytes and each
// iterations writes 64 bytes, so we can do only tableSize/32 writes
// instead of the 2048 writes that would zero-initialize all of table's
// 32768 bytes. This clear could overrun the first tableSize elements, but
// it won't overrun the allocated stack size.
ADD $128, RSP, R17
MOVD R17, R4
// !!! R6 = &src[tableSize]
ADD R6<<1, R17, R6
memclr:
STP.P (ZR, ZR), 64(R4)
STP (ZR, ZR), -48(R4)
STP (ZR, ZR), -32(R4)
STP (ZR, ZR), -16(R4)
CMP R4, R6
BHI memclr
// !!! R6 = &src[0]
MOVD R7, R6
// sLimit := len(src) - inputMargin
MOVD R14, R9
SUB $15, R9, R9
// !!! Pre-emptively spill R5, R6 and R9 to the stack. Their values don't
// change for the rest of the function.
MOVD R5, 64(RSP)
MOVD R6, 72(RSP)
MOVD R9, 96(RSP)
// nextEmit := 0
MOVD R6, R10
// s := 1
ADD $1, R7, R7
// nextHash := hash(load32(src, s), shift)
MOVW 0(R7), R11
MULW R16, R11, R11
LSRW R5, R11, R11
outer:
// for { etc }
// skip := 32
MOVD $32, R12
// nextS := s
MOVD R7, R13
// candidate := 0
MOVD $0, R15
inner0:
// for { etc }
// s := nextS
MOVD R13, R7
// bytesBetweenHashLookups := skip >> 5
MOVD R12, R14
LSR $5, R14, R14
// nextS = s + bytesBetweenHashLookups
ADD R14, R13, R13
// skip += bytesBetweenHashLookups
ADD R14, R12, R12
// if nextS > sLimit { goto emitRemainder }
MOVD R13, R3
SUB R6, R3, R3
CMP R9, R3
BHI emitRemainder
// candidate = int(table[nextHash])
MOVHU 0(R17)(R11<<1), R15
// table[nextHash] = uint16(s)
MOVD R7, R3
SUB R6, R3, R3
MOVH R3, 0(R17)(R11<<1)
// nextHash = hash(load32(src, nextS), shift)
MOVW 0(R13), R11
MULW R16, R11
LSRW R5, R11, R11
// if load32(src, s) != load32(src, candidate) { continue } break
MOVW 0(R7), R3
MOVW (R6)(R15), R4
CMPW R4, R3
BNE inner0
fourByteMatch:
// As per the encode_other.go code:
//
// A 4-byte match has been found. We'll later see etc.
// !!! Jump to a fast path for short (<= 16 byte) literals. See the comment
// on inputMargin in encode.go.
MOVD R7, R3
SUB R10, R3, R3
CMP $16, R3
BLE emitLiteralFastPath
// ----------------------------------------
// Begin inline of the emitLiteral call.
//
// d += emitLiteral(dst[d:], src[nextEmit:s])
MOVW R3, R4
SUBW $1, R4, R4
MOVW $60, R2
CMPW R2, R4
BLT inlineEmitLiteralOneByte
MOVW $256, R2
CMPW R2, R4
BLT inlineEmitLiteralTwoBytes
inlineEmitLiteralThreeBytes:
MOVD $0xf4, R1
MOVB R1, 0(R8)
MOVW R4, 1(R8)
ADD $3, R8, R8
B inlineEmitLiteralMemmove
inlineEmitLiteralTwoBytes:
MOVD $0xf0, R1
MOVB R1, 0(R8)
MOVB R4, 1(R8)
ADD $2, R8, R8
B inlineEmitLiteralMemmove
inlineEmitLiteralOneByte:
LSLW $2, R4, R4
MOVB R4, 0(R8)
ADD $1, R8, R8
inlineEmitLiteralMemmove:
// Spill local variables (registers) onto the stack; call; unspill.
//
// copy(dst[i:], lit)
//
// This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push
// R8, R10 and R3 as arguments.
MOVD R8, 8(RSP)
MOVD R10, 16(RSP)
MOVD R3, 24(RSP)
// Finish the "d +=" part of "d += emitLiteral(etc)".
ADD R3, R8, R8
MOVD R7, 80(RSP)
MOVD R8, 88(RSP)
MOVD R15, 120(RSP)
CALL runtime·memmove(SB)
MOVD 64(RSP), R5
MOVD 72(RSP), R6
MOVD 80(RSP), R7
MOVD 88(RSP), R8
MOVD 96(RSP), R9
MOVD 120(RSP), R15
ADD $128, RSP, R17
MOVW $0xa7bd, R16
MOVKW $(0x1e35<<16), R16
B inner1
inlineEmitLiteralEnd:
// End inline of the emitLiteral call.
// ----------------------------------------
emitLiteralFastPath:
// !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2".
MOVB R3, R4
SUBW $1, R4, R4
AND $0xff, R4, R4
LSLW $2, R4, R4
MOVB R4, (R8)
ADD $1, R8, R8
// !!! Implement the copy from lit to dst as a 16-byte load and store.
// (Encode's documentation says that dst and src must not overlap.)
//
// This always copies 16 bytes, instead of only len(lit) bytes, but that's
// OK. Subsequent iterations will fix up the overrun.
//
// Note that on arm64, it is legal and cheap to issue unaligned 8-byte or
// 16-byte loads and stores. This technique probably wouldn't be as
// effective on architectures that are fussier about alignment.
LDP 0(R10), (R0, R1)
STP (R0, R1), 0(R8)
ADD R3, R8, R8
inner1:
// for { etc }
// base := s
MOVD R7, R12
// !!! offset := base - candidate
MOVD R12, R11
SUB R15, R11, R11
SUB R6, R11, R11
// ----------------------------------------
// Begin inline of the extendMatch call.
//
// s = extendMatch(src, candidate+4, s+4)
// !!! R14 = &src[len(src)]
MOVD src_len+32(FP), R14
ADD R6, R14, R14
// !!! R13 = &src[len(src) - 8]
MOVD R14, R13
SUB $8, R13, R13
// !!! R15 = &src[candidate + 4]
ADD $4, R15, R15
ADD R6, R15, R15
// !!! s += 4
ADD $4, R7, R7
inlineExtendMatchCmp8:
// As long as we are 8 or more bytes before the end of src, we can load and
// compare 8 bytes at a time. If those 8 bytes are equal, repeat.
CMP R13, R7
BHI inlineExtendMatchCmp1
MOVD (R15), R3
MOVD (R7), R4
CMP R4, R3
BNE inlineExtendMatchBSF
ADD $8, R15, R15
ADD $8, R7, R7
B inlineExtendMatchCmp8
inlineExtendMatchBSF:
// If those 8 bytes were not equal, XOR the two 8 byte values, and return
// the index of the first byte that differs.
// RBIT reverses the bit order, then CLZ counts the leading zeros, the
// combination of which finds the least significant bit which is set.
// The arm64 architecture is little-endian, and the shift by 3 converts
// a bit index to a byte index.
EOR R3, R4, R4
RBIT R4, R4
CLZ R4, R4
ADD R4>>3, R7, R7
B inlineExtendMatchEnd
inlineExtendMatchCmp1:
// In src's tail, compare 1 byte at a time.
CMP R7, R14
BLS inlineExtendMatchEnd
MOVB (R15), R3
MOVB (R7), R4
CMP R4, R3
BNE inlineExtendMatchEnd
ADD $1, R15, R15
ADD $1, R7, R7
B inlineExtendMatchCmp1
inlineExtendMatchEnd:
// End inline of the extendMatch call.
// ----------------------------------------
// ----------------------------------------
// Begin inline of the emitCopy call.
//
// d += emitCopy(dst[d:], base-candidate, s-base)
// !!! length := s - base
MOVD R7, R3
SUB R12, R3, R3
inlineEmitCopyLoop0:
// for length >= 68 { etc }
MOVW $68, R2
CMPW R2, R3
BLT inlineEmitCopyStep1
// Emit a length 64 copy, encoded as 3 bytes.
MOVD $0xfe, R1
MOVB R1, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
SUBW $64, R3, R3
B inlineEmitCopyLoop0
inlineEmitCopyStep1:
// if length > 64 { etc }
MOVW $64, R2
CMPW R2, R3
BLE inlineEmitCopyStep2
// Emit a length 60 copy, encoded as 3 bytes.
MOVD $0xee, R1
MOVB R1, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
SUBW $60, R3, R3
inlineEmitCopyStep2:
// if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 }
MOVW $12, R2
CMPW R2, R3
BGE inlineEmitCopyStep3
MOVW $2048, R2
CMPW R2, R11
BGE inlineEmitCopyStep3
// Emit the remaining copy, encoded as 2 bytes.
MOVB R11, 1(R8)
LSRW $8, R11, R11
LSLW $5, R11, R11
SUBW $4, R3, R3
AND $0xff, R3, R3
LSLW $2, R3, R3
ORRW R3, R11, R11
ORRW $1, R11, R11
MOVB R11, 0(R8)
ADD $2, R8, R8
B inlineEmitCopyEnd
inlineEmitCopyStep3:
// Emit the remaining copy, encoded as 3 bytes.
SUBW $1, R3, R3
LSLW $2, R3, R3
ORRW $2, R3, R3
MOVB R3, 0(R8)
MOVW R11, 1(R8)
ADD $3, R8, R8
inlineEmitCopyEnd:
// End inline of the emitCopy call.
// ----------------------------------------
// nextEmit = s
MOVD R7, R10
// if s >= sLimit { goto emitRemainder }
MOVD R7, R3
SUB R6, R3, R3
CMP R3, R9
BLS emitRemainder
// As per the encode_other.go code:
//
// We could immediately etc.
// x := load64(src, s-1)
MOVD -1(R7), R14
// prevHash := hash(uint32(x>>0), shift)
MOVW R14, R11
MULW R16, R11, R11
LSRW R5, R11, R11
// table[prevHash] = uint16(s-1)
MOVD R7, R3
SUB R6, R3, R3
SUB $1, R3, R3
MOVHU R3, 0(R17)(R11<<1)
// currHash := hash(uint32(x>>8), shift)
LSR $8, R14, R14
MOVW R14, R11
MULW R16, R11, R11
LSRW R5, R11, R11
// candidate = int(table[currHash])
MOVHU 0(R17)(R11<<1), R15
// table[currHash] = uint16(s)
ADD $1, R3, R3
MOVHU R3, 0(R17)(R11<<1)
// if uint32(x>>8) == load32(src, candidate) { continue }
MOVW (R6)(R15), R4
CMPW R4, R14
BEQ inner1
// nextHash = hash(uint32(x>>16), shift)
LSR $8, R14, R14
MOVW R14, R11
MULW R16, R11, R11
LSRW R5, R11, R11
// s++
ADD $1, R7, R7
// break out of the inner1 for loop, i.e. continue the outer loop.
B outer
emitRemainder:
// if nextEmit < len(src) { etc }
MOVD src_len+32(FP), R3
ADD R6, R3, R3
CMP R3, R10
BEQ encodeBlockEnd
// d += emitLiteral(dst[d:], src[nextEmit:])
//
// Push args.
MOVD R8, 8(RSP)
MOVD $0, 16(RSP) // Unnecessary, as the callee ignores it, but conservative.
MOVD $0, 24(RSP) // Unnecessary, as the callee ignores it, but conservative.
MOVD R10, 32(RSP)
SUB R10, R3, R3
MOVD R3, 40(RSP)
MOVD R3, 48(RSP) // Unnecessary, as the callee ignores it, but conservative.
// Spill local variables (registers) onto the stack; call; unspill.
MOVD R8, 88(RSP)
CALL ·emitLiteral(SB)
MOVD 88(RSP), R8
// Finish the "d +=" part of "d += emitLiteral(etc)".
MOVD 56(RSP), R1
ADD R1, R8, R8
encodeBlockEnd:
MOVD dst_base+0(FP), R3
SUB R3, R8, R8
MOVD R8, d+48(FP)
RET

View File

@ -5,6 +5,7 @@
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !noasm // +build !noasm
// +build amd64 arm64
package snappy package snappy

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 appengine !gc noasm // +build !amd64,!arm64 appengine !gc noasm
package snappy package snappy

1
vendor/github.com/golang/snappy/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/golang/snappy

View File

@ -1,17 +0,0 @@
language: go
sudo: false
go:
- "1.12.x"
- "1.13.x"
- tip
env:
- GO111MODULE=on
script:
- go generate ./... && test `git ls-files --modified | wc -l` = 0
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,7 +1,7 @@
# Makefile for releasing. # Makefile for releasing.
# #
# The release is controlled from version.go. The version found there is # The release is controlled from version.go. The version found there is
# used to tag the git repo, we're not building any artifects so there is nothing # used to tag the git repo, we're not building any artifacts so there is nothing
# to upload to github. # to upload to github.
# #
# * Up the version in version.go # * Up the version in version.go

View File

@ -26,8 +26,8 @@ avoiding breaking changes wherever reasonable. We support the last two versions
A not-so-up-to-date-list-that-may-be-actually-current: A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/coredns/coredns * https://github.com/coredns/coredns
* https://cloudflare.com
* https://github.com/abh/geodns * https://github.com/abh/geodns
* https://github.com/baidu/bfe
* http://www.statdns.com/ * http://www.statdns.com/
* http://www.dnsinspect.com/ * http://www.dnsinspect.com/
* https://github.com/chuangbo/jianbing-dictionary-dns * https://github.com/chuangbo/jianbing-dictionary-dns
@ -41,11 +41,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/StalkR/dns-reverse-proxy * https://github.com/StalkR/dns-reverse-proxy
* 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://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://github.com/miekg/unbound * https://github.com/miekg/unbound
* https://github.com/miekg/exdns * https://github.com/miekg/exdns
* https://dnslookup.org * https://dnslookup.org
@ -54,22 +52,28 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/mehrdadrad/mylg * https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness * https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns * https://github.com/fffaraz/microdns
* http://kelda.io
* https://github.com/ipdcode/hades <https://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/
* https://dns.apebits.com
* https://github.com/oif/apex * https://github.com/oif/apex
* https://github.com/jedisct1/dnscrypt-proxy * https://github.com/jedisct1/dnscrypt-proxy
* https://github.com/jedisct1/rpdns * https://github.com/jedisct1/rpdns
* https://github.com/xor-gate/sshfp * https://github.com/xor-gate/sshfp
* 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://render.com * https://render.com
* https://github.com/peterzen/goresolver * https://github.com/peterzen/goresolver
* https://github.com/folbricht/routedns * https://github.com/folbricht/routedns
* https://domainr.com/
* https://zonedb.org/
* https://router7.org/
* https://github.com/fortio/dnsping
* https://github.com/Luzilla/dnsbl_exporter
* https://github.com/bodgit/tsig
* https://github.com/v2fly/v2ray-core (test only)
* https://kuma.io/
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
@ -166,6 +170,9 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 7873 - Domain Name System (DNS) Cookies * 7873 - Domain Name System (DNS) Cookies
* 8080 - EdDSA for DNSSEC * 8080 - EdDSA for DNSSEC
* 8499 - DNS Terminology * 8499 - DNS Terminology
* 8659 - DNS Certification Authority Authorization (CAA) Resource Record
* 8914 - Extended DNS Errors
* 8976 - Message Digest for DNS Zones (ZONEMD RR)
## Loosely Based Upon ## Loosely Based Upon

View File

@ -25,6 +25,7 @@ var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
// MsgAcceptAction represents the action to be taken. // MsgAcceptAction represents the action to be taken.
type MsgAcceptAction int type MsgAcceptAction int
// Allowed returned values from a MsgAcceptFunc.
const ( const (
MsgAccept MsgAcceptAction = iota // Accept the message MsgAccept MsgAcceptAction = iota // Accept the message
MsgReject // Reject the message with a RcodeFormatError MsgReject // Reject the message with a RcodeFormatError

View File

@ -23,6 +23,7 @@ type Conn struct {
net.Conn // a net.Conn holding the connection net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messages UDPSize uint16 // minimum receive buffer for UDP messages
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
tsigRequestMAC string tsigRequestMAC string
} }
@ -34,12 +35,13 @@ type Client struct {
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout, // Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and // WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext) // Client.Dialer) or context.Context.Deadline (see ExchangeContext)
Timeout time.Duration Timeout time.Duration
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero 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
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)
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
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
} }
@ -106,7 +108,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
conn.UDPSize = c.UDPSize
return conn, nil return conn, nil
} }
@ -125,14 +127,36 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// To specify a local address or a timeout, the caller has to set the `Client.Dialer` // To specify a local address or a timeout, the caller has to set the `Client.Dialer`
// 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) {
co, err := c.Dial(address)
if err != nil {
return nil, 0, err
}
defer co.Close()
return c.ExchangeWithConn(m, co)
}
// ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection
// that will be used instead of creating a new one.
// Usage pattern with a *dns.Client:
// c := new(dns.Client)
// // connection management logic goes here
//
// conn := c.Dial(address)
// in, rtt, err := c.ExchangeWithConn(message, conn)
//
// This allows users of the library to implement their own connection management,
// as opposed to Exchange, which will always use new connections and incur the added overhead
// that entails when using "tcp" and especially "tcp-tls" clients.
func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight { if !c.SingleInflight {
return c.exchange(m, address) return c.exchange(m, conn)
} }
q := m.Question[0] q := m.Question[0]
key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass) key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) { r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
return c.exchange(m, address) return c.exchange(m, conn)
}) })
if r != nil && shared { if r != nil && shared {
r = r.Copy() r = r.Copy()
@ -141,15 +165,7 @@ func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, er
return r, rtt, err return r, rtt, err
} }
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) { func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
var co *Conn
co, err = c.Dial(a)
if err != nil {
return nil, 0, err
}
defer co.Close()
opt := m.IsEdns0() opt := m.IsEdns0()
// If EDNS0 is used use that for size. // If EDNS0 is used use that for size.
@ -161,7 +177,7 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
co.UDPSize = c.UDPSize co.UDPSize = c.UDPSize
} }
co.TsigSecret = c.TsigSecret co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider
t := time.Now() t := time.Now()
// write with the appropriate write timeout // write with the appropriate write timeout
co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout()))) co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout())))
@ -170,9 +186,20 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
} }
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout()))) co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
r, err = co.ReadMsg() if _, ok := co.Conn.(net.PacketConn); ok {
if err == nil && r.Id != m.Id { for {
err = ErrId r, err = co.ReadMsg()
// Ignore replies with mismatched IDs because they might be
// responses to earlier queries that timed out.
if err != nil || r.Id == m.Id {
break
}
}
} else {
r, err = co.ReadMsg()
if err == nil && r.Id != m.Id {
err = ErrId
}
} }
rtt = time.Since(t) rtt = time.Since(t)
return r, rtt, err return r, rtt, err
@ -197,11 +224,15 @@ func (co *Conn) ReadMsg() (*Msg, error) {
return m, err return m, err
} }
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok { if co.TsigProvider != nil {
return m, ErrSecret err = tsigVerifyProvider(p, co.TsigProvider, co.tsigRequestMAC, false)
} else {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
return m, ErrSecret
}
// Need to work on the original message p, as that was used to calculate the tsig.
err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
} }
// Need to work on the original message p, as that was used to calculate the tsig.
err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
} }
return m, err return m, err
} }
@ -279,10 +310,14 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
var out []byte var out []byte
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
mac := "" mac := ""
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok { if co.TsigProvider != nil {
return ErrSecret out, mac, err = tsigGenerateProvider(m, co.TsigProvider, co.tsigRequestMAC, false)
} else {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
return ErrSecret
}
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
} }
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
// Set for the next read, although only used in zone transfers // Set for the next read, although only used in zone transfers
co.tsigRequestMAC = mac co.tsigRequestMAC = mac
} else { } else {
@ -305,11 +340,10 @@ func (co *Conn) Write(p []byte) (int, error) {
return co.Conn.Write(p) return co.Conn.Write(p)
} }
l := make([]byte, 2) msg := make([]byte, 2+len(p))
binary.BigEndian.PutUint16(l, uint16(len(p))) binary.BigEndian.PutUint16(msg, uint16(len(p)))
copy(msg[2:], p)
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn) return co.Conn.Write(msg)
return int(n), err
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
@ -345,7 +379,7 @@ func Dial(network, address string) (conn *Conn, err error) {
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) { func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
client := Client{Net: "udp"} client := Client{Net: "udp"}
r, _, err = client.ExchangeContext(ctx, m, a) r, _, err = client.ExchangeContext(ctx, m, a)
// ignorint rtt to leave the original ExchangeContext API unchanged, but // ignoring rtt to leave the original ExchangeContext API unchanged, but
// this function will go away // this function will go away
return r, err return r, err
} }

View File

@ -105,7 +105,7 @@ func (dns *Msg) SetAxfr(z string) *Msg {
// SetTsig appends a TSIG RR to the message. // SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the // This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send. // additional section. The TSIG is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg { func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
t := new(TSIG) t := new(TSIG)
t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0} t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
@ -317,6 +317,12 @@ func Fqdn(s string) string {
return s + "." return s + "."
} }
// CanonicalName returns the domain name in canonical form. A name in canonical
// form is lowercase and fully qualified. See Section 6.2 in RFC 4034.
func CanonicalName(s string) string {
return strings.ToLower(Fqdn(s))
}
// Copied from the official Go code. // Copied from the official Go code.
// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP // ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
@ -343,10 +349,7 @@ func ReverseAddr(addr string) (arpa string, err error) {
// 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]
buf = append(buf, hexDigit[v&0xF]) buf = append(buf, hexDigit[v&0xF], '.', hexDigit[v>>4], '.')
buf = append(buf, '.')
buf = append(buf, hexDigit[v>>4])
buf = append(buf, '.')
} }
// Append "ip6.arpa." and return (buf already has the final .) // Append "ip6.arpa." and return (buf already has the final .)
buf = append(buf, "ip6.arpa."...) buf = append(buf, "ip6.arpa."...)
@ -364,7 +367,7 @@ func (t Type) String() string {
// String returns the string representation for the class c. // String returns the string representation for the class c.
func (c Class) String() string { func (c Class) String() string {
if s, ok := ClassToString[uint16(c)]; ok { if s, ok := ClassToString[uint16(c)]; ok {
// Only emit mnemonics when they are unambiguous, specically ANY is in both. // Only emit mnemonics when they are unambiguous, specially ANY is in both.
if _, ok := StringToType[s]; !ok { if _, ok := StringToType[s]; !ok {
return s return s
} }

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

@ -1,6 +1,9 @@
package dns package dns
import "strconv" import (
"encoding/hex"
"strconv"
)
const ( const (
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
@ -111,7 +114,7 @@ func (h *RR_Header) parse(c *zlexer, origin string) *ParseError {
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597. // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
func (rr *RFC3597) ToRFC3597(r RR) error { func (rr *RFC3597) ToRFC3597(r RR) error {
buf := make([]byte, Len(r)*2) buf := make([]byte, Len(r))
headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false) headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
if err != nil { if err != nil {
return err return err
@ -126,9 +129,30 @@ func (rr *RFC3597) ToRFC3597(r RR) error {
} }
_, err = rr.unpack(buf, headerEnd) _, err = rr.unpack(buf, headerEnd)
return err
}
// fromRFC3597 converts an unknown RR representation from RFC 3597 to the known RR type.
func (rr *RFC3597) fromRFC3597(r RR) error {
hdr := r.Header()
*hdr = rr.Hdr
// Can't overflow uint16 as the length of Rdata is validated in (*RFC3597).parse.
// We can only get here when rr was constructed with that method.
hdr.Rdlength = uint16(hex.DecodedLen(len(rr.Rdata)))
if noRdata(*hdr) {
// Dynamic update.
return nil
}
// rr.pack requires an extra allocation and a copy so we just decode Rdata
// manually, it's simpler anyway.
msg, err := hex.DecodeString(rr.Rdata)
if err != nil { if err != nil {
return err return err
} }
return nil _, err = r.unpack(msg, 0)
return err
} }

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

@ -3,15 +3,14 @@ package dns
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic" "crypto/elliptic"
_ "crypto/md5"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
_ "crypto/sha1" _ "crypto/sha1" // need its init function
_ "crypto/sha256" _ "crypto/sha256" // need its init function
_ "crypto/sha512" _ "crypto/sha512" // need its init function
"encoding/asn1" "encoding/asn1"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
@ -19,8 +18,6 @@ import (
"sort" "sort"
"strings" "strings"
"time" "time"
"golang.org/x/crypto/ed25519"
) )
// DNSSEC encryption algorithm codes. // DNSSEC encryption algorithm codes.
@ -200,7 +197,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
wire = wire[:n] wire = wire[:n]
owner := make([]byte, 255) owner := make([]byte, 255)
off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false) off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false)
if err1 != nil { if err1 != nil {
return nil return nil
} }
@ -285,7 +282,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
sigwire.Inception = rr.Inception sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag sigwire.KeyTag = rr.KeyTag
// For signing, lowercase this name // For signing, lowercase this name
sigwire.SignerName = strings.ToLower(rr.SignerName) sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob // Create the desired binary blob
signdata := make([]byte, DefaultMsgSize) signdata := make([]byte, DefaultMsgSize)
@ -318,6 +315,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
return nil
case RSAMD5, DSA, DSANSEC3SHA1: case RSAMD5, DSA, DSANSEC3SHA1:
// See RFC 6944. // See RFC 6944.
return ErrAlg return ErrAlg
@ -332,9 +330,8 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
return nil
} }
return nil
} }
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) { func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
@ -346,7 +343,6 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
switch alg { switch alg {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
return signature, nil return signature, nil
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256, ECDSAP384SHA384:
ecdsaSignature := &struct { ecdsaSignature := &struct {
R, S *big.Int R, S *big.Int
@ -366,25 +362,18 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
signature := intToBytes(ecdsaSignature.R, intlen) signature := intToBytes(ecdsaSignature.R, intlen)
signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...) signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
return signature, nil return signature, nil
// There is no defined interface for what a DSA backed crypto.Signer returns
case DSA, DSANSEC3SHA1:
// t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
// signature := []byte{byte(t)}
// signature = append(signature, intToBytes(r1, 20)...)
// signature = append(signature, intToBytes(s1, 20)...)
// rr.Signature = signature
case ED25519: case ED25519:
return signature, nil return signature, nil
default:
return nil, ErrAlg
} }
return nil, ErrAlg
} }
// Verify validates an RRSet with the signature and key. This is only the // Verify validates an RRSet with the signature and key. This is only the
// cryptographic test, the signature validity period must be checked separately. // cryptographic test, the signature validity period must be checked separately.
// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work. // This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
// It also checks that the Zone Key bit (RFC 4034 2.1.1) is set on the DNSKEY
// and that the Protocol field is set to 3 (RFC 4034 2.1.2).
func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
// First the easy checks // First the easy checks
if !IsRRset(rrset) { if !IsRRset(rrset) {
@ -405,6 +394,12 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if k.Protocol != 3 { if k.Protocol != 3 {
return ErrKey return ErrKey
} }
// RFC 4034 2.1.1 If bit 7 has value 0, then the DNSKEY record holds some
// other type of DNS public key and MUST NOT be used to verify RRSIGs that
// cover RRsets.
if k.Flags&ZONE == 0 {
return ErrKey
}
// 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
@ -423,7 +418,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
sigwire.Expiration = rr.Expiration sigwire.Expiration = rr.Expiration
sigwire.Inception = rr.Inception sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag sigwire.KeyTag = rr.KeyTag
sigwire.SignerName = strings.ToLower(rr.SignerName) sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob // Create the desired binary blob
signeddata := make([]byte, DefaultMsgSize) signeddata := make([]byte, DefaultMsgSize)
n, err := packSigWire(sigwire, signeddata) n, err := packSigWire(sigwire, signeddata)
@ -448,7 +443,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
} }
switch rr.Algorithm { switch rr.Algorithm {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere?? // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
pubkey := k.publicKeyRSA() // Get the key pubkey := k.publicKeyRSA() // Get the key
if pubkey == nil { if pubkey == nil {
@ -512,7 +507,7 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
return ti <= utc && utc <= te return ti <= utc && utc <= te
} }
// Return the signatures base64 encodedig sigdata as a byte slice. // Return the signatures base64 encoding sigdata as a byte slice.
func (rr *RRSIG) sigBuf() []byte { func (rr *RRSIG) sigBuf() []byte {
sigbuf, err := fromBase64([]byte(rr.Signature)) sigbuf, err := fromBase64([]byte(rr.Signature))
if err != nil { if err != nil {
@ -600,30 +595,6 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
return pubkey return pubkey
} }
func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
keybuf, err := fromBase64([]byte(k.PublicKey))
if err != nil {
return nil
}
if len(keybuf) < 22 {
return nil
}
t, keybuf := int(keybuf[0]), keybuf[1:]
size := 64 + t*8
q, keybuf := keybuf[:20], keybuf[20:]
if len(keybuf) != 3*size {
return nil
}
p, keybuf := keybuf[:size], keybuf[size:]
g, y := keybuf[:size], keybuf[size:]
pubkey := new(dsa.PublicKey)
pubkey.Parameters.Q = new(big.Int).SetBytes(q)
pubkey.Parameters.P = new(big.Int).SetBytes(p)
pubkey.Parameters.G = new(big.Int).SetBytes(g)
pubkey.Y = new(big.Int).SetBytes(y)
return pubkey
}
func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey { func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
keybuf, err := fromBase64([]byte(k.PublicKey)) keybuf, err := fromBase64([]byte(k.PublicKey))
if err != nil { if err != nil {
@ -659,7 +630,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
h.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
h.Name = strings.ToLower(h.Name) h.Name = CanonicalName(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,
@ -672,49 +643,49 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
// conversion. // conversion.
switch x := r1.(type) { switch x := r1.(type) {
case *NS: case *NS:
x.Ns = strings.ToLower(x.Ns) x.Ns = CanonicalName(x.Ns)
case *MD: case *MD:
x.Md = strings.ToLower(x.Md) x.Md = CanonicalName(x.Md)
case *MF: case *MF:
x.Mf = strings.ToLower(x.Mf) x.Mf = CanonicalName(x.Mf)
case *CNAME: case *CNAME:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
case *SOA: case *SOA:
x.Ns = strings.ToLower(x.Ns) x.Ns = CanonicalName(x.Ns)
x.Mbox = strings.ToLower(x.Mbox) x.Mbox = CanonicalName(x.Mbox)
case *MB: case *MB:
x.Mb = strings.ToLower(x.Mb) x.Mb = CanonicalName(x.Mb)
case *MG: case *MG:
x.Mg = strings.ToLower(x.Mg) x.Mg = CanonicalName(x.Mg)
case *MR: case *MR:
x.Mr = strings.ToLower(x.Mr) x.Mr = CanonicalName(x.Mr)
case *PTR: case *PTR:
x.Ptr = strings.ToLower(x.Ptr) x.Ptr = CanonicalName(x.Ptr)
case *MINFO: case *MINFO:
x.Rmail = strings.ToLower(x.Rmail) x.Rmail = CanonicalName(x.Rmail)
x.Email = strings.ToLower(x.Email) x.Email = CanonicalName(x.Email)
case *MX: case *MX:
x.Mx = strings.ToLower(x.Mx) x.Mx = CanonicalName(x.Mx)
case *RP: case *RP:
x.Mbox = strings.ToLower(x.Mbox) x.Mbox = CanonicalName(x.Mbox)
x.Txt = strings.ToLower(x.Txt) x.Txt = CanonicalName(x.Txt)
case *AFSDB: case *AFSDB:
x.Hostname = strings.ToLower(x.Hostname) x.Hostname = CanonicalName(x.Hostname)
case *RT: case *RT:
x.Host = strings.ToLower(x.Host) x.Host = CanonicalName(x.Host)
case *SIG: case *SIG:
x.SignerName = strings.ToLower(x.SignerName) x.SignerName = CanonicalName(x.SignerName)
case *PX: case *PX:
x.Map822 = strings.ToLower(x.Map822) x.Map822 = CanonicalName(x.Map822)
x.Mapx400 = strings.ToLower(x.Mapx400) x.Mapx400 = CanonicalName(x.Mapx400)
case *NAPTR: case *NAPTR:
x.Replacement = strings.ToLower(x.Replacement) x.Replacement = CanonicalName(x.Replacement)
case *KX: case *KX:
x.Exchanger = strings.ToLower(x.Exchanger) x.Exchanger = CanonicalName(x.Exchanger)
case *SRV: case *SRV:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
case *DNAME: case *DNAME:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
} }
// 6.2. Canonical RR Form. (5) - origTTL // 6.2. Canonical RR Form. (5) - origTTL
wire := make([]byte, Len(r1)+1) // +1 to be safe(r) wire := make([]byte, Len(r1)+1) // +1 to be safe(r)

View File

@ -3,12 +3,11 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"math/big" "math/big"
"golang.org/x/crypto/ed25519"
) )
// Generate generates a DNSKEY of the given bit size. // Generate generates a DNSKEY of the given bit size.
@ -19,8 +18,6 @@ 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 RSAMD5, DSA, DSANSEC3SHA1:
return nil, ErrAlg
case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1: case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
if bits < 512 || bits > 4096 { if bits < 512 || bits > 4096 {
return nil, ErrKeySize return nil, ErrKeySize
@ -41,6 +38,8 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
if bits != 256 { if bits != 256 {
return nil, ErrKeySize return nil, ErrKeySize
} }
default:
return nil, ErrAlg
} }
switch k.Algorithm { switch k.Algorithm {

View File

@ -4,13 +4,12 @@ import (
"bufio" "bufio"
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa" "crypto/rsa"
"io" "io"
"math/big" "math/big"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/crypto/ed25519"
) )
// NewPrivateKey returns a PrivateKey by parsing the string s. // NewPrivateKey returns a PrivateKey by parsing the string s.
@ -43,15 +42,7 @@ 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 RSAMD5, DSA, DSANSEC3SHA1: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
return nil, ErrAlg
case RSASHA1:
fallthrough
case RSASHA1NSEC3SHA1:
fallthrough
case RSASHA256:
fallthrough
case RSASHA512:
priv, err := readPrivateKeyRSA(m) priv, err := readPrivateKeyRSA(m)
if err != nil { if err != nil {
return nil, err return nil, err
@ -62,11 +53,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
} }
priv.PublicKey = *pub priv.PublicKey = *pub
return priv, nil return priv, nil
case ECCGOST: case ECDSAP256SHA256, ECDSAP384SHA384:
return nil, ErrPrivKey
case ECDSAP256SHA256:
fallthrough
case ECDSAP384SHA384:
priv, err := readPrivateKeyECDSA(m) priv, err := readPrivateKeyECDSA(m)
if err != nil { if err != nil {
return nil, err return nil, err
@ -80,7 +67,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
case ED25519: case ED25519:
return readPrivateKeyED25519(m) return readPrivateKeyED25519(m)
default: default:
return nil, ErrPrivKey return nil, ErrAlg
} }
} }

View File

@ -2,13 +2,11 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa" "crypto/rsa"
"math/big" "math/big"
"strconv" "strconv"
"golang.org/x/crypto/ed25519"
) )
const format = "Private-key-format: v1.3\n" const format = "Private-key-format: v1.3\n"
@ -17,8 +15,8 @@ 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.
// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey // It supports *rsa.PrivateKey, *ecdsa.PrivateKey and ed25519.PrivateKey.
func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string { func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
algorithm := strconv.Itoa(int(r.Algorithm)) algorithm := strconv.Itoa(int(r.Algorithm))
algorithm += " (" + AlgorithmToString[r.Algorithm] + ")" algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
@ -67,21 +65,6 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
"Algorithm: " + algorithm + "\n" + "Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n" "PrivateKey: " + private + "\n"
case *dsa.PrivateKey:
T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
priv := toBase64(intToBytes(p.X, 20))
pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
return format +
"Algorithm: " + algorithm + "\n" +
"Prime(p): " + prime + "\n" +
"Subprime(q): " + subprime + "\n" +
"Base(g): " + base + "\n" +
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
case ed25519.PrivateKey: case ed25519.PrivateKey:
private := toBase64(p.Seed()) private := toBase64(p.Seed())
return format + return format +

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

@ -159,7 +159,7 @@ shows the options you have and what functions to call.
TRANSACTION SIGNATURE TRANSACTION SIGNATURE
An TSIG or transaction signature adds a HMAC TSIG record to each message sent. An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512. The supported algorithms include: HmacSHA1, HmacSHA256 and HmacSHA512.
Basic use pattern when querying with a TSIG name "axfr." (note that these key names Basic use pattern when querying with a TSIG name "axfr." (note that these key names
must be fully qualified - as they are domain names) and the base64 secret must be fully qualified - as they are domain names) and the base64 secret
@ -174,7 +174,7 @@ changes to the RRset after calling SetTsig() the signature will be incorrect.
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
m := new(dns.Msg) m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX) m.SetQuestion("miek.nl.", dns.TypeMX)
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix())
... ...
// When sending the TSIG RR is calculated and filled in before sending // When sending the TSIG RR is calculated and filled in before sending
@ -187,13 +187,37 @@ request an AXFR for miek.nl. with TSIG key named "axfr." and secret
m := new(dns.Msg) m := new(dns.Msg)
t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
m.SetAxfr("miek.nl.") m.SetAxfr("miek.nl.")
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix())
c, err := t.In(m, "176.58.119.54:53") c, err := t.In(m, "176.58.119.54:53")
for r := range c { ... } for r := range c { ... }
You can now read the records from the transfer as they come in. Each envelope You can now read the records from the transfer as they come in. Each envelope
is checked with TSIG. If something is not correct an error is returned. is checked with TSIG. If something is not correct an error is returned.
A custom TSIG implementation can be used. This requires additional code to
perform any session establishment and signature generation/verification. The
client must be configured with an implementation of the TsigProvider interface:
type Provider struct{}
func (*Provider) Generate(msg []byte, tsig *dns.TSIG) ([]byte, error) {
// Use tsig.Hdr.Name and tsig.Algorithm in your code to
// generate the MAC using msg as the payload.
}
func (*Provider) Verify(msg []byte, tsig *dns.TSIG) error {
// Use tsig.Hdr.Name and tsig.Algorithm in your code to verify
// that msg matches the value in tsig.MAC.
}
c := new(dns.Client)
c.TsigProvider = new(Provider)
m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX)
m.SetTsig(keyname, dns.HmacSHA256, 300, time.Now().Unix())
...
// TSIG RR is calculated by calling your Generate method
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.
server := &dns.Server{Addr: ":53", Net: "udp"} server := &dns.Server{Addr: ":53", Net: "udp"}
@ -207,9 +231,9 @@ Basic use pattern validating and replying to a message that has TSIG set.
if r.IsTsig() != nil { if r.IsTsig() != nil {
if w.TsigStatus() == nil { if w.TsigStatus() == nil {
// *Msg r has an TSIG record and it was validated // *Msg r has an TSIG record and it was validated
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix())
} else { } else {
// *Msg r has an TSIG records and it was not valided // *Msg r has an TSIG records and it was not validated
} }
} }
w.WriteMsg(m) w.WriteMsg(m)
@ -260,7 +284,7 @@ From RFC 2931:
on requests and responses, and protection of the overall integrity of a response. on requests and responses, and protection of the overall integrity of a response.
It works like TSIG, except that SIG(0) uses public key cryptography, instead of It works like TSIG, except that SIG(0) uses public key cryptography, instead of
the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256, the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256,
ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512. ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
Signing subsequent messages in multi-message sessions is not implemented. Signing subsequent messages in multi-message sessions is not implemented.

View File

@ -3,9 +3,8 @@ package dns
//go:generate go run duplicate_generate.go //go:generate go run duplicate_generate.go
// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL. // IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
// So this means the header data is equal *and* the RDATA is the same. Return true // So this means the header data is equal *and* the RDATA is the same. Returns true
// is so, otherwise false. // if so, otherwise false. It's a protocol violation to have identical RRs in a message.
// It's a protocol violation to have identical RRs in a message.
func IsDuplicate(r1, r2 RR) bool { func IsDuplicate(r1, r2 RR) bool {
// Check whether the record header is identical. // Check whether the record header is identical.
if !r1.Header().isDuplicate(r2.Header()) { if !r1.Header().isDuplicate(r2.Header()) {

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

@ -22,11 +22,47 @@ const (
EDNS0COOKIE = 0xa // EDNS0 Cookie EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828) EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830) EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
EDNS0EDE = 0xf // EDNS0 extended DNS errors (See RFC 8914)
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891) EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891) EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
_DO = 1 << 15 // DNSSEC OK _DO = 1 << 15 // DNSSEC OK
) )
// makeDataOpt is used to unpack the EDNS0 option(s) from a message.
func makeDataOpt(code uint16) EDNS0 {
// All the EDNS0.* constants above need to be in this switch.
switch code {
case EDNS0LLQ:
return new(EDNS0_LLQ)
case EDNS0UL:
return new(EDNS0_UL)
case EDNS0NSID:
return new(EDNS0_NSID)
case EDNS0DAU:
return new(EDNS0_DAU)
case EDNS0DHU:
return new(EDNS0_DHU)
case EDNS0N3U:
return new(EDNS0_N3U)
case EDNS0SUBNET:
return new(EDNS0_SUBNET)
case EDNS0EXPIRE:
return new(EDNS0_EXPIRE)
case EDNS0COOKIE:
return new(EDNS0_COOKIE)
case EDNS0TCPKEEPALIVE:
return new(EDNS0_TCP_KEEPALIVE)
case EDNS0PADDING:
return new(EDNS0_PADDING)
case EDNS0EDE:
return new(EDNS0_EDE)
default:
e := new(EDNS0_LOCAL)
e.Code = code
return e
}
}
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information. // OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
// See RFC 6891. // See RFC 6891.
type OPT struct { type OPT struct {
@ -73,6 +109,8 @@ func (rr *OPT) String() string {
s += "\n; LOCAL OPT: " + o.String() s += "\n; LOCAL OPT: " + o.String()
case *EDNS0_PADDING: case *EDNS0_PADDING:
s += "\n; PADDING: " + o.String() s += "\n; PADDING: " + o.String()
case *EDNS0_EDE:
s += "\n; EDE: " + o.String()
} }
} }
return s return s
@ -88,11 +126,11 @@ func (rr *OPT) len(off int, compression map[string]struct{}) int {
return l return l
} }
func (rr *OPT) parse(c *zlexer, origin string) *ParseError { func (*OPT) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on OPT") return &ParseError{err: "OPT records do not have a presentation format"}
} }
func (r1 *OPT) isDuplicate(r2 RR) bool { return false } func (rr *OPT) isDuplicate(r2 RR) bool { return false }
// return the old value -> delete SetVersion? // return the old value -> delete SetVersion?
@ -148,6 +186,16 @@ func (rr *OPT) SetDo(do ...bool) {
} }
} }
// Z returns the Z part of the OPT RR as a uint16 with only the 15 least significant bits used.
func (rr *OPT) Z() uint16 {
return uint16(rr.Hdr.Ttl & 0x7FFF)
}
// SetZ sets the Z part of the OPT RR, note only the 15 least significant bits of z are used.
func (rr *OPT) SetZ(z uint16) {
rr.Hdr.Ttl = rr.Hdr.Ttl&^0x7FFF | uint32(z&0x7FFF)
}
// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it. // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
type EDNS0 interface { type EDNS0 interface {
// Option returns the option code for the option. // Option returns the option code for the option.
@ -452,7 +500,7 @@ func (e *EDNS0_LLQ) copy() EDNS0 {
return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife} 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_DAU implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
type EDNS0_DAU struct { type EDNS0_DAU struct {
Code uint16 // Always EDNS0DAU Code uint16 // Always EDNS0DAU
AlgCode []uint8 AlgCode []uint8
@ -525,7 +573,7 @@ func (e *EDNS0_N3U) String() string {
} }
func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} } 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 implements the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct { type EDNS0_EXPIRE struct {
Code uint16 // Always EDNS0EXPIRE Code uint16 // Always EDNS0EXPIRE
Expire uint32 Expire uint32
@ -673,3 +721,101 @@ func (e *EDNS0_PADDING) copy() EDNS0 {
copy(b, e.Padding) copy(b, e.Padding)
return &EDNS0_PADDING{b} return &EDNS0_PADDING{b}
} }
// Extended DNS Error Codes (RFC 8914).
const (
ExtendedErrorCodeOther uint16 = iota
ExtendedErrorCodeUnsupportedDNSKEYAlgorithm
ExtendedErrorCodeUnsupportedDSDigestType
ExtendedErrorCodeStaleAnswer
ExtendedErrorCodeForgedAnswer
ExtendedErrorCodeDNSSECIndeterminate
ExtendedErrorCodeDNSBogus
ExtendedErrorCodeSignatureExpired
ExtendedErrorCodeSignatureNotYetValid
ExtendedErrorCodeDNSKEYMissing
ExtendedErrorCodeRRSIGsMissing
ExtendedErrorCodeNoZoneKeyBitSet
ExtendedErrorCodeNSECMissing
ExtendedErrorCodeCachedError
ExtendedErrorCodeNotReady
ExtendedErrorCodeBlocked
ExtendedErrorCodeCensored
ExtendedErrorCodeFiltered
ExtendedErrorCodeProhibited
ExtendedErrorCodeStaleNXDOMAINAnswer
ExtendedErrorCodeNotAuthoritative
ExtendedErrorCodeNotSupported
ExtendedErrorCodeNoReachableAuthority
ExtendedErrorCodeNetworkError
ExtendedErrorCodeInvalidData
)
// ExtendedErrorCodeToString maps extended error info codes to a human readable
// description.
var ExtendedErrorCodeToString = map[uint16]string{
ExtendedErrorCodeOther: "Other",
ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm",
ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type",
ExtendedErrorCodeStaleAnswer: "Stale Answer",
ExtendedErrorCodeForgedAnswer: "Forged Answer",
ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate",
ExtendedErrorCodeDNSBogus: "DNSSEC Bogus",
ExtendedErrorCodeSignatureExpired: "Signature Expired",
ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid",
ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing",
ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing",
ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set",
ExtendedErrorCodeNSECMissing: "NSEC Missing",
ExtendedErrorCodeCachedError: "Cached Error",
ExtendedErrorCodeNotReady: "Not Ready",
ExtendedErrorCodeBlocked: "Blocked",
ExtendedErrorCodeCensored: "Censored",
ExtendedErrorCodeFiltered: "Filtered",
ExtendedErrorCodeProhibited: "Prohibited",
ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer",
ExtendedErrorCodeNotAuthoritative: "Not Authoritative",
ExtendedErrorCodeNotSupported: "Not Supported",
ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority",
ExtendedErrorCodeNetworkError: "Network Error",
ExtendedErrorCodeInvalidData: "Invalid Data",
}
// StringToExtendedErrorCode is a map from human readable descriptions to
// extended error info codes.
var StringToExtendedErrorCode = reverseInt16(ExtendedErrorCodeToString)
// EDNS0_EDE option is used to return additional information about the cause of
// DNS errors.
type EDNS0_EDE struct {
InfoCode uint16
ExtraText string
}
// Option implements the EDNS0 interface.
func (e *EDNS0_EDE) Option() uint16 { return EDNS0EDE }
func (e *EDNS0_EDE) copy() EDNS0 { return &EDNS0_EDE{e.InfoCode, e.ExtraText} }
func (e *EDNS0_EDE) String() string {
info := strconv.FormatUint(uint64(e.InfoCode), 10)
if s, ok := ExtendedErrorCodeToString[e.InfoCode]; ok {
info += fmt.Sprintf(" (%s)", s)
}
return fmt.Sprintf("%s: (%s)", info, e.ExtraText)
}
func (e *EDNS0_EDE) pack() ([]byte, error) {
b := make([]byte, 2+len(e.ExtraText))
binary.BigEndian.PutUint16(b[0:], e.InfoCode)
copy(b[2:], []byte(e.ExtraText))
return b, nil
}
func (e *EDNS0_EDE) unpack(b []byte) error {
if len(b) < 2 {
return ErrBuf
}
e.InfoCode = binary.BigEndian.Uint16(b[0:])
e.ExtraText = string(b[2:])
return nil
}

View File

@ -20,13 +20,13 @@ import (
// of $ after that are interpreted. // of $ after that are interpreted.
func (zp *ZoneParser) generate(l lex) (RR, bool) { func (zp *ZoneParser) generate(l lex) (RR, bool) {
token := l.token token := l.token
step := 1 step := int64(1)
if i := strings.IndexByte(token, '/'); i >= 0 { if i := strings.IndexByte(token, '/'); i >= 0 {
if i+1 == len(token) { if i+1 == len(token) {
return zp.setParseError("bad step in $GENERATE range", l) return zp.setParseError("bad step in $GENERATE range", l)
} }
s, err := strconv.Atoi(token[i+1:]) s, err := strconv.ParseInt(token[i+1:], 10, 64)
if err != nil || s <= 0 { if err != nil || s <= 0 {
return zp.setParseError("bad step in $GENERATE range", l) return zp.setParseError("bad step in $GENERATE range", l)
} }
@ -40,12 +40,12 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
return zp.setParseError("bad start-stop in $GENERATE range", l) return zp.setParseError("bad start-stop in $GENERATE range", l)
} }
start, err := strconv.Atoi(sx[0]) start, err := strconv.ParseInt(sx[0], 10, 64)
if err != nil { if err != nil {
return zp.setParseError("bad start in $GENERATE range", l) return zp.setParseError("bad start in $GENERATE range", l)
} }
end, err := strconv.Atoi(sx[1]) end, err := strconv.ParseInt(sx[1], 10, 64)
if err != nil { if err != nil {
return zp.setParseError("bad stop in $GENERATE range", l) return zp.setParseError("bad stop in $GENERATE range", l)
} }
@ -94,10 +94,10 @@ type generateReader struct {
s string s string
si int si int
cur int cur int64
start int start int64
end int end int64
step int step int64
mod bytes.Buffer mod bytes.Buffer
@ -173,7 +173,7 @@ func (r *generateReader) ReadByte() (byte, error) {
return '$', nil return '$', nil
} }
var offset int var offset int64
// Search for { and } // Search for { and }
if r.s[si+1] == '{' { if r.s[si+1] == '{' {
@ -208,7 +208,7 @@ func (r *generateReader) ReadByte() (byte, error) {
} }
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with. // Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
func modToPrintf(s string) (string, int, string) { func modToPrintf(s string) (string, int64, string) {
// Modifier is { offset [ ,width [ ,base ] ] } - provide default // Modifier is { offset [ ,width [ ,base ] ] } - provide default
// values for optional width and type, if necessary. // values for optional width and type, if necessary.
var offStr, widthStr, base string var offStr, widthStr, base string
@ -229,12 +229,12 @@ func modToPrintf(s string) (string, int, string) {
return "", 0, "bad base in $GENERATE" return "", 0, "bad base in $GENERATE"
} }
offset, err := strconv.Atoi(offStr) offset, err := strconv.ParseInt(offStr, 10, 64)
if err != nil { if err != nil {
return "", 0, "bad offset in $GENERATE" return "", 0, "bad offset in $GENERATE"
} }
width, err := strconv.Atoi(widthStr) width, err := strconv.ParseInt(widthStr, 10, 64)
if err != nil || width < 0 || width > 255 { if err != nil || width < 0 || width > 255 {
return "", 0, "bad width in $GENERATE" return "", 0, "bad width in $GENERATE"
} }

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

@ -1,11 +1,9 @@
module github.com/miekg/dns module github.com/miekg/dns
go 1.12 go 1.14
require ( require (
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sys v0.0.0-20210303074136-134d130e1a04
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect
) )

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

@ -1,39 +1,10 @@
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4 h1:Vk3wNqEZwyGyei9yq5ekj7frek2u7HUfffJ1/opblzc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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-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/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -10,7 +10,7 @@ package dns
// escaped dots (\.) for instance. // escaped dots (\.) for instance.
// s must be a syntactically valid domain name, see IsDomainName. // s must be a syntactically valid domain name, see IsDomainName.
func SplitDomainName(s string) (labels []string) { func SplitDomainName(s string) (labels []string) {
if len(s) == 0 { if s == "" {
return nil return nil
} }
fqdnEnd := 0 // offset of the final '.' or the length of the name fqdnEnd := 0 // offset of the final '.' or the length of the name
@ -83,7 +83,7 @@ func CompareDomainName(s1, s2 string) (n int) {
return return
} }
// CountLabel counts the the number of labels in the string s. // CountLabel counts the number of labels in the string s.
// s must be a syntactically valid domain name. // s must be a syntactically valid domain name.
func CountLabel(s string) (labels int) { func CountLabel(s string) (labels int) {
if s == "." { if s == "." {

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

@ -398,17 +398,12 @@ Loop:
return "", lenmsg, ErrLongDomain return "", lenmsg, ErrLongDomain
} }
for _, b := range msg[off : off+c] { for _, b := range msg[off : off+c] {
switch b { if isDomainNameLabelSpecial(b) {
case '.', '(', ')', ';', ' ', '@':
fallthrough
case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
default: } else if b < ' ' || b > '~' {
if b < ' ' || b > '~' { // unprintable, use \DDD s = append(s, escapeByte(b)...)
s = append(s, escapeByte(b)...) } else {
} else { s = append(s, b)
s = append(s, b)
}
} }
} }
s = append(s, '.') s = append(s, '.')
@ -629,11 +624,18 @@ func UnpackRRWithHeader(h RR_Header, msg []byte, off int) (rr RR, off1 int, err
rr = &RFC3597{Hdr: h} rr = &RFC3597{Hdr: h}
} }
if noRdata(h) { if off < 0 || off > len(msg) {
return rr, off, nil return &h, off, &Error{err: "bad off"}
} }
end := off + int(h.Rdlength) end := off + int(h.Rdlength)
if end < off || end > len(msg) {
return &h, end, &Error{err: "bad rdlength"}
}
if noRdata(h) {
return rr, off, nil
}
off, err = rr.unpack(msg, off) off, err = rr.unpack(msg, off)
if err != nil { if err != nil {
@ -661,7 +663,6 @@ func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error)
} }
// If offset does not increase anymore, l is a lie // If offset does not increase anymore, l is a lie
if off1 == off { if off1 == off {
l = i
break break
} }
dst = append(dst, r) dst = append(dst, r)
@ -741,7 +742,7 @@ func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression compression
} }
// Set extended rcode unconditionally if we have an opt, this will allow // Set extended rcode unconditionally if we have an opt, this will allow
// reseting the extended rcode bits if they need to. // resetting the extended rcode bits if they need to.
if opt := dns.IsEdns0(); opt != nil { if opt := dns.IsEdns0(); opt != nil {
opt.SetExtendedRcode(uint16(dns.Rcode)) opt.SetExtendedRcode(uint16(dns.Rcode))
} else if dns.Rcode > 0xF { } else if dns.Rcode > 0xF {

View File

@ -6,6 +6,7 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"net" "net"
"sort"
"strings" "strings"
) )
@ -423,86 +424,12 @@ Option:
if off+int(optlen) > len(msg) { if off+int(optlen) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking opt"} return nil, len(msg), &Error{err: "overflow unpacking opt"}
} }
switch code { e := makeDataOpt(code)
case EDNS0NSID: if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
e := new(EDNS0_NSID) return nil, len(msg), err
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0SUBNET:
e := new(EDNS0_SUBNET)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0COOKIE:
e := new(EDNS0_COOKIE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0EXPIRE:
e := new(EDNS0_EXPIRE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0UL:
e := new(EDNS0_UL)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0LLQ:
e := new(EDNS0_LLQ)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DAU:
e := new(EDNS0_DAU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DHU:
e := new(EDNS0_DHU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0N3U:
e := new(EDNS0_N3U)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0PADDING:
e := new(EDNS0_PADDING)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
default:
e := new(EDNS0_LOCAL)
e.Code = code
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
} }
edns = append(edns, e)
off += int(optlen)
if off < len(msg) { if off < len(msg) {
goto Option goto Option
@ -521,9 +448,7 @@ func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
off += 4 off += 4
if off+len(b) > len(msg) { if off+len(b) > len(msg) {
copy(msg[off:], b) return len(msg), &Error{err: "overflow packing opt"}
off = len(msg)
continue
} }
// Actual data // Actual data
copy(msg[off:off+len(b)], b) copy(msg[off:off+len(b)], b)
@ -659,6 +584,65 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
return off, nil return off, nil
} }
func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
var xs []SVCBKeyValue
var code uint16
var length uint16
var err error
for off < len(msg) {
code, off, err = unpackUint16(msg, off)
if err != nil {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
length, off, err = unpackUint16(msg, off)
if err != nil || off+int(length) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
e := makeSVCBKeyValue(SVCBKey(code))
if e == nil {
return nil, len(msg), &Error{err: "bad SVCB key"}
}
if err := e.unpack(msg[off : off+int(length)]); err != nil {
return nil, len(msg), err
}
if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
}
xs = append(xs, e)
off += int(length)
}
return xs, off, nil
}
func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
pairs = append([]SVCBKeyValue(nil), pairs...)
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].Key() < pairs[j].Key()
})
prev := svcb_RESERVED
for _, el := range pairs {
if el.Key() == prev {
return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
}
prev = el.Key()
packed, err := el.pack()
if err != nil {
return len(msg), err
}
off, err = packUint16(uint16(el.Key()), msg, off)
if err != nil {
return len(msg), &Error{err: "overflow packing SVCB"}
}
off, err = packUint16(uint16(len(packed)), msg, off)
if err != nil || off+len(packed) > len(msg) {
return len(msg), &Error{err: "overflow packing SVCB"}
}
copy(msg[off:off+len(packed)], packed)
off += len(packed)
}
return off, nil
}
func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) { func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
var ( var (
servers []string servers []string
@ -730,6 +714,13 @@ func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
if p.Negation { if p.Negation {
n = 0x80 n = 0x80
} }
// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
i := len(addr) - 1
for ; i >= 0 && addr[i] == 0; i-- {
}
addr = addr[:i+1]
adflen := uint8(len(addr)) & 0x7f adflen := uint8(len(addr)) & 0x7f
off, err = packUint8(n|adflen, msg, off) off, err = packUint8(n|adflen, msg, off)
if err != nil { if err != nil {
@ -783,28 +774,31 @@ func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
if int(prefix) > 8*len(ip) { if int(prefix) > 8*len(ip) {
return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"} return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
} }
afdlen := int(nlen & 0x7f) afdlen := int(nlen & 0x7f)
if (int(prefix)+7)/8 != afdlen { if afdlen > len(ip) {
return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"} return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
} }
if off+afdlen > len(msg) { if off+afdlen > len(msg) {
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"} return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
} }
off += copy(ip, msg[off:off+afdlen]) off += copy(ip, msg[off:off+afdlen])
if prefix%8 > 0 { if afdlen > 0 {
last := ip[afdlen-1] last := ip[afdlen-1]
zero := uint8(0xff) >> (prefix % 8) if last == 0 {
if last&zero > 0 {
return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"} return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
} }
} }
ipnet := net.IPNet{
IP: ip,
Mask: net.CIDRMask(int(prefix), 8*len(ip)),
}
network := ipnet.IP.Mask(ipnet.Mask)
if !network.Equal(ipnet.IP) {
return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"}
}
return APLPrefix{ return APLPrefix{
Negation: (nlen & 0x80) != 0, Negation: (nlen & 0x80) != 0,
Network: net.IPNet{ Network: ipnet,
IP: ip,
Mask: net.CIDRMask(int(prefix), 8*len(ip)),
},
}, off, nil }, off, nil
} }

View File

@ -8,8 +8,14 @@ package dns
// record adding as many records as possible without exceeding the // record adding as many records as possible without exceeding the
// requested buffer size. // requested buffer size.
// //
// If the message fits within the requested size without compression,
// Truncate will set the message's Compress attribute to false. It is
// the caller's responsibility to set it back to true if they wish to
// compress the payload regardless of size.
//
// The TC bit will be set if any records were excluded from the message. // The TC bit will be set if any records were excluded from the message.
// This indicates to that the client should retry over TCP. // If the TC bit is already set on the message it will be retained.
// TC indicates that the client should retry over TCP.
// //
// According to RFC 2181, the TC bit should only be set if not all of the // 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 // "required" RRs can be included in the response. Unfortunately, we have
@ -28,11 +34,11 @@ func (dns *Msg) Truncate(size int) {
} }
// RFC 6891 mandates that the payload size in an OPT record // RFC 6891 mandates that the payload size in an OPT record
// less than 512 bytes must be treated as equal to 512 bytes. // less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes.
// //
// For ease of use, we impose that restriction here. // For ease of use, we impose that restriction here.
if size < 512 { if size < MinMsgSize {
size = 512 size = MinMsgSize
} }
l := msgLenWithCompressionMap(dns, nil) // uncompressed length l := msgLenWithCompressionMap(dns, nil) // uncompressed length
@ -73,11 +79,11 @@ func (dns *Msg) Truncate(size int) {
var numExtra int var numExtra int
if l < size { if l < size {
l, numExtra = truncateLoop(dns.Extra, size, l, compression) _, numExtra = truncateLoop(dns.Extra, size, l, compression)
} }
// See the function documentation for when we set this. // See the function documentation for when we set this.
dns.Truncated = len(dns.Answer) > numAnswer || dns.Truncated = dns.Truncated || len(dns.Answer) > numAnswer ||
len(dns.Ns) > numNS || len(dns.Extra) > numExtra len(dns.Ns) > numNS || len(dns.Extra) > numExtra
dns.Answer = dns.Answer[:numAnswer] dns.Answer = dns.Answer[:numAnswer]

View File

@ -43,7 +43,7 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
return toBase32(nsec3) return toBase32(nsec3)
} }
// Cover returns true if a name is covered by the NSEC3 record // Cover returns true if a name is covered by the NSEC3 record.
func (rr *NSEC3) Cover(name string) bool { func (rr *NSEC3) Cover(name string) bool {
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt) nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
owner := strings.ToUpper(rr.Hdr.Name) owner := strings.ToUpper(rr.Hdr.Name)

View File

@ -6,14 +6,13 @@ import "strings"
// 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
// official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove. // official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove.
type PrivateRdata interface { type PrivateRdata interface {
// String returns the text presentaton of the Rdata of the Private RR. // String returns the text presentation of the Rdata of the Private RR.
String() string String() string
// Parse parses the Rdata of the private RR. // Parse parses the Rdata of the private RR.
Parse([]string) error Parse([]string) error
// Pack is used when packing a private RR into a buffer. // Pack is used when packing a private RR into a buffer.
Pack([]byte) (int, error) Pack([]byte) (int, error)
// 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.
Unpack([]byte) (int, error) Unpack([]byte) (int, error)
// Copy copies the Rdata into the PrivateRdata argument. // Copy copies the Rdata into the PrivateRdata argument.
Copy(PrivateRdata) error Copy(PrivateRdata) error
@ -91,7 +90,7 @@ Fetch:
return nil return nil
} }
func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false } func (r *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.

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

@ -87,31 +87,18 @@ type lex struct {
column int // column in the file column int // column in the file
} }
// Token holds the token that are returned when a zone file is parsed.
type Token struct {
// The scanned resource record when error is not nil.
RR
// When an error occurred, this has the error specifics.
Error *ParseError
// A potential comment positioned after the RR and on the same line.
Comment string
}
// ttlState describes the state necessary to fill in an omitted RR TTL // ttlState describes the state necessary to fill in an omitted RR TTL
type ttlState struct { type ttlState struct {
ttl uint32 // ttl is the current default TTL ttl uint32 // ttl is the current default TTL
isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
} }
// NewRR reads the RR contained in the string s. Only the first RR is // NewRR reads the RR contained in the string s. Only the first RR is returned.
// returned. If s contains no records, NewRR will return nil with no // If s contains no records, NewRR will return nil with no error.
// error.
// //
// The class defaults to IN and TTL defaults to 3600. The full zone // The class defaults to IN and TTL defaults to 3600. The full zone file syntax
// file syntax like $TTL, $ORIGIN, etc. is supported. // like $TTL, $ORIGIN, etc. is supported. All fields of the returned RR are
// // set, except RR.Header().Rdlength which is set to 0.
// All fields of the returned RR are set, except RR.Header().Rdlength
// which is set to 0.
func NewRR(s string) (RR, error) { func NewRR(s string) (RR, error) {
if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
return ReadRR(strings.NewReader(s+"\n"), "") return ReadRR(strings.NewReader(s+"\n"), "")
@ -133,70 +120,6 @@ func ReadRR(r io.Reader, file string) (RR, error) {
return rr, zp.Err() return rr, zp.Err()
} }
// ParseZone reads a RFC 1035 style zonefile from r. It returns
// Tokens on the returned channel, each consisting of either a
// 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.
//
// The string file is used in error reporting and to resolve relative
// $INCLUDE directives. The string origin is used as the initial
// origin, as if the file would start with an $ORIGIN directive.
//
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
// 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
// zone data:
//
// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
// if x.Error != nil {
// // log.Println(x.Error)
// } else {
// // Do something with x.RR
// }
// }
//
// Comments specified after an RR (and on the same line!) are
// returned too:
//
// foo. IN A 10.0.0.1 ; this is a comment
//
// The text "; this is comment" is returned in Token.Comment.
// Comments inside the RR are returned concatenated along with the
// RR. Comments on a line by themselves are discarded.
//
// To prevent memory leaks it is important to always fully drain the
// returned channel. If an error occurs, it will always be the last
// Token sent on the channel.
//
// Deprecated: New users should prefer the ZoneParser API.
func ParseZone(r io.Reader, origin, file string) chan *Token {
t := make(chan *Token, 10000)
go parseZone(r, origin, file, t)
return t
}
func parseZone(r io.Reader, origin, file string, t chan *Token) {
defer close(t)
zp := NewZoneParser(r, origin, file)
zp.SetIncludeAllowed(true)
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
t <- &Token{RR: rr, Comment: zp.Comment()}
}
if err := zp.Err(); err != nil {
pe, ok := err.(*ParseError)
if !ok {
pe = &ParseError{file: file, err: err.Error()}
}
t <- &Token{Error: pe}
}
}
// ZoneParser is a parser for an RFC 1035 style zonefile. // ZoneParser is a parser for an RFC 1035 style zonefile.
// //
// Each parsed RR in the zone is returned sequentially from Next. An // Each parsed RR in the zone is returned sequentially from Next. An
@ -227,6 +150,9 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) {
// The text "; this is comment" is returned from Comment. Comments inside // The text "; this is comment" is returned from Comment. Comments inside
// the RR are returned concatenated along with the RR. Comments on a line // the RR are returned concatenated along with the RR. Comments on a line
// by themselves are discarded. // by themselves are discarded.
//
// Callers should not assume all returned data in an Resource Record is
// syntactically correct, e.g. illegal base64 in RRSIGs will be returned as-is.
type ZoneParser struct { type ZoneParser struct {
c *zlexer c *zlexer
@ -247,7 +173,7 @@ type ZoneParser struct {
includeDepth uint8 includeDepth uint8
includeAllowed bool includeAllowed bool
generateDisallowed bool generateDisallowed bool
} }
@ -654,10 +580,23 @@ func (zp *ZoneParser) Next() (RR, bool) {
st = zExpectRdata st = zExpectRdata
case zExpectRdata: case zExpectRdata:
var rr RR var (
if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) { rr RR
parseAsRFC3597 bool
)
if newFn, ok := TypeToRR[h.Rrtype]; ok {
rr = newFn() rr = newFn()
*rr.Header() = *h *rr.Header() = *h
// We may be parsing a known RR type using the RFC3597 format.
// If so, we handle that here in a generic way.
//
// This is also true for PrivateRR types which will have the
// RFC3597 parsing done for them and the Unpack method called
// to populate the RR instead of simply deferring to Parse.
if zp.c.Peek().token == "\\#" {
parseAsRFC3597 = true
}
} else { } else {
rr = &RFC3597{Hdr: *h} rr = &RFC3597{Hdr: *h}
} }
@ -677,13 +616,18 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError("unexpected newline", l) return zp.setParseError("unexpected newline", l)
} }
if err := rr.parse(zp.c, zp.origin); err != nil { parseAsRR := rr
if parseAsRFC3597 {
parseAsRR = &RFC3597{Hdr: *h}
}
if err := parseAsRR.parse(zp.c, zp.origin); err != nil {
// err is a concrete *ParseError without the file field set. // err is a concrete *ParseError without the file field set.
// The setParseError call below will construct a new // The setParseError call below will construct a new
// *ParseError with file set to zp.file. // *ParseError with file set to zp.file.
// If err.lex is nil than we have encounter an unknown RR type // err.lex may be nil in which case we substitute our current
// in that case we substitute our current lex token. // lex token.
if err.lex == (lex{}) { if err.lex == (lex{}) {
return zp.setParseError(err.err, l) return zp.setParseError(err.err, l)
} }
@ -691,6 +635,13 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError(err.err, err.lex) return zp.setParseError(err.err, err.lex)
} }
if parseAsRFC3597 {
err := parseAsRR.(*RFC3597).fromRFC3597(rr)
if err != nil {
return zp.setParseError(err.Error(), l)
}
}
return rr, true return rr, true
} }
} }
@ -700,18 +651,6 @@ 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
@ -1287,11 +1226,29 @@ func stringToCm(token string) (e, m uint8, ok bool) {
if cmeters, err = strconv.Atoi(s[1]); err != nil { if cmeters, err = strconv.Atoi(s[1]); err != nil {
return return
} }
// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
// So we simply reject it.
// We also make sure the first character is a digit to reject '+-' signs.
if len(s[1]) > 2 || s[1][0] < '0' || s[1][0] > '9' {
return
}
if len(s[1]) == 1 {
// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
cmeters *= 10
}
if s[0] == "" {
// This will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
break
}
fallthrough fallthrough
case 1: case 1:
if meters, err = strconv.Atoi(s[0]); err != nil { if meters, err = strconv.Atoi(s[0]); err != nil {
return return
} }
// RFC1876 states the max value is 90000000.00. The latter two conditions enforce it.
if s[0][0] < '0' || s[0][0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
return
}
case 0: case 0:
// huh? // huh?
return 0, 0, false return 0, 0, false
@ -1304,13 +1261,10 @@ func stringToCm(token string) (e, m uint8, ok bool) {
e = 0 e = 0
val = cmeters val = cmeters
} }
for val > 10 { for val >= 10 {
e++ e++
val /= 10 val /= 10
} }
if e > 9 {
ok = false
}
m = uint8(val) m = uint8(val)
return return
} }
@ -1352,6 +1306,9 @@ func appendOrigin(name, origin string) string {
// LOC record helper function // LOC record helper function
func locCheckNorth(token string, latitude uint32) (uint32, bool) { func locCheckNorth(token string, latitude uint32) (uint32, bool) {
if latitude > 90*1000*60*60 {
return latitude, false
}
switch token { switch token {
case "n", "N": case "n", "N":
return LOC_EQUATOR + latitude, true return LOC_EQUATOR + latitude, true
@ -1363,6 +1320,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) {
// LOC record helper function // LOC record helper function
func locCheckEast(token string, longitude uint32) (uint32, bool) { func locCheckEast(token string, longitude uint32) (uint32, bool) {
if longitude > 180*1000*60*60 {
return longitude, false
}
switch token { switch token {
case "e", "E": case "e", "E":
return LOC_EQUATOR + longitude, true return LOC_EQUATOR + longitude, true
@ -1395,7 +1355,7 @@ func stringToNodeID(l lex) (uint64, *ParseError) {
if len(l.token) < 19 { if len(l.token) < 19 {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
} }
// There must be three colons at fixes postitions, if not its a parse error // There must be three colons at fixes positions, if not its a parse error
if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' { if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
} }

View File

@ -1,6 +1,7 @@
package dns package dns
import ( import (
"bytes"
"encoding/base64" "encoding/base64"
"net" "net"
"strconv" "strconv"
@ -10,15 +11,15 @@ import (
// A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces) // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
// or an error // or an error
func endingToString(c *zlexer, errstr string) (string, *ParseError) { func endingToString(c *zlexer, errstr string) (string, *ParseError) {
var s string var buffer bytes.Buffer
l, _ := c.Next() // zString l, _ := c.Next() // zString
for l.value != zNewline && l.value != zEOF { for l.value != zNewline && l.value != zEOF {
if l.err { if l.err {
return s, &ParseError{"", errstr, l} return buffer.String(), &ParseError{"", errstr, l}
} }
switch l.value { switch l.value {
case zString: case zString:
s += l.token buffer.WriteString(l.token)
case zBlank: // Ok case zBlank: // Ok
default: default:
return "", &ParseError{"", errstr, l} return "", &ParseError{"", errstr, l}
@ -26,7 +27,7 @@ func endingToString(c *zlexer, errstr string) (string, *ParseError) {
l, _ = c.Next() l, _ = c.Next()
} }
return s, nil return buffer.String(), nil
} }
// A remainder of the rdata with embedded spaces, split on unquoted whitespace // A remainder of the rdata with embedded spaces, split on unquoted whitespace
@ -403,7 +404,7 @@ func (rr *SOA) parse(c *zlexer, o string) *ParseError {
if l.err { if l.err {
return &ParseError{"", "bad SOA zone parameter", l} return &ParseError{"", "bad SOA zone parameter", l}
} }
if j, e := strconv.ParseUint(l.token, 10, 32); e != nil { if j, err := strconv.ParseUint(l.token, 10, 32); err != nil {
if i == 0 { if i == 0 {
// Serial must be a number // Serial must be a number
return &ParseError{"", "bad SOA zone parameter", l} return &ParseError{"", "bad SOA zone parameter", l}
@ -446,16 +447,16 @@ func (rr *SRV) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16) i, e1 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad SRV Weight", l} return &ParseError{"", "bad SRV Weight", l}
} }
rr.Weight = uint16(i) rr.Weight = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16) i, e2 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad SRV Port", l} return &ParseError{"", "bad SRV Port", l}
} }
rr.Port = uint16(i) rr.Port = uint16(i)
@ -482,8 +483,8 @@ func (rr *NAPTR) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16) i, e1 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad NAPTR Preference", l} return &ParseError{"", "bad NAPTR Preference", l}
} }
rr.Preference = uint16(i) rr.Preference = uint16(i)
@ -581,15 +582,15 @@ func (rr *TALINK) parse(c *zlexer, o string) *ParseError {
func (rr *LOC) parse(c *zlexer, o string) *ParseError { func (rr *LOC) parse(c *zlexer, o string) *ParseError {
// Non zero defaults for LOC record, see RFC 1876, Section 3. // Non zero defaults for LOC record, see RFC 1876, Section 3.
rr.HorizPre = 165 // 10000 rr.Size = 0x12 // 1e2 cm (1m)
rr.VertPre = 162 // 10 rr.HorizPre = 0x16 // 1e6 cm (10000m)
rr.Size = 18 // 1 rr.VertPre = 0x13 // 1e3 cm (10m)
ok := false ok := false
// North // North
l, _ := c.Next() l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32) i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err { if e != nil || l.err || i > 90 {
return &ParseError{"", "bad LOC Latitude", l} return &ParseError{"", "bad LOC Latitude", l}
} }
rr.Latitude = 1000 * 60 * 60 * uint32(i) rr.Latitude = 1000 * 60 * 60 * uint32(i)
@ -600,15 +601,15 @@ func (rr *LOC) parse(c *zlexer, o string) *ParseError {
if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok { if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
goto East goto East
} }
i, e = strconv.ParseUint(l.token, 10, 32) if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
if e != nil || l.err {
return &ParseError{"", "bad LOC Latitude minutes", l} return &ParseError{"", "bad LOC Latitude minutes", l}
} else {
rr.Latitude += 1000 * 60 * uint32(i)
} }
rr.Latitude += 1000 * 60 * uint32(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { if i, err := strconv.ParseFloat(l.token, 64); err != nil || l.err || i < 0 || i >= 60 {
return &ParseError{"", "bad LOC Latitude seconds", l} return &ParseError{"", "bad LOC Latitude seconds", l}
} else { } else {
rr.Latitude += uint32(1000 * i) rr.Latitude += uint32(1000 * i)
@ -626,7 +627,7 @@ East:
// East // East
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 180 {
return &ParseError{"", "bad LOC Longitude", l} return &ParseError{"", "bad LOC Longitude", l}
} else { } else {
rr.Longitude = 1000 * 60 * 60 * uint32(i) rr.Longitude = 1000 * 60 * 60 * uint32(i)
@ -637,14 +638,14 @@ East:
if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok { if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
goto Altitude goto Altitude
} }
if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
return &ParseError{"", "bad LOC Longitude minutes", l} return &ParseError{"", "bad LOC Longitude minutes", l}
} else { } else {
rr.Longitude += 1000 * 60 * uint32(i) rr.Longitude += 1000 * 60 * uint32(i)
} }
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { if i, err := strconv.ParseFloat(l.token, 64); err != nil || l.err || i < 0 || i >= 60 {
return &ParseError{"", "bad LOC Longitude seconds", l} return &ParseError{"", "bad LOC Longitude seconds", l}
} else { } else {
rr.Longitude += uint32(1000 * i) rr.Longitude += uint32(1000 * i)
@ -661,13 +662,13 @@ East:
Altitude: Altitude:
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if len(l.token) == 0 || l.err { if l.token == "" || l.err {
return &ParseError{"", "bad LOC Altitude", l} return &ParseError{"", "bad LOC Altitude", l}
} }
if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' { if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
l.token = l.token[0 : len(l.token)-1] l.token = l.token[0 : len(l.token)-1]
} }
if i, e := strconv.ParseFloat(l.token, 32); e != nil { if i, err := strconv.ParseFloat(l.token, 64); err != nil {
return &ParseError{"", "bad LOC Altitude", l} return &ParseError{"", "bad LOC Altitude", l}
} else { } else {
rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5) rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
@ -681,23 +682,23 @@ Altitude:
case zString: case zString:
switch count { switch count {
case 0: // Size case 0: // Size
e, m, ok := stringToCm(l.token) exp, m, ok := stringToCm(l.token)
if !ok { if !ok {
return &ParseError{"", "bad LOC Size", l} return &ParseError{"", "bad LOC Size", l}
} }
rr.Size = e&0x0f | m<<4&0xf0 rr.Size = exp&0x0f | m<<4&0xf0
case 1: // HorizPre case 1: // HorizPre
e, m, ok := stringToCm(l.token) exp, m, ok := stringToCm(l.token)
if !ok { if !ok {
return &ParseError{"", "bad LOC HorizPre", l} return &ParseError{"", "bad LOC HorizPre", l}
} }
rr.HorizPre = e&0x0f | m<<4&0xf0 rr.HorizPre = exp&0x0f | m<<4&0xf0
case 2: // VertPre case 2: // VertPre
e, m, ok := stringToCm(l.token) exp, m, ok := stringToCm(l.token)
if !ok { if !ok {
return &ParseError{"", "bad LOC VertPre", l} return &ParseError{"", "bad LOC VertPre", l}
} }
rr.VertPre = e&0x0f | m<<4&0xf0 rr.VertPre = exp&0x0f | m<<4&0xf0
} }
count++ count++
case zBlank: case zBlank:
@ -721,7 +722,7 @@ func (rr *HIP) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
if len(l.token) == 0 || l.err { if l.token == "" || l.err {
return &ParseError{"", "bad HIP Hit", l} return &ParseError{"", "bad HIP Hit", l}
} }
rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6. rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
@ -729,11 +730,15 @@ func (rr *HIP) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
if len(l.token) == 0 || l.err { if l.token == "" || l.err {
return &ParseError{"", "bad HIP PublicKey", l} return &ParseError{"", "bad HIP PublicKey", l}
} }
rr.PublicKey = l.token // This cannot contain spaces rr.PublicKey = l.token // This cannot contain spaces
rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey))) decodedPK, decodedPKerr := base64.StdEncoding.DecodeString(rr.PublicKey)
if decodedPKerr != nil {
return &ParseError{"", "bad HIP PublicKey", l}
}
rr.PublicKeyLength = uint16(len(decodedPK))
// RendezvousServers (if any) // RendezvousServers (if any)
l, _ = c.Next() l, _ = c.Next()
@ -762,7 +767,7 @@ func (rr *CERT) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
if v, ok := StringToCertType[l.token]; ok { if v, ok := StringToCertType[l.token]; ok {
rr.Type = v rr.Type = v
} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil { } else if i, err := strconv.ParseUint(l.token, 10, 16); err != nil {
return &ParseError{"", "bad CERT Type", l} return &ParseError{"", "bad CERT Type", l}
} else { } else {
rr.Type = uint16(i) rr.Type = uint16(i)
@ -778,7 +783,7 @@ func (rr *CERT) parse(c *zlexer, o string) *ParseError {
l, _ = c.Next() // zString l, _ = c.Next() // zString
if v, ok := StringToAlgorithm[l.token]; ok { if v, ok := StringToAlgorithm[l.token]; ok {
rr.Algorithm = v rr.Algorithm = v
} else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { } else if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
return &ParseError{"", "bad CERT Algorithm", l} return &ParseError{"", "bad CERT Algorithm", l}
} else { } else {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
@ -812,8 +817,8 @@ func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
j, e = strconv.ParseUint(l.token, 10, 16) j, e1 := strconv.ParseUint(l.token, 10, 16)
if e != nil { if e1 != nil {
// Serial must be a number // Serial must be a number
return &ParseError{"", "bad CSYNC flags", l} return &ParseError{"", "bad CSYNC flags", l}
} }
@ -845,10 +850,40 @@ func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
return nil return nil
} }
func (rr *SIG) parse(c *zlexer, o string) *ParseError { func (rr *ZONEMD) parse(c *zlexer, o string) *ParseError {
return rr.RRSIG.parse(c, o) l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return &ParseError{"", "bad ZONEMD Serial", l}
}
rr.Serial = uint32(i)
c.Next() // zBlank
l, _ = c.Next()
i, e1 := strconv.ParseUint(l.token, 10, 8)
if e1 != nil || l.err {
return &ParseError{"", "bad ZONEMD Scheme", l}
}
rr.Scheme = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad ZONEMD Hash Algorithm", l}
}
rr.Hash = uint8(i)
s, e2 := endingToString(c, "bad ZONEMD Digest")
if e2 != nil {
return e2
}
rr.Digest = s
return nil
} }
func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
func (rr *RRSIG) parse(c *zlexer, o string) *ParseError { func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
tokenUpper := strings.ToUpper(l.token) tokenUpper := strings.ToUpper(l.token)
@ -868,24 +903,24 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, err := strconv.ParseUint(l.token, 10, 8) i, e := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err { if e != nil || l.err {
return &ParseError{"", "bad RRSIG Algorithm", l} return &ParseError{"", "bad RRSIG Algorithm", l}
} }
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad RRSIG Labels", l} return &ParseError{"", "bad RRSIG Labels", l}
} }
rr.Labels = uint8(i) rr.Labels = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 32) i, e2 := strconv.ParseUint(l.token, 10, 32)
if err != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad RRSIG OrigTtl", l} return &ParseError{"", "bad RRSIG OrigTtl", l}
} }
rr.OrigTtl = uint32(i) rr.OrigTtl = uint32(i)
@ -894,8 +929,7 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
l, _ = c.Next() l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil { if i, err := StringToTime(l.token); err != nil {
// Try to see if all numeric and use it as epoch // Try to see if all numeric and use it as epoch
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
// TODO(miek): error out on > MAX_UINT32, same below
rr.Expiration = uint32(i) rr.Expiration = uint32(i)
} else { } else {
return &ParseError{"", "bad RRSIG Expiration", l} return &ParseError{"", "bad RRSIG Expiration", l}
@ -907,7 +941,7 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil { if i, err := StringToTime(l.token); err != nil {
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
rr.Inception = uint32(i) rr.Inception = uint32(i)
} else { } else {
return &ParseError{"", "bad RRSIG Inception", l} return &ParseError{"", "bad RRSIG Inception", l}
@ -918,8 +952,8 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 16) i, e3 := strconv.ParseUint(l.token, 10, 16)
if err != nil || l.err { if e3 != nil || l.err {
return &ParseError{"", "bad RRSIG KeyTag", l} return &ParseError{"", "bad RRSIG KeyTag", l}
} }
rr.KeyTag = uint16(i) rr.KeyTag = uint16(i)
@ -933,9 +967,9 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
} }
rr.SignerName = name rr.SignerName = name
s, e := endingToString(c, "bad RRSIG Signature") s, e4 := endingToString(c, "bad RRSIG Signature")
if e != nil { if e4 != nil {
return e return e4
} }
rr.Signature = s rr.Signature = s
@ -985,21 +1019,21 @@ func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
rr.Hash = uint8(i) rr.Hash = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad NSEC3 Flags", l} return &ParseError{"", "bad NSEC3 Flags", l}
} }
rr.Flags = uint8(i) rr.Flags = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16) i, e2 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad NSEC3 Iterations", l} return &ParseError{"", "bad NSEC3 Iterations", l}
} }
rr.Iterations = uint16(i) rr.Iterations = uint16(i)
c.Next() c.Next()
l, _ = c.Next() l, _ = c.Next()
if len(l.token) == 0 || l.err { if l.token == "" || l.err {
return &ParseError{"", "bad NSEC3 Salt", l} return &ParseError{"", "bad NSEC3 Salt", l}
} }
if l.token != "-" { if l.token != "-" {
@ -1009,7 +1043,7 @@ func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
c.Next() c.Next()
l, _ = c.Next() l, _ = c.Next()
if len(l.token) == 0 || l.err { if l.token == "" || l.err {
return &ParseError{"", "bad NSEC3 NextDomain", l} return &ParseError{"", "bad NSEC3 NextDomain", l}
} }
rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits) rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
@ -1050,22 +1084,22 @@ func (rr *NSEC3PARAM) parse(c *zlexer, o string) *ParseError {
rr.Hash = uint8(i) rr.Hash = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad NSEC3PARAM Flags", l} return &ParseError{"", "bad NSEC3PARAM Flags", l}
} }
rr.Flags = uint8(i) rr.Flags = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16) i, e2 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad NSEC3PARAM Iterations", l} return &ParseError{"", "bad NSEC3PARAM Iterations", l}
} }
rr.Iterations = uint16(i) rr.Iterations = uint16(i)
c.Next() c.Next()
l, _ = c.Next() l, _ = c.Next()
if l.token != "-" { if l.token != "-" {
rr.SaltLength = uint8(len(l.token)) rr.SaltLength = uint8(len(l.token) / 2)
rr.Salt = l.token rr.Salt = l.token
} }
return slurpRemainder(c) return slurpRemainder(c)
@ -1132,15 +1166,15 @@ func (rr *SSHFP) parse(c *zlexer, o string) *ParseError {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad SSHFP Type", l} return &ParseError{"", "bad SSHFP Type", l}
} }
rr.Type = uint8(i) rr.Type = uint8(i)
c.Next() // zBlank c.Next() // zBlank
s, e1 := endingToString(c, "bad SSHFP Fingerprint") s, e2 := endingToString(c, "bad SSHFP Fingerprint")
if e1 != nil { if e2 != nil {
return e1 return e2
} }
rr.FingerPrint = s rr.FingerPrint = s
return nil return nil
@ -1155,37 +1189,32 @@ func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, typ string) *ParseError {
rr.Flags = uint16(i) rr.Flags = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad " + typ + " Protocol", l} return &ParseError{"", "bad " + typ + " Protocol", l}
} }
rr.Protocol = uint8(i) rr.Protocol = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8) i, e2 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad " + typ + " Algorithm", l} return &ParseError{"", "bad " + typ + " Algorithm", l}
} }
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
s, e1 := endingToString(c, "bad "+typ+" PublicKey") s, e3 := endingToString(c, "bad "+typ+" PublicKey")
if e1 != nil { if e3 != nil {
return e1 return e3
} }
rr.PublicKey = s rr.PublicKey = s
return nil return nil
} }
func (rr *DNSKEY) parse(c *zlexer, o string) *ParseError { func (rr *DNSKEY) parse(c *zlexer, o string) *ParseError { return rr.parseDNSKEY(c, o, "DNSKEY") }
return rr.parseDNSKEY(c, o, "DNSKEY") func (rr *KEY) parse(c *zlexer, o string) *ParseError { return rr.parseDNSKEY(c, o, "KEY") }
} func (rr *CDNSKEY) parse(c *zlexer, o string) *ParseError { return rr.parseDNSKEY(c, o, "CDNSKEY") }
func (rr *DS) parse(c *zlexer, o string) *ParseError { return rr.parseDS(c, o, "DS") }
func (rr *KEY) parse(c *zlexer, o string) *ParseError { func (rr *DLV) parse(c *zlexer, o string) *ParseError { return rr.parseDS(c, o, "DLV") }
return rr.parseDNSKEY(c, o, "KEY") func (rr *CDS) parse(c *zlexer, o string) *ParseError { return rr.parseDS(c, o, "CDS") }
}
func (rr *CDNSKEY) parse(c *zlexer, o string) *ParseError {
return rr.parseDNSKEY(c, o, "CDNSKEY")
}
func (rr *RKEY) parse(c *zlexer, o string) *ParseError { func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
@ -1196,21 +1225,21 @@ func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
rr.Flags = uint16(i) rr.Flags = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad RKEY Protocol", l} return &ParseError{"", "bad RKEY Protocol", l}
} }
rr.Protocol = uint8(i) rr.Protocol = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8) i, e2 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad RKEY Algorithm", l} return &ParseError{"", "bad RKEY Algorithm", l}
} }
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
s, e1 := endingToString(c, "bad RKEY PublicKey") s, e3 := endingToString(c, "bad RKEY PublicKey")
if e1 != nil { if e3 != nil {
return e1 return e3
} }
rr.PublicKey = s rr.PublicKey = s
return nil return nil
@ -1243,15 +1272,15 @@ func (rr *GPOS) parse(c *zlexer, o string) *ParseError {
rr.Longitude = l.token rr.Longitude = l.token
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
_, e = strconv.ParseFloat(l.token, 64) _, e1 := strconv.ParseFloat(l.token, 64)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad GPOS Latitude", l} return &ParseError{"", "bad GPOS Latitude", l}
} }
rr.Latitude = l.token rr.Latitude = l.token
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
_, e = strconv.ParseFloat(l.token, 64) _, e2 := strconv.ParseFloat(l.token, 64)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad GPOS Altitude", l} return &ParseError{"", "bad GPOS Altitude", l}
} }
rr.Altitude = l.token rr.Altitude = l.token
@ -1267,7 +1296,7 @@ func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
rr.KeyTag = uint16(i) rr.KeyTag = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, e = strconv.ParseUint(l.token, 10, 8); e != nil { if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
tokenUpper := strings.ToUpper(l.token) tokenUpper := strings.ToUpper(l.token)
i, ok := StringToAlgorithm[tokenUpper] i, ok := StringToAlgorithm[tokenUpper]
if !ok || l.err { if !ok || l.err {
@ -1279,31 +1308,19 @@ func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
} }
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad " + typ + " DigestType", l} return &ParseError{"", "bad " + typ + " DigestType", l}
} }
rr.DigestType = uint8(i) rr.DigestType = uint8(i)
s, e1 := endingToString(c, "bad "+typ+" Digest") s, e2 := endingToString(c, "bad "+typ+" Digest")
if e1 != nil { if e2 != nil {
return e1 return e2
} }
rr.Digest = s rr.Digest = s
return nil return nil
} }
func (rr *DS) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "DS")
}
func (rr *DLV) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "DLV")
}
func (rr *CDS) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "CDS")
}
func (rr *TA) parse(c *zlexer, o string) *ParseError { func (rr *TA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16) i, e := strconv.ParseUint(l.token, 10, 16)
@ -1313,7 +1330,7 @@ func (rr *TA) parse(c *zlexer, o string) *ParseError {
rr.KeyTag = uint16(i) rr.KeyTag = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
tokenUpper := strings.ToUpper(l.token) tokenUpper := strings.ToUpper(l.token)
i, ok := StringToAlgorithm[tokenUpper] i, ok := StringToAlgorithm[tokenUpper]
if !ok || l.err { if !ok || l.err {
@ -1325,14 +1342,14 @@ func (rr *TA) parse(c *zlexer, o string) *ParseError {
} }
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad TA DigestType", l} return &ParseError{"", "bad TA DigestType", l}
} }
rr.DigestType = uint8(i) rr.DigestType = uint8(i)
s, err := endingToString(c, "bad TA Digest") s, e2 := endingToString(c, "bad TA Digest")
if err != nil { if e2 != nil {
return err return e2
} }
rr.Digest = s rr.Digest = s
return nil return nil
@ -1347,22 +1364,22 @@ func (rr *TLSA) parse(c *zlexer, o string) *ParseError {
rr.Usage = uint8(i) rr.Usage = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad TLSA Selector", l} return &ParseError{"", "bad TLSA Selector", l}
} }
rr.Selector = uint8(i) rr.Selector = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e2 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad TLSA MatchingType", l} return &ParseError{"", "bad TLSA MatchingType", l}
} }
rr.MatchingType = uint8(i) rr.MatchingType = uint8(i)
// So this needs be e2 (i.e. different than e), because...??t // So this needs be e2 (i.e. different than e), because...??t
s, e2 := endingToString(c, "bad TLSA Certificate") s, e3 := endingToString(c, "bad TLSA Certificate")
if e2 != nil { if e3 != nil {
return e2 return e3
} }
rr.Certificate = s rr.Certificate = s
return nil return nil
@ -1377,22 +1394,22 @@ func (rr *SMIMEA) parse(c *zlexer, o string) *ParseError {
rr.Usage = uint8(i) rr.Usage = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad SMIMEA Selector", l} return &ParseError{"", "bad SMIMEA Selector", l}
} }
rr.Selector = uint8(i) rr.Selector = uint8(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8) i, e2 := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err { if e2 != nil || l.err {
return &ParseError{"", "bad SMIMEA MatchingType", l} return &ParseError{"", "bad SMIMEA MatchingType", l}
} }
rr.MatchingType = uint8(i) rr.MatchingType = uint8(i)
// So this needs be e2 (i.e. different than e), because...??t // So this needs be e2 (i.e. different than e), because...??t
s, e2 := endingToString(c, "bad SMIMEA Certificate") s, e3 := endingToString(c, "bad SMIMEA Certificate")
if e2 != nil { if e3 != nil {
return e2 return e3
} }
rr.Certificate = s rr.Certificate = s
return nil return nil
@ -1406,7 +1423,7 @@ func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
rdlength, e := strconv.Atoi(l.token) rdlength, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e != nil || l.err {
return &ParseError{"", "bad RFC3597 Rdata ", l} return &ParseError{"", "bad RFC3597 Rdata ", l}
} }
@ -1415,7 +1432,7 @@ func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
if e1 != nil { if e1 != nil {
return e1 return e1
} }
if rdlength*2 != len(s) { if int(rdlength)*2 != len(s) {
return &ParseError{"", "bad RFC3597 Rdata", l} return &ParseError{"", "bad RFC3597 Rdata", l}
} }
rr.Rdata = s rr.Rdata = s
@ -1469,16 +1486,16 @@ func (rr *URI) parse(c *zlexer, o string) *ParseError {
rr.Priority = uint16(i) rr.Priority = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16) i, e1 := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad URI Weight", l} return &ParseError{"", "bad URI Weight", l}
} }
rr.Weight = uint16(i) rr.Weight = uint16(i)
c.Next() // zBlank c.Next() // zBlank
s, err := endingToTxtSlice(c, "bad URI Target") s, e2 := endingToTxtSlice(c, "bad URI Target")
if err != nil { if e2 != nil {
return err return e2
} }
if len(s) != 1 { if len(s) != 1 {
return &ParseError{"", "bad URI Target", l} return &ParseError{"", "bad URI Target", l}
@ -1506,9 +1523,9 @@ func (rr *NID) parse(c *zlexer, o string) *ParseError {
rr.Preference = uint16(i) rr.Preference = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
u, err := stringToNodeID(l) u, e1 := stringToNodeID(l)
if err != nil || l.err { if e1 != nil || l.err {
return err return e1
} }
rr.NodeID = u rr.NodeID = u
return slurpRemainder(c) return slurpRemainder(c)
@ -1546,7 +1563,6 @@ func (rr *LP) parse(c *zlexer, o string) *ParseError {
return &ParseError{"", "bad LP Fqdn", l} return &ParseError{"", "bad LP Fqdn", l}
} }
rr.Fqdn = name rr.Fqdn = name
return slurpRemainder(c) return slurpRemainder(c)
} }
@ -1559,9 +1575,9 @@ func (rr *L64) parse(c *zlexer, o string) *ParseError {
rr.Preference = uint16(i) rr.Preference = uint16(i)
c.Next() // zBlank c.Next() // zBlank
l, _ = c.Next() // zString l, _ = c.Next() // zString
u, err := stringToNodeID(l) u, e1 := stringToNodeID(l)
if err != nil || l.err { if e1 != nil || l.err {
return err return e1
} }
rr.Locator64 = u rr.Locator64 = u
return slurpRemainder(c) return slurpRemainder(c)
@ -1624,14 +1640,13 @@ func (rr *PX) parse(c *zlexer, o string) *ParseError {
return &ParseError{"", "bad PX Mapx400", l} return &ParseError{"", "bad PX Mapx400", l}
} }
rr.Mapx400 = mapx400 rr.Mapx400 = mapx400
return slurpRemainder(c) return slurpRemainder(c)
} }
func (rr *CAA) parse(c *zlexer, o string) *ParseError { func (rr *CAA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
i, err := strconv.ParseUint(l.token, 10, 8) i, e := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err { if e != nil || l.err {
return &ParseError{"", "bad CAA Flag", l} return &ParseError{"", "bad CAA Flag", l}
} }
rr.Flag = uint8(i) rr.Flag = uint8(i)
@ -1644,9 +1659,9 @@ func (rr *CAA) parse(c *zlexer, o string) *ParseError {
rr.Tag = l.token rr.Tag = l.token
c.Next() // zBlank c.Next() // zBlank
s, e := endingToTxtSlice(c, "bad CAA Value") s, e1 := endingToTxtSlice(c, "bad CAA Value")
if e != nil { if e1 != nil {
return e return e1
} }
if len(s) != 1 { if len(s) != 1 {
return &ParseError{"", "bad CAA Value", l} return &ParseError{"", "bad CAA Value", l}
@ -1667,8 +1682,8 @@ func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
// Get the key length and key values // Get the key length and key values
l, _ = c.Next() l, _ = c.Next()
i, err := strconv.ParseUint(l.token, 10, 8) i, e := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err { if e != nil || l.err {
return &ParseError{"", "bad TKEY key length", l} return &ParseError{"", "bad TKEY key length", l}
} }
rr.KeySize = uint16(i) rr.KeySize = uint16(i)
@ -1682,8 +1697,8 @@ func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
// Get the otherdata length and string data // Get the otherdata length and string data
l, _ = c.Next() l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 8) i, e1 := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err { if e1 != nil || l.err {
return &ParseError{"", "bad TKEY otherdata length", l} return &ParseError{"", "bad TKEY otherdata length", l}
} }
rr.OtherLen = uint16(i) rr.OtherLen = uint16(i)
@ -1693,7 +1708,6 @@ func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
return &ParseError{"", "bad TKEY otherday", l} return &ParseError{"", "bad TKEY otherday", l}
} }
rr.OtherData = l.token rr.OtherData = l.token
return nil return nil
} }
@ -1727,9 +1741,9 @@ func (rr *APL) parse(c *zlexer, o string) *ParseError {
family = family[1:] family = family[1:]
} }
afi, err := strconv.ParseUint(family, 10, 16) afi, e := strconv.ParseUint(family, 10, 16)
if err != nil { if e != nil {
return &ParseError{"", "failed to parse APL family: " + err.Error(), l} return &ParseError{"", "failed to parse APL family: " + e.Error(), l}
} }
var addrLen int var addrLen int
switch afi { switch afi {
@ -1741,9 +1755,9 @@ func (rr *APL) parse(c *zlexer, o string) *ParseError {
return &ParseError{"", "unrecognized APL family", l} return &ParseError{"", "unrecognized APL family", l}
} }
ip, subnet, err := net.ParseCIDR(cidr) ip, subnet, e1 := net.ParseCIDR(cidr)
if err != nil { if e1 != nil {
return &ParseError{"", "failed to parse APL address: " + err.Error(), l} return &ParseError{"", "failed to parse APL address: " + e1.Error(), l}
} }
if !ip.Equal(subnet.IP) { if !ip.Equal(subnet.IP) {
return &ParseError{"", "extra bits in APL address", l} return &ParseError{"", "extra bits in APL address", l}

View File

@ -1,7 +1,6 @@
package dns package dns
import ( import (
"strings"
"sync" "sync"
) )
@ -36,7 +35,7 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
return nil return nil
} }
q = strings.ToLower(q) q = CanonicalName(q)
var handler Handler var handler Handler
for off, end := 0, false; !end; off, end = NextLabel(q, off) { for off, end := 0, false; !end; off, end = NextLabel(q, off) {
@ -66,7 +65,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
if mux.z == nil { if mux.z == nil {
mux.z = make(map[string]Handler) mux.z = make(map[string]Handler)
} }
mux.z[Fqdn(pattern)] = handler mux.z[CanonicalName(pattern)] = handler
mux.m.Unlock() mux.m.Unlock()
} }
@ -81,7 +80,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
panic("dns: invalid pattern " + pattern) panic("dns: invalid pattern " + pattern)
} }
mux.m.Lock() mux.m.Lock()
delete(mux.z, Fqdn(pattern)) delete(mux.z, CanonicalName(pattern))
mux.m.Unlock() mux.m.Unlock()
} }
@ -92,7 +91,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
// are redirected to the parent zone (if that is also registered), // are redirected to the parent zone (if that is also registered),
// otherwise the child gets the query. // otherwise the child gets the query.
// //
// If no handler is found, or there is no question, a standard SERVFAIL // If no handler is found, or there is no question, a standard REFUSED
// message is returned // message is returned
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) { func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
var h Handler var h Handler
@ -103,7 +102,7 @@ func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
if h != nil { if h != nil {
h.ServeDNS(w, req) h.ServeDNS(w, req)
} else { } else {
HandleFailed(w, req) handleRefused(w, req)
} }
} }

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

@ -72,13 +72,22 @@ type response struct {
tsigStatus error tsigStatus error
tsigRequestMAC string tsigRequestMAC string
tsigSecret map[string]string // the tsig secrets tsigSecret map[string]string // the tsig secrets
udp *net.UDPConn // i/o connection if UDP was used udp net.PacketConn // i/o connection if UDP was used
tcp net.Conn // i/o connection if TCP was used tcp net.Conn // i/o connection if TCP was used
udpSession *SessionUDP // oob data to get egress interface right udpSession *SessionUDP // oob data to get egress interface right
pcSession net.Addr // address to use when writing to a generic net.PacketConn
writer Writer // writer to output the raw DNS bits writer Writer // writer to output the raw DNS bits
} }
// handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
func handleRefused(w ResponseWriter, r *Msg) {
m := new(Msg)
m.SetRcode(r, RcodeRefused)
w.WriteMsg(m)
}
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
// Deprecated: This function is going away.
func HandleFailed(w ResponseWriter, r *Msg) { func HandleFailed(w ResponseWriter, r *Msg) {
m := new(Msg) m := new(Msg)
m.SetRcode(r, RcodeServerFailure) m.SetRcode(r, RcodeServerFailure)
@ -139,12 +148,24 @@ type Reader interface {
ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
} }
// defaultReader is an adapter for the Server struct that implements the Reader interface // PacketConnReader is an optional interface that Readers can implement to support using generic net.PacketConns.
// using the readTCP and readUDP func of the embedded Server. type PacketConnReader interface {
Reader
// ReadPacketConn reads a raw message from a generic net.PacketConn UDP connection. Implementations may
// alter connection properties, for example the read-deadline.
ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error)
}
// defaultReader is an adapter for the Server struct that implements the Reader and
// PacketConnReader interfaces using the readTCP, readUDP and readPacketConn funcs
// of the embedded Server.
type defaultReader struct { type defaultReader struct {
*Server *Server
} }
var _ PacketConnReader = defaultReader{}
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)
} }
@ -153,8 +174,14 @@ func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byt
return dr.readUDP(conn, timeout) return dr.readUDP(conn, timeout)
} }
func (dr defaultReader) ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
return dr.readPacketConn(conn, timeout)
}
// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader. // DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
// Implementations should never return a nil Reader. // Implementations should never return a nil Reader.
// Readers should also implement the optional PacketConnReader interface.
// PacketConnReader is required to use a generic net.PacketConn.
type DecorateReader func(Reader) Reader type DecorateReader func(Reader) Reader
// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer. // DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
@ -294,6 +321,7 @@ func (srv *Server) ListenAndServe() error {
} }
u := l.(*net.UDPConn) u := l.(*net.UDPConn)
if e := setUDPSocketOptions(u); e != nil { if e := setUDPSocketOptions(u); e != nil {
u.Close()
return e return e
} }
srv.PacketConn = l srv.PacketConn = l
@ -317,24 +345,22 @@ func (srv *Server) ActivateAndServe() error {
srv.init() srv.init()
pConn := srv.PacketConn if srv.PacketConn != nil {
l := srv.Listener
if pConn != nil {
// Check PacketConn interface's type is valid and value // Check PacketConn interface's type is valid and value
// is not nil // is not nil
if t, ok := pConn.(*net.UDPConn); ok && t != nil { if t, ok := srv.PacketConn.(*net.UDPConn); ok && t != nil {
if e := setUDPSocketOptions(t); e != nil { if e := setUDPSocketOptions(t); e != nil {
return e return e
} }
srv.started = true
unlock()
return srv.serveUDP(t)
} }
}
if l != nil {
srv.started = true srv.started = true
unlock() unlock()
return srv.serveTCP(l) return srv.serveUDP(srv.PacketConn)
}
if srv.Listener != nil {
srv.started = true
unlock()
return srv.serveTCP(srv.Listener)
} }
return &Error{err: "bad listeners"} return &Error{err: "bad listeners"}
} }
@ -438,18 +464,24 @@ func (srv *Server) serveTCP(l net.Listener) error {
} }
// serveUDP starts a UDP listener for the server. // serveUDP starts a UDP listener for the server.
func (srv *Server) serveUDP(l *net.UDPConn) error { func (srv *Server) serveUDP(l net.PacketConn) error {
defer l.Close() defer l.Close()
if srv.NotifyStartedFunc != nil {
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)
} }
lUDP, isUDP := l.(*net.UDPConn)
readerPC, canPacketConn := reader.(PacketConnReader)
if !isUDP && !canPacketConn {
return &Error{err: "PacketConnReader was not implemented on Reader returned from DecorateReader but is required for net.PacketConn"}
}
if srv.NotifyStartedFunc != nil {
srv.NotifyStartedFunc()
}
var wg sync.WaitGroup var wg sync.WaitGroup
defer func() { defer func() {
wg.Wait() wg.Wait()
@ -459,7 +491,17 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
rtimeout := srv.getReadTimeout() rtimeout := srv.getReadTimeout()
// deadline is not used here // deadline is not used here
for srv.isStarted() { for srv.isStarted() {
m, s, err := reader.ReadUDP(l, rtimeout) var (
m []byte
sPC net.Addr
sUDP *SessionUDP
err error
)
if isUDP {
m, sUDP, err = reader.ReadUDP(lUDP, rtimeout)
} else {
m, sPC, err = readerPC.ReadPacketConn(l, rtimeout)
}
if err != nil { if err != nil {
if !srv.isStarted() { if !srv.isStarted() {
return nil return nil
@ -476,7 +518,7 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
continue continue
} }
wg.Add(1) wg.Add(1)
go srv.serveUDPPacket(&wg, m, l, s) go srv.serveUDPPacket(&wg, m, l, sUDP, sPC)
} }
return nil return nil
@ -538,8 +580,8 @@ func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
} }
// Serve a new UDP request. // Serve a new UDP request.
func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u *net.UDPConn, s *SessionUDP) { func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) {
w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: s} w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: udpSession, pcSession: pcSession}
if srv.DecorateWriter != nil { if srv.DecorateWriter != nil {
w.writer = srv.DecorateWriter(w) w.writer = srv.DecorateWriter(w)
} else { } else {
@ -651,6 +693,24 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
return m, s, nil return m, s, nil
} }
func (srv *Server) readPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
srv.lock.RLock()
if srv.started {
// See the comment in readTCP above.
conn.SetReadDeadline(time.Now().Add(timeout))
}
srv.lock.RUnlock()
m := srv.udpPool.Get().([]byte)
n, addr, err := conn.ReadFrom(m)
if err != nil {
srv.udpPool.Put(m)
return nil, nil, err
}
m = m[:n]
return m, addr, nil
}
// 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 { if w.closed {
@ -684,17 +744,19 @@ func (w *response) Write(m []byte) (int, error) {
switch { switch {
case w.udp != nil: case w.udp != nil:
return WriteToSessionUDP(w.udp, m, w.udpSession) if u, ok := w.udp.(*net.UDPConn); ok {
return WriteToSessionUDP(u, m, w.udpSession)
}
return w.udp.WriteTo(m, w.pcSession)
case w.tcp != nil: case w.tcp != nil:
if len(m) > MaxMsgSize { if len(m) > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2) msg := make([]byte, 2+len(m))
binary.BigEndian.PutUint16(l, uint16(len(m))) binary.BigEndian.PutUint16(msg, uint16(len(m)))
copy(msg[2:], m)
n, err := (&net.Buffers{l, m}).WriteTo(w.tcp) return w.tcp.Write(msg)
return int(n), err
default: default:
panic("dns: internal error: udp and tcp both nil") panic("dns: internal error: udp and tcp both nil")
} }
@ -717,10 +779,12 @@ func (w *response) RemoteAddr() net.Addr {
switch { switch {
case w.udpSession != nil: case w.udpSession != nil:
return w.udpSession.RemoteAddr() return w.udpSession.RemoteAddr()
case w.pcSession != nil:
return w.pcSession
case w.tcp != nil: case w.tcp != nil:
return w.tcp.RemoteAddr() return w.tcp.RemoteAddr()
default: default:
panic("dns: internal error: udpSession and tcp both nil") panic("dns: internal error: udpSession, pcSession and tcp are all nil")
} }
} }

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

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"encoding/binary" "encoding/binary"
@ -18,7 +17,7 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
if k == nil { if k == nil {
return nil, ErrPrivKey return nil, ErrPrivKey
} }
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 { if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 {
return nil, ErrKey return nil, ErrKey
} }
@ -79,13 +78,13 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
if k == nil { if k == nil {
return ErrKey return ErrKey
} }
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 { if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 {
return ErrKey return ErrKey
} }
var hash crypto.Hash var hash crypto.Hash
switch rr.Algorithm { switch rr.Algorithm {
case DSA, RSASHA1: case RSASHA1:
hash = crypto.SHA1 hash = crypto.SHA1
case RSASHA256, ECDSAP256SHA256: case RSASHA256, ECDSAP256SHA256:
hash = crypto.SHA256 hash = crypto.SHA256
@ -178,17 +177,6 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
hashed := hasher.Sum(nil) hashed := hasher.Sum(nil)
sig := buf[sigend:] sig := buf[sigend:]
switch k.Algorithm { switch k.Algorithm {
case DSA:
pk := k.publicKeyDSA()
sig = sig[1:]
r := new(big.Int).SetBytes(sig[:len(sig)/2])
s := new(big.Int).SetBytes(sig[len(sig)/2:])
if pk != nil {
if dsa.Verify(pk, hashed, r, s) {
return nil
}
return ErrSig
}
case RSASHA1, RSASHA256, RSASHA512: case RSASHA1, RSASHA256, RSASHA512:
pk := k.publicKeyRSA() pk := k.publicKeyRSA()
if pk != nil { if pk != nil {

755
vendor/github.com/miekg/dns/svcb.go generated vendored Normal file
View File

@ -0,0 +1,755 @@
package dns
import (
"bytes"
"encoding/binary"
"errors"
"net"
"sort"
"strconv"
"strings"
)
// SVCBKey is the type of the keys used in the SVCB RR.
type SVCBKey uint16
// Keys defined in draft-ietf-dnsop-svcb-https-01 Section 12.3.2.
const (
SVCB_MANDATORY SVCBKey = 0
SVCB_ALPN SVCBKey = 1
SVCB_NO_DEFAULT_ALPN SVCBKey = 2
SVCB_PORT SVCBKey = 3
SVCB_IPV4HINT SVCBKey = 4
SVCB_ECHCONFIG SVCBKey = 5
SVCB_IPV6HINT SVCBKey = 6
svcb_RESERVED SVCBKey = 65535
)
var svcbKeyToStringMap = map[SVCBKey]string{
SVCB_MANDATORY: "mandatory",
SVCB_ALPN: "alpn",
SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
SVCB_PORT: "port",
SVCB_IPV4HINT: "ipv4hint",
SVCB_ECHCONFIG: "echconfig",
SVCB_IPV6HINT: "ipv6hint",
}
var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey {
n := make(map[string]SVCBKey, len(m))
for u, s := range m {
n[s] = u
}
return n
}
// String takes the numerical code of an SVCB key and returns its name.
// Returns an empty string for reserved keys.
// Accepts unassigned keys as well as experimental/private keys.
func (key SVCBKey) String() string {
if x := svcbKeyToStringMap[key]; x != "" {
return x
}
if key == svcb_RESERVED {
return ""
}
return "key" + strconv.FormatUint(uint64(key), 10)
}
// svcbStringToKey returns the numerical code of an SVCB key.
// Returns svcb_RESERVED for reserved/invalid keys.
// Accepts unassigned keys as well as experimental/private keys.
func svcbStringToKey(s string) SVCBKey {
if strings.HasPrefix(s, "key") {
a, err := strconv.ParseUint(s[3:], 10, 16)
// no leading zeros
// key shouldn't be registered
if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" {
return svcb_RESERVED
}
return SVCBKey(a)
}
if key, ok := svcbStringToKeyMap[s]; ok {
return key
}
return svcb_RESERVED
}
func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{l.token, "bad SVCB priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Target = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{l.token, "bad SVCB Target", l}
}
rr.Target = name
// Values (if any)
l, _ = c.Next()
var xs []SVCBKeyValue
// Helps require whitespace between pairs.
// Prevents key1000="a"key1001=...
canHaveNextKey := true
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
if !canHaveNextKey {
// The key we can now read was probably meant to be
// a part of the last value.
return &ParseError{l.token, "bad SVCB value quotation", l}
}
// In key=value pairs, value does not have to be quoted unless value
// contains whitespace. And keys don't need to have values.
// Similarly, keys with an equality signs after them don't need values.
// l.token includes at least up to the first equality sign.
idx := strings.IndexByte(l.token, '=')
var key, value string
if idx < 0 {
// Key with no value and no equality sign
key = l.token
} else if idx == 0 {
return &ParseError{l.token, "bad SVCB key", l}
} else {
key, value = l.token[:idx], l.token[idx+1:]
if value == "" {
// We have a key and an equality sign. Maybe we have nothing
// after "=" or we have a double quote.
l, _ = c.Next()
if l.value == zQuote {
// Only needed when value ends with double quotes.
// Any value starting with zQuote ends with it.
canHaveNextKey = false
l, _ = c.Next()
switch l.value {
case zString:
// We have a value in double quotes.
value = l.token
l, _ = c.Next()
if l.value != zQuote {
return &ParseError{l.token, "SVCB unterminated value", l}
}
case zQuote:
// There's nothing in double quotes.
default:
return &ParseError{l.token, "bad SVCB value", l}
}
}
}
}
kv := makeSVCBKeyValue(svcbStringToKey(key))
if kv == nil {
return &ParseError{l.token, "bad SVCB key", l}
}
if err := kv.parse(value); err != nil {
return &ParseError{l.token, err.Error(), l}
}
xs = append(xs, kv)
case zQuote:
return &ParseError{l.token, "SVCB key can't contain double quotes", l}
case zBlank:
canHaveNextKey = true
default:
return &ParseError{l.token, "bad SVCB values", l}
}
l, _ = c.Next()
}
rr.Value = xs
if rr.Priority == 0 && len(xs) > 0 {
return &ParseError{l.token, "SVCB aliasform can't have values", l}
}
return nil
}
// makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys.
func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
switch key {
case SVCB_MANDATORY:
return new(SVCBMandatory)
case SVCB_ALPN:
return new(SVCBAlpn)
case SVCB_NO_DEFAULT_ALPN:
return new(SVCBNoDefaultAlpn)
case SVCB_PORT:
return new(SVCBPort)
case SVCB_IPV4HINT:
return new(SVCBIPv4Hint)
case SVCB_ECHCONFIG:
return new(SVCBECHConfig)
case SVCB_IPV6HINT:
return new(SVCBIPv6Hint)
case svcb_RESERVED:
return nil
default:
e := new(SVCBLocal)
e.KeyCode = key
return e
}
}
// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-01).
type SVCB struct {
Hdr RR_Header
Priority uint16
Target string `dns:"domain-name"`
Value []SVCBKeyValue `dns:"pairs"` // Value must be empty if Priority is zero.
}
// HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
// Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
type HTTPS struct {
SVCB
}
func (rr *HTTPS) String() string {
return rr.SVCB.String()
}
func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
return rr.SVCB.parse(c, o)
}
// SVCBKeyValue defines a key=value pair for the SVCB RR type.
// An SVCB RR can have multiple SVCBKeyValues appended to it.
type SVCBKeyValue interface {
Key() SVCBKey // Key returns the numerical key code.
pack() ([]byte, error) // pack returns the encoded value.
unpack([]byte) error // unpack sets the value.
String() string // String returns the string representation of the value.
parse(string) error // parse sets the value to the given string representation of the value.
copy() SVCBKeyValue // copy returns a deep-copy of the pair.
len() int // len returns the length of value in the wire format.
}
// SVCBMandatory pair adds to required keys that must be interpreted for the RR
// to be functional.
// Basic use pattern for creating a mandatory option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBMandatory)
// e.Code = []uint16{65403}
// s.Value = append(s.Value, e)
type SVCBMandatory struct {
Code []SVCBKey // Must not include mandatory
}
func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
func (s *SVCBMandatory) String() string {
str := make([]string, len(s.Code))
for i, e := range s.Code {
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBMandatory) pack() ([]byte, error) {
codes := append([]SVCBKey(nil), s.Code...)
sort.Slice(codes, func(i, j int) bool {
return codes[i] < codes[j]
})
b := make([]byte, 2*len(codes))
for i, e := range codes {
binary.BigEndian.PutUint16(b[2*i:], uint16(e))
}
return b, nil
}
func (s *SVCBMandatory) unpack(b []byte) error {
if len(b)%2 != 0 {
return errors.New("dns: svcbmandatory: value length is not a multiple of 2")
}
codes := make([]SVCBKey, 0, len(b)/2)
for i := 0; i < len(b); i += 2 {
// We assume strictly increasing order.
codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:])))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) parse(b string) error {
str := strings.Split(b, ",")
codes := make([]SVCBKey, 0, len(str))
for _, e := range str {
codes = append(codes, svcbStringToKey(e))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) len() int {
return 2 * len(s.Code)
}
func (s *SVCBMandatory) copy() SVCBKeyValue {
return &SVCBMandatory{
append([]SVCBKey(nil), s.Code...),
}
}
// SVCBAlpn pair is used to list supported connection protocols.
// Protocol ids can be found at:
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
// Basic use pattern for creating an alpn option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "http/1.1"}
// h.Value = append(o.Value, e)
type SVCBAlpn struct {
Alpn []string
}
func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
func (s *SVCBAlpn) pack() ([]byte, error) {
// Liberally estimate the size of an alpn as 10 octets
b := make([]byte, 0, 10*len(s.Alpn))
for _, e := range s.Alpn {
if e == "" {
return nil, errors.New("dns: svcbalpn: empty alpn-id")
}
if len(e) > 255 {
return nil, errors.New("dns: svcbalpn: alpn-id too long")
}
b = append(b, byte(len(e)))
b = append(b, e...)
}
return b, nil
}
func (s *SVCBAlpn) unpack(b []byte) error {
// Estimate the size of the smallest alpn as 4 bytes
alpn := make([]string, 0, len(b)/4)
for i := 0; i < len(b); {
length := int(b[i])
i++
if i+length > len(b) {
return errors.New("dns: svcbalpn: alpn array overflowing")
}
alpn = append(alpn, string(b[i:i+length]))
i += length
}
s.Alpn = alpn
return nil
}
func (s *SVCBAlpn) parse(b string) error {
s.Alpn = strings.Split(b, ",")
return nil
}
func (s *SVCBAlpn) len() int {
var l int
for _, e := range s.Alpn {
l += 1 + len(e)
}
return l
}
func (s *SVCBAlpn) copy() SVCBKeyValue {
return &SVCBAlpn{
append([]string(nil), s.Alpn...),
}
}
// SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
// Basic use pattern for creating a no-default-alpn option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBNoDefaultAlpn)
// s.Value = append(s.Value, e)
type SVCBNoDefaultAlpn struct{}
func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN }
func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} }
func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil }
func (*SVCBNoDefaultAlpn) String() string { return "" }
func (*SVCBNoDefaultAlpn) len() int { return 0 }
func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
func (*SVCBNoDefaultAlpn) parse(b string) error {
if b != "" {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
// SVCBPort pair defines the port for connection.
// Basic use pattern for creating a port option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBPort)
// e.Port = 80
// s.Value = append(s.Value, e)
type SVCBPort struct {
Port uint16
}
func (*SVCBPort) Key() SVCBKey { return SVCB_PORT }
func (*SVCBPort) len() int { return 2 }
func (s *SVCBPort) String() string { return strconv.FormatUint(uint64(s.Port), 10) }
func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} }
func (s *SVCBPort) unpack(b []byte) error {
if len(b) != 2 {
return errors.New("dns: svcbport: port length is not exactly 2 octets")
}
s.Port = binary.BigEndian.Uint16(b)
return nil
}
func (s *SVCBPort) pack() ([]byte, error) {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, s.Port)
return b, nil
}
func (s *SVCBPort) parse(b string) error {
port, err := strconv.ParseUint(b, 10, 16)
if err != nil {
return errors.New("dns: svcbport: port out of range")
}
s.Port = uint16(port)
return nil
}
// SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the connection
// to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv4hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv4Hint)
// e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
//
// Or
//
// e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
// h.Value = append(h.Value, e)
type SVCBIPv4Hint struct {
Hint []net.IP
}
func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT }
func (s *SVCBIPv4Hint) len() int { return 4 * len(s.Hint) }
func (s *SVCBIPv4Hint) pack() ([]byte, error) {
b := make([]byte, 0, 4*len(s.Hint))
for _, e := range s.Hint {
x := e.To4()
if x == nil {
return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6")
}
b = append(b, x...)
}
return b, nil
}
func (s *SVCBIPv4Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%4 != 0 {
return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
}
x := make([]net.IP, 0, len(b)/4)
for i := 0; i < len(b); i += 4 {
x = append(x, net.IP(b[i:i+4]))
}
s.Hint = x
return nil
}
func (s *SVCBIPv4Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
x := e.To4()
if x == nil {
return "<nil>"
}
str[i] = x.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv4Hint) parse(b string) error {
if strings.Contains(b, ":") {
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e).To4()
if ip == nil {
return errors.New("dns: svcbipv4hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
hint := make([]net.IP, len(s.Hint))
for i, ip := range s.Hint {
hint[i] = copyIP(ip)
}
return &SVCBIPv4Hint{
Hint: hint,
}
}
// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
// Basic use pattern for creating an echconfig option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBECHConfig)
// e.ECH = []byte{0xfe, 0x08, ...}
// h.Value = append(h.Value, e)
type SVCBECHConfig struct {
ECH []byte
}
func (*SVCBECHConfig) Key() SVCBKey { return SVCB_ECHCONFIG }
func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
func (s *SVCBECHConfig) len() int { return len(s.ECH) }
func (s *SVCBECHConfig) pack() ([]byte, error) {
return append([]byte(nil), s.ECH...), nil
}
func (s *SVCBECHConfig) copy() SVCBKeyValue {
return &SVCBECHConfig{
append([]byte(nil), s.ECH...),
}
}
func (s *SVCBECHConfig) unpack(b []byte) error {
s.ECH = append([]byte(nil), b...)
return nil
}
func (s *SVCBECHConfig) parse(b string) error {
x, err := fromBase64([]byte(b))
if err != nil {
return errors.New("dns: svcbechconfig: bad base64 echconfig")
}
s.ECH = x
return nil
}
// SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the
// connection to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv6hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv6Hint)
// e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
// h.Value = append(h.Value, e)
type SVCBIPv6Hint struct {
Hint []net.IP
}
func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT }
func (s *SVCBIPv6Hint) len() int { return 16 * len(s.Hint) }
func (s *SVCBIPv6Hint) pack() ([]byte, error) {
b := make([]byte, 0, 16*len(s.Hint))
for _, e := range s.Hint {
if len(e) != net.IPv6len || e.To4() != nil {
return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4")
}
b = append(b, e...)
}
return b, nil
}
func (s *SVCBIPv6Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%16 != 0 {
return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
}
x := make([]net.IP, 0, len(b)/16)
for i := 0; i < len(b); i += 16 {
ip := net.IP(b[i : i+16])
if ip.To4() != nil {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
x = append(x, ip)
}
s.Hint = x
return nil
}
func (s *SVCBIPv6Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
if x := e.To4(); x != nil {
return "<nil>"
}
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv6Hint) parse(b string) error {
if strings.Contains(b, ".") {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e)
if ip == nil {
return errors.New("dns: svcbipv6hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
hint := make([]net.IP, len(s.Hint))
for i, ip := range s.Hint {
hint[i] = copyIP(ip)
}
return &SVCBIPv6Hint{
Hint: hint,
}
}
// SVCBLocal pair is intended for experimental/private use. The key is recommended
// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
// Basic use pattern for creating a keyNNNNN option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBLocal)
// e.KeyCode = 65400
// e.Data = []byte("abc")
// h.Value = append(h.Value, e)
type SVCBLocal struct {
KeyCode SVCBKey // Never 65535 or any assigned keys.
Data []byte // All byte sequences are allowed.
}
func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode }
func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
func (s *SVCBLocal) len() int { return len(s.Data) }
func (s *SVCBLocal) unpack(b []byte) error {
s.Data = append([]byte(nil), b...)
return nil
}
func (s *SVCBLocal) String() string {
var str strings.Builder
str.Grow(4 * len(s.Data))
for _, e := range s.Data {
if ' ' <= e && e <= '~' {
switch e {
case '"', ';', ' ', '\\':
str.WriteByte('\\')
str.WriteByte(e)
default:
str.WriteByte(e)
}
} else {
str.WriteString(escapeByte(e))
}
}
return str.String()
}
func (s *SVCBLocal) parse(b string) error {
data := make([]byte, 0, len(b))
for i := 0; i < len(b); {
if b[i] != '\\' {
data = append(data, b[i])
i++
continue
}
if i+1 == len(b) {
return errors.New("dns: svcblocal: svcb private/experimental key escape unterminated")
}
if isDigit(b[i+1]) {
if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
a, err := strconv.ParseUint(b[i+1:i+4], 10, 8)
if err == nil {
i += 4
data = append(data, byte(a))
continue
}
}
return errors.New("dns: svcblocal: svcb private/experimental key bad escaped octet")
} else {
data = append(data, b[i+1])
i += 2
}
}
s.Data = data
return nil
}
func (s *SVCBLocal) copy() SVCBKeyValue {
return &SVCBLocal{s.KeyCode,
append([]byte(nil), s.Data...),
}
}
func (rr *SVCB) String() string {
s := rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
sprintName(rr.Target)
for _, e := range rr.Value {
s += " " + e.Key().String() + "=\"" + e.String() + "\""
}
return s
}
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
a = append([]SVCBKeyValue(nil), a...)
b = append([]SVCBKeyValue(nil), b...)
sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
for i, e := range a {
if e.Key() != b[i].Key() {
return false
}
b1, err1 := e.pack()
b2, err2 := b[i].pack()
if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
return false
}
}
return true
}

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

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto/hmac" "crypto/hmac"
"crypto/md5"
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
@ -16,12 +15,65 @@ import (
// HMAC hashing codes. These are transmitted as domain names. // HMAC hashing codes. These are transmitted as domain names.
const ( const (
HmacMD5 = "hmac-md5.sig-alg.reg.int."
HmacSHA1 = "hmac-sha1." HmacSHA1 = "hmac-sha1."
HmacSHA224 = "hmac-sha224."
HmacSHA256 = "hmac-sha256." HmacSHA256 = "hmac-sha256."
HmacSHA384 = "hmac-sha384."
HmacSHA512 = "hmac-sha512." HmacSHA512 = "hmac-sha512."
HmacMD5 = "hmac-md5.sig-alg.reg.int." // Deprecated: HmacMD5 is no longer supported.
) )
// TsigProvider provides the API to plug-in a custom TSIG implementation.
type TsigProvider interface {
// Generate is passed the DNS message to be signed and the partial TSIG RR. It returns the signature and nil, otherwise an error.
Generate(msg []byte, t *TSIG) ([]byte, error)
// Verify is passed the DNS message to be verified and the TSIG RR. If the signature is valid it will return nil, otherwise an error.
Verify(msg []byte, t *TSIG) error
}
type tsigHMACProvider string
func (key tsigHMACProvider) Generate(msg []byte, t *TSIG) ([]byte, error) {
// If we barf here, the caller is to blame
rawsecret, err := fromBase64([]byte(key))
if err != nil {
return nil, err
}
var h hash.Hash
switch CanonicalName(t.Algorithm) {
case HmacSHA1:
h = hmac.New(sha1.New, rawsecret)
case HmacSHA224:
h = hmac.New(sha256.New224, rawsecret)
case HmacSHA256:
h = hmac.New(sha256.New, rawsecret)
case HmacSHA384:
h = hmac.New(sha512.New384, rawsecret)
case HmacSHA512:
h = hmac.New(sha512.New, rawsecret)
default:
return nil, ErrKeyAlg
}
h.Write(msg)
return h.Sum(nil), nil
}
func (key tsigHMACProvider) Verify(msg []byte, t *TSIG) error {
b, err := key.Generate(msg, t)
if err != nil {
return err
}
mac, err := hex.DecodeString(t.MAC)
if err != nil {
return err
}
if !hmac.Equal(b, mac) {
return ErrSig
}
return nil
}
// TSIG is the RR the holds the transaction signature of a message. // TSIG is the RR the holds the transaction signature of a message.
// See RFC 2845 and RFC 4635. // See RFC 2845 and RFC 4635.
type TSIG struct { type TSIG struct {
@ -54,8 +106,8 @@ func (rr *TSIG) String() string {
return s return s
} }
func (rr *TSIG) parse(c *zlexer, origin string) *ParseError { func (*TSIG) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on TSIG") return &ParseError{err: "TSIG records do not have a presentation format"}
} }
// 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.
@ -96,14 +148,13 @@ type timerWireFmt struct {
// timersOnly is false. // timersOnly is false.
// If something goes wrong an error is returned, otherwise it is nil. // If something goes wrong an error is returned, otherwise it is nil.
func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) { func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
return tsigGenerateProvider(m, tsigHMACProvider(secret), requestMAC, timersOnly)
}
func tsigGenerateProvider(m *Msg, provider TsigProvider, requestMAC string, timersOnly bool) ([]byte, string, error) {
if m.IsTsig() == nil { if m.IsTsig() == nil {
panic("dns: TSIG not last RR in additional") panic("dns: TSIG not last RR in additional")
} }
// If we barf here, the caller is to blame
rawsecret, err := fromBase64([]byte(secret))
if err != nil {
return nil, "", err
}
rr := m.Extra[len(m.Extra)-1].(*TSIG) rr := m.Extra[len(m.Extra)-1].(*TSIG)
m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg
@ -111,32 +162,21 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly) buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
if err != nil {
return nil, "", err
}
t := new(TSIG) t := new(TSIG)
var h hash.Hash // Copy all TSIG fields except MAC and its size, which are filled using the computed digest.
switch strings.ToLower(rr.Algorithm) { *t = *rr
case HmacMD5: mac, err := provider.Generate(buf, rr)
h = hmac.New(md5.New, rawsecret) if err != nil {
case HmacSHA1: return nil, "", err
h = hmac.New(sha1.New, rawsecret)
case HmacSHA256:
h = hmac.New(sha256.New, rawsecret)
case HmacSHA512:
h = hmac.New(sha512.New, rawsecret)
default:
return nil, "", ErrKeyAlg
} }
h.Write(buf) t.MAC = hex.EncodeToString(mac)
t.MAC = hex.EncodeToString(h.Sum(nil))
t.MACSize = uint16(len(t.MAC) / 2) // Size is half! t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0}
t.Fudge = rr.Fudge
t.TimeSigned = rr.TimeSigned
t.Algorithm = rr.Algorithm
t.OrigId = m.Id
tbuf := make([]byte, Len(t)) tbuf := make([]byte, Len(t))
off, err := PackRR(t, tbuf, 0, nil, false) off, err := PackRR(t, tbuf, 0, nil, false)
if err != nil { if err != nil {
@ -153,26 +193,34 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
// If the signature does not validate err contains the // If the signature does not validate err contains the
// error, otherwise it is nil. // error, otherwise it is nil.
func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error { func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
rawsecret, err := fromBase64([]byte(secret)) return tsigVerify(msg, tsigHMACProvider(secret), requestMAC, timersOnly, uint64(time.Now().Unix()))
if err != nil { }
return err
} func tsigVerifyProvider(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool) error {
return tsigVerify(msg, provider, requestMAC, timersOnly, uint64(time.Now().Unix()))
}
// actual implementation of TsigVerify, taking the current time ('now') as a parameter for the convenience of tests.
func tsigVerify(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool, now uint64) error {
// Strip the TSIG from the incoming msg // Strip the TSIG from the incoming msg
stripped, tsig, err := stripTsig(msg) stripped, tsig, err := stripTsig(msg)
if err != nil { if err != nil {
return err return err
} }
msgMAC, err := hex.DecodeString(tsig.MAC) buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
if err != nil { if err != nil {
return err return err
} }
buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly) if err := provider.Verify(buf, tsig); err != nil {
return err
}
// Fudge factor works both ways. A message can arrive before it was signed because // Fudge factor works both ways. A message can arrive before it was signed because
// of clock skew. // of clock skew.
now := uint64(time.Now().Unix()) // We check this after verifying the signature, following draft-ietf-dnsop-rfc2845bis
// instead of RFC2845, in order to prevent a security vulnerability as reported in CVE-2017-3142/3143.
ti := now - tsig.TimeSigned ti := now - tsig.TimeSigned
if now < tsig.TimeSigned { if now < tsig.TimeSigned {
ti = tsig.TimeSigned - now ti = tsig.TimeSigned - now
@ -181,28 +229,11 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
return ErrTime return ErrTime
} }
var h hash.Hash
switch strings.ToLower(tsig.Algorithm) {
case HmacMD5:
h = hmac.New(md5.New, rawsecret)
case HmacSHA1:
h = hmac.New(sha1.New, rawsecret)
case HmacSHA256:
h = hmac.New(sha256.New, rawsecret)
case HmacSHA512:
h = hmac.New(sha512.New, rawsecret)
default:
return ErrKeyAlg
}
h.Write(buf)
if !hmac.Equal(h.Sum(nil), msgMAC) {
return ErrSig
}
return nil return nil
} }
// Create a wiredata buffer for the MAC calculation. // Create a wiredata buffer for the MAC calculation.
func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []byte { func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) ([]byte, error) {
var buf []byte var buf []byte
if rr.TimeSigned == 0 { if rr.TimeSigned == 0 {
rr.TimeSigned = uint64(time.Now().Unix()) rr.TimeSigned = uint64(time.Now().Unix())
@ -219,7 +250,10 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
m.MACSize = uint16(len(requestMAC) / 2) m.MACSize = uint16(len(requestMAC) / 2)
m.MAC = requestMAC m.MAC = requestMAC
buf = make([]byte, len(requestMAC)) // long enough buf = make([]byte, len(requestMAC)) // long enough
n, _ := packMacWire(m, buf) n, err := packMacWire(m, buf)
if err != nil {
return nil, err
}
buf = buf[:n] buf = buf[:n]
} }
@ -228,20 +262,26 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
tsig := new(timerWireFmt) tsig := new(timerWireFmt)
tsig.TimeSigned = rr.TimeSigned tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge tsig.Fudge = rr.Fudge
n, _ := packTimerWire(tsig, tsigvar) n, err := packTimerWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} else { } else {
tsig := new(tsigWireFmt) tsig := new(tsigWireFmt)
tsig.Name = strings.ToLower(rr.Hdr.Name) tsig.Name = CanonicalName(rr.Hdr.Name)
tsig.Class = ClassANY tsig.Class = ClassANY
tsig.Ttl = rr.Hdr.Ttl tsig.Ttl = rr.Hdr.Ttl
tsig.Algorithm = strings.ToLower(rr.Algorithm) tsig.Algorithm = CanonicalName(rr.Algorithm)
tsig.TimeSigned = rr.TimeSigned tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge tsig.Fudge = rr.Fudge
tsig.Error = rr.Error tsig.Error = rr.Error
tsig.OtherLen = rr.OtherLen tsig.OtherLen = rr.OtherLen
tsig.OtherData = rr.OtherData tsig.OtherData = rr.OtherData
n, _ := packTsigWire(tsig, tsigvar) n, err := packTsigWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} }
@ -251,7 +291,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
} else { } else {
buf = append(msgbuf, tsigvar...) buf = append(msgbuf, tsigvar...)
} }
return buf return buf, nil
} }
// Strip the TSIG from the raw message. // Strip the TSIG from the raw message.

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

@ -81,6 +81,9 @@ const (
TypeCDNSKEY uint16 = 60 TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61 TypeOPENPGPKEY uint16 = 61
TypeCSYNC uint16 = 62 TypeCSYNC uint16 = 62
TypeZONEMD uint16 = 63
TypeSVCB uint16 = 64
TypeHTTPS uint16 = 65
TypeSPF uint16 = 99 TypeSPF uint16 = 99
TypeUINFO uint16 = 100 TypeUINFO uint16 = 100
TypeUID uint16 = 101 TypeUID uint16 = 101
@ -148,6 +151,14 @@ const (
OpcodeUpdate = 5 OpcodeUpdate = 5
) )
// Used in ZONEMD https://tools.ietf.org/html/rfc8976
const (
ZoneMDSchemeSimple = 1
ZoneMDHashAlgSHA384 = 1
ZoneMDHashAlgSHA512 = 2
)
// Header is the wire format for the DNS packet header. // Header is the wire format for the DNS packet header.
type Header struct { type Header struct {
Id uint16 Id uint16
@ -165,11 +176,11 @@ const (
_RD = 1 << 8 // recursion desired _RD = 1 << 8 // recursion desired
_RA = 1 << 7 // recursion available _RA = 1 << 7 // recursion available
_Z = 1 << 6 // Z _Z = 1 << 6 // Z
_AD = 1 << 5 // authticated data _AD = 1 << 5 // authenticated data
_CD = 1 << 4 // checking disabled _CD = 1 << 4 // checking disabled
) )
// Various constants used in the LOC RR, See RFC 1887. // Various constants used in the LOC RR. See RFC 1887.
const ( const (
LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2. LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2. LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
@ -209,8 +220,11 @@ var CertTypeToString = map[uint16]string{
//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. Usually there is just one. While the
// question section of a message. Usually there is just one. // original DNS RFCs allow multiple questions in the question section of a
// message, in practice it never works. Because most DNS servers see multiple
// questions as an error, it is recommended to only have one question per
// message.
type Question struct { type Question struct {
Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed) Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
Qtype uint16 Qtype uint16
@ -231,7 +245,7 @@ func (q *Question) String() (s string) {
return s return s
} }
// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY // ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
// is named "*" there. // is named "*" there.
type ANY struct { type ANY struct {
Hdr RR_Header Hdr RR_Header
@ -240,8 +254,8 @@ 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 { func (*ANY) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on ANY") return &ParseError{err: "ANY records do not have a presentation format"}
} }
// NULL RR. See RFC 1035. // NULL RR. See RFC 1035.
@ -255,8 +269,8 @@ func (rr *NULL) String() string {
return ";" + rr.Hdr.String() + rr.Data return ";" + rr.Hdr.String() + rr.Data
} }
func (rr *NULL) parse(c *zlexer, origin string) *ParseError { func (*NULL) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on NULL") return &ParseError{err: "NULL records do not have a presentation format"}
} }
// CNAME RR. See RFC 1034. // CNAME RR. See RFC 1034.
@ -442,45 +456,38 @@ func sprintName(s string) string {
var dst strings.Builder var dst strings.Builder
for i := 0; i < len(s); { for i := 0; i < len(s); {
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { if s[i] == '.' {
if dst.Len() != 0 { if dst.Len() != 0 {
dst.WriteString(s[i : i+2]) dst.WriteByte('.')
} }
i += 2 i++
continue continue
} }
b, n := nextByte(s, i) b, n := nextByte(s, i)
if n == 0 { if n == 0 {
i++ // Drop "dangling" incomplete escapes.
continue if dst.Len() == 0 {
} return s[:i]
if b == '.' {
if dst.Len() != 0 {
dst.WriteByte('.')
} }
i += n break
continue
} }
switch b { if isDomainNameLabelSpecial(b) {
case ' ', '\'', '@', ';', '(', ')', '"', '\\': // additional chars to escape
if dst.Len() == 0 { if dst.Len() == 0 {
dst.Grow(len(s) * 2) dst.Grow(len(s) * 2)
dst.WriteString(s[:i]) dst.WriteString(s[:i])
} }
dst.WriteByte('\\') dst.WriteByte('\\')
dst.WriteByte(b) dst.WriteByte(b)
default: } else if b < ' ' || b > '~' { // unprintable, use \DDD
if ' ' <= b && b <= '~' { if dst.Len() == 0 {
if dst.Len() != 0 { dst.Grow(len(s) * 2)
dst.WriteByte(b) dst.WriteString(s[:i])
} }
} else { dst.WriteString(escapeByte(b))
if dst.Len() == 0 { } else {
dst.Grow(len(s) * 2) if dst.Len() != 0 {
dst.WriteString(s[:i]) dst.WriteByte(b)
}
dst.WriteString(escapeByte(b))
} }
} }
i += n i += n
@ -503,15 +510,10 @@ func sprintTxtOctet(s string) string {
} }
b, n := nextByte(s, i) b, n := nextByte(s, i)
switch { if n == 0 {
case n == 0:
i++ // dangling back slash i++ // dangling back slash
case b == '.': } else {
dst.WriteByte('.') writeTXTStringByte(&dst, b)
case b < ' ' || b > '~':
dst.WriteString(escapeByte(b))
default:
dst.WriteByte(b)
} }
i += n i += n
} }
@ -587,6 +589,17 @@ func escapeByte(b byte) string {
return escapedByteLarge[int(b)*4 : int(b)*4+4] return escapedByteLarge[int(b)*4 : int(b)*4+4]
} }
// isDomainNameLabelSpecial returns true if
// a domain name label byte should be prefixed
// with an escaping backslash.
func isDomainNameLabelSpecial(b byte) bool {
switch b {
case '.', ' ', '\'', '@', ';', '(', ')', '"', '\\':
return true
}
return false
}
func nextByte(s string, offset int) (byte, int) { func nextByte(s string, offset int) (byte, int) {
if offset >= len(s) { if offset >= len(s) {
return 0, 0 return 0, 0
@ -759,8 +772,8 @@ type LOC struct {
Altitude uint32 Altitude uint32
} }
// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent // cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
// format and returns a string in m (two decimals for the cm) // format and returns a string in m (two decimals for the cm).
func cmToM(m, e uint8) string { func cmToM(m, e uint8) string {
if e < 2 { if e < 2 {
if e == 1 { if e == 1 {
@ -1118,6 +1131,7 @@ type URI struct {
Target string `dns:"octet"` Target string `dns:"octet"`
} }
// rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
func (rr *URI) String() string { func (rr *URI) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) + return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target) " " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
@ -1279,6 +1293,7 @@ type CAA struct {
Value string `dns:"octet"` Value string `dns:"octet"`
} }
// rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
func (rr *CAA) String() string { func (rr *CAA) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value) return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
} }
@ -1355,6 +1370,23 @@ func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
return l return l
} }
// ZONEMD RR, from draft-ietf-dnsop-dns-zone-digest
type ZONEMD struct {
Hdr RR_Header
Serial uint32
Scheme uint8
Hash uint8
Digest string `dns:"hex"`
}
func (rr *ZONEMD) String() string {
return rr.Hdr.String() +
strconv.Itoa(int(rr.Serial)) +
" " + strconv.Itoa(int(rr.Scheme)) +
" " + strconv.Itoa(int(rr.Hash)) +
" " + rr.Digest
}
// APL RR. See RFC 3123. // APL RR. See RFC 3123.
type APL struct { type APL struct {
Hdr RR_Header Hdr RR_Header
@ -1381,13 +1413,13 @@ func (rr *APL) String() string {
} }
// str returns presentation form of the APL prefix. // str returns presentation form of the APL prefix.
func (p *APLPrefix) str() string { func (a *APLPrefix) str() string {
var sb strings.Builder var sb strings.Builder
if p.Negation { if a.Negation {
sb.WriteByte('!') sb.WriteByte('!')
} }
switch len(p.Network.IP) { switch len(a.Network.IP) {
case net.IPv4len: case net.IPv4len:
sb.WriteByte('1') sb.WriteByte('1')
case net.IPv6len: case net.IPv6len:
@ -1396,20 +1428,20 @@ func (p *APLPrefix) str() string {
sb.WriteByte(':') sb.WriteByte(':')
switch len(p.Network.IP) { switch len(a.Network.IP) {
case net.IPv4len: case net.IPv4len:
sb.WriteString(p.Network.IP.String()) sb.WriteString(a.Network.IP.String())
case net.IPv6len: case net.IPv6len:
// add prefix for IPv4-mapped IPv6 // add prefix for IPv4-mapped IPv6
if v4 := p.Network.IP.To4(); v4 != nil { if v4 := a.Network.IP.To4(); v4 != nil {
sb.WriteString("::ffff:") sb.WriteString("::ffff:")
} }
sb.WriteString(p.Network.IP.String()) sb.WriteString(a.Network.IP.String())
} }
sb.WriteByte('/') sb.WriteByte('/')
prefix, _ := p.Network.Mask.Size() prefix, _ := a.Network.Mask.Size()
sb.WriteString(strconv.Itoa(prefix)) sb.WriteString(strconv.Itoa(prefix))
return sb.String() return sb.String()
@ -1423,17 +1455,17 @@ func (a *APLPrefix) equals(b *APLPrefix) bool {
} }
// copy returns a copy of the APL prefix. // copy returns a copy of the APL prefix.
func (p *APLPrefix) copy() APLPrefix { func (a *APLPrefix) copy() APLPrefix {
return APLPrefix{ return APLPrefix{
Negation: p.Negation, Negation: a.Negation,
Network: copyNet(p.Network), Network: copyNet(a.Network),
} }
} }
// len returns size of the prefix in wire format. // len returns size of the prefix in wire format.
func (p *APLPrefix) len() int { func (a *APLPrefix) len() int {
// 4-byte header and the network address prefix (see Section 4 of RFC 3123) // 4-byte header and the network address prefix (see Section 4 of RFC 3123)
prefix, _ := p.Network.Mask.Size() prefix, _ := a.Network.Mask.Size()
return 4 + (prefix+7)/8 return 4 + (prefix+7)/8
} }
@ -1466,7 +1498,7 @@ func StringToTime(s string) (uint32, error) {
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty. // saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
func saltToString(s string) string { func saltToString(s string) string {
if len(s) == 0 { if s == "" {
return "-" return "-"
} }
return strings.ToUpper(s) return strings.ToUpper(s)

View File

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

View File

@ -104,6 +104,48 @@ func (r1 *CAA) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *CDNSKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDNSKEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *CDS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDS)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *CERT) isDuplicate(_r2 RR) bool { func (r1 *CERT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CERT) r2, ok := _r2.(*CERT)
if !ok { if !ok {
@ -172,6 +214,27 @@ func (r1 *DHCID) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *DLV) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DLV)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *DNAME) isDuplicate(_r2 RR) bool { func (r1 *DNAME) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DNAME) r2, ok := _r2.(*DNAME)
if !ok { if !ok {
@ -339,6 +402,48 @@ func (r1 *HIP) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HTTPS)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *KEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *KX) isDuplicate(_r2 RR) bool { func (r1 *KX) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KX) r2, ok := _r2.(*KX)
if !ok { if !ok {
@ -849,6 +954,42 @@ func (r1 *RT) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *SIG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SIG)
if !ok {
return false
}
_ = r2
if r1.TypeCovered != r2.TypeCovered {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Labels != r2.Labels {
return false
}
if r1.OrigTtl != r2.OrigTtl {
return false
}
if r1.Expiration != r2.Expiration {
return false
}
if r1.Inception != r2.Inception {
return false
}
if r1.KeyTag != r2.KeyTag {
return false
}
if !isDuplicateName(r1.SignerName, r2.SignerName) {
return false
}
if r1.Signature != r2.Signature {
return false
}
return true
}
func (r1 *SMIMEA) isDuplicate(_r2 RR) bool { func (r1 *SMIMEA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SMIMEA) r2, ok := _r2.(*SMIMEA)
if !ok { if !ok {
@ -956,6 +1097,27 @@ func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *SVCB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SVCB)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *TA) isDuplicate(_r2 RR) bool { func (r1 *TA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TA) r2, ok := _r2.(*TA)
if !ok { if !ok {
@ -1155,3 +1317,24 @@ func (r1 *X25) isDuplicate(_r2 RR) bool {
} }
return true return true
} }
func (r1 *ZONEMD) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*ZONEMD)
if !ok {
return false
}
_ = r2
if r1.Serial != r2.Serial {
return false
}
if r1.Scheme != r2.Scheme {
return false
}
if r1.Hash != r2.Hash {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}

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

@ -316,6 +316,22 @@ func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bo
return off, nil return off, nil
} }
func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off) off, err = packUint16(rr.Flags, msg, off)
if err != nil { if err != nil {
@ -906,6 +922,22 @@ func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress
return off, nil return off, nil
} }
func (rr *SVCB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off) off, err = packUint16(rr.KeyTag, msg, off)
if err != nil { if err != nil {
@ -1086,6 +1118,26 @@ func (rr *X25) pack(msg []byte, off int, compression compressionMap, compress bo
return off, nil return off, nil
} }
func (rr *ZONEMD) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint32(rr.Serial, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Scheme, msg, off)
if err != nil {
return off, err
}
off, err = packUint8(rr.Hash, msg, off)
if err != nil {
return off, err
}
off, err = packStringHex(rr.Digest, msg, off)
if err != nil {
return off, err
}
return off, nil
}
// unpack*() functions // unpack*() functions
func (rr *A) unpack(msg []byte, off int) (off1 int, err error) { func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
@ -1559,6 +1611,31 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) { func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart
@ -2461,6 +2538,31 @@ func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) { func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart
@ -2739,3 +2841,35 @@ func (rr *X25) unpack(msg []byte, off int) (off1 int, err error) {
} }
return off, nil return off, nil
} }
func (rr *ZONEMD) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Serial, off, err = unpackUint32(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Scheme, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Hash, off, err = unpackUint8(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
if err != nil {
return off, err
}
return off, nil
}

View File

@ -33,6 +33,7 @@ var TypeToRR = map[uint16]func() RR{
TypeGPOS: func() RR { return new(GPOS) }, TypeGPOS: func() RR { return new(GPOS) },
TypeHINFO: func() RR { return new(HINFO) }, TypeHINFO: func() RR { return new(HINFO) },
TypeHIP: func() RR { return new(HIP) }, TypeHIP: func() RR { return new(HIP) },
TypeHTTPS: func() RR { return new(HTTPS) },
TypeKEY: func() RR { return new(KEY) }, TypeKEY: func() RR { return new(KEY) },
TypeKX: func() RR { return new(KX) }, TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) }, TypeL32: func() RR { return new(L32) },
@ -70,6 +71,7 @@ var TypeToRR = map[uint16]func() RR{
TypeSPF: func() RR { return new(SPF) }, TypeSPF: func() RR { return new(SPF) },
TypeSRV: func() RR { return new(SRV) }, TypeSRV: func() RR { return new(SRV) },
TypeSSHFP: func() RR { return new(SSHFP) }, TypeSSHFP: func() RR { return new(SSHFP) },
TypeSVCB: func() RR { return new(SVCB) },
TypeTA: func() RR { return new(TA) }, TypeTA: func() RR { return new(TA) },
TypeTALINK: func() RR { return new(TALINK) }, TypeTALINK: func() RR { return new(TALINK) },
TypeTKEY: func() RR { return new(TKEY) }, TypeTKEY: func() RR { return new(TKEY) },
@ -80,6 +82,7 @@ var TypeToRR = map[uint16]func() RR{
TypeUINFO: func() RR { return new(UINFO) }, TypeUINFO: func() RR { return new(UINFO) },
TypeURI: func() RR { return new(URI) }, TypeURI: func() RR { return new(URI) },
TypeX25: func() RR { return new(X25) }, TypeX25: func() RR { return new(X25) },
TypeZONEMD: func() RR { return new(ZONEMD) },
} }
// TypeToString is a map of strings for each RR type. // TypeToString is a map of strings for each RR type.
@ -110,6 +113,7 @@ var TypeToString = map[uint16]string{
TypeGPOS: "GPOS", TypeGPOS: "GPOS",
TypeHINFO: "HINFO", TypeHINFO: "HINFO",
TypeHIP: "HIP", TypeHIP: "HIP",
TypeHTTPS: "HTTPS",
TypeISDN: "ISDN", TypeISDN: "ISDN",
TypeIXFR: "IXFR", TypeIXFR: "IXFR",
TypeKEY: "KEY", TypeKEY: "KEY",
@ -153,6 +157,7 @@ var TypeToString = map[uint16]string{
TypeSPF: "SPF", TypeSPF: "SPF",
TypeSRV: "SRV", TypeSRV: "SRV",
TypeSSHFP: "SSHFP", TypeSSHFP: "SSHFP",
TypeSVCB: "SVCB",
TypeTA: "TA", TypeTA: "TA",
TypeTALINK: "TALINK", TypeTALINK: "TALINK",
TypeTKEY: "TKEY", TypeTKEY: "TKEY",
@ -164,6 +169,7 @@ var TypeToString = map[uint16]string{
TypeUNSPEC: "UNSPEC", TypeUNSPEC: "UNSPEC",
TypeURI: "URI", TypeURI: "URI",
TypeX25: "X25", TypeX25: "X25",
TypeZONEMD: "ZONEMD",
TypeNSAPPTR: "NSAP-PTR", TypeNSAPPTR: "NSAP-PTR",
} }
@ -191,6 +197,7 @@ func (rr *GID) Header() *RR_Header { return &rr.Hdr }
func (rr *GPOS) Header() *RR_Header { return &rr.Hdr } func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
func (rr *HINFO) Header() *RR_Header { return &rr.Hdr } func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *HIP) Header() *RR_Header { return &rr.Hdr } func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr }
func (rr *KEY) Header() *RR_Header { return &rr.Hdr } func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
func (rr *KX) Header() *RR_Header { return &rr.Hdr } func (rr *KX) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) Header() *RR_Header { return &rr.Hdr } func (rr *L32) Header() *RR_Header { return &rr.Hdr }
@ -229,6 +236,7 @@ func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
func (rr *SPF) Header() *RR_Header { return &rr.Hdr } func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
func (rr *SRV) Header() *RR_Header { return &rr.Hdr } func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr } func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
func (rr *SVCB) Header() *RR_Header { return &rr.Hdr }
func (rr *TA) Header() *RR_Header { return &rr.Hdr } func (rr *TA) Header() *RR_Header { return &rr.Hdr }
func (rr *TALINK) Header() *RR_Header { return &rr.Hdr } func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
func (rr *TKEY) Header() *RR_Header { return &rr.Hdr } func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
@ -239,6 +247,7 @@ func (rr *UID) Header() *RR_Header { return &rr.Hdr }
func (rr *UINFO) Header() *RR_Header { return &rr.Hdr } func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *URI) Header() *RR_Header { return &rr.Hdr } 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 }
func (rr *ZONEMD) Header() *RR_Header { return &rr.Hdr }
// len() functions // len() functions
func (rr *A) len(off int, compression map[string]struct{}) int { func (rr *A) len(off int, compression map[string]struct{}) int {
@ -592,6 +601,15 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
l += len(rr.FingerPrint) / 2 l += len(rr.FingerPrint) / 2
return l return l
} }
func (rr *SVCB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += domainNameLen(rr.Target, off+l, compression, false)
for _, x := range rr.Value {
l += 4 + int(x.len())
}
return l
}
func (rr *TA) len(off int, compression map[string]struct{}) int { func (rr *TA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += 2 // KeyTag l += 2 // KeyTag
@ -669,6 +687,14 @@ func (rr *X25) len(off int, compression map[string]struct{}) int {
l += len(rr.PSDNAddress) + 1 l += len(rr.PSDNAddress) + 1
return l return l
} }
func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 4 // Serial
l++ // Scheme
l++ // Hash
l += len(rr.Digest) / 2
return l
}
// copy() functions // copy() functions
func (rr *A) copy() RR { func (rr *A) copy() RR {
@ -685,8 +711,8 @@ func (rr *ANY) copy() RR {
} }
func (rr *APL) copy() RR { func (rr *APL) copy() RR {
Prefixes := make([]APLPrefix, len(rr.Prefixes)) Prefixes := make([]APLPrefix, len(rr.Prefixes))
for i := range rr.Prefixes { for i, e := range rr.Prefixes {
Prefixes[i] = rr.Prefixes[i].copy() Prefixes[i] = e.copy()
} }
return &APL{rr.Hdr, Prefixes} return &APL{rr.Hdr, Prefixes}
} }
@ -698,6 +724,12 @@ func (rr *AVC) copy() RR {
func (rr *CAA) copy() RR { func (rr *CAA) copy() RR {
return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value} return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
} }
func (rr *CDNSKEY) copy() RR {
return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *CDS) copy() RR {
return &CDS{*rr.DS.copy().(*DS)}
}
func (rr *CERT) copy() RR { func (rr *CERT) copy() RR {
return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
} }
@ -712,6 +744,9 @@ func (rr *CSYNC) copy() RR {
func (rr *DHCID) copy() RR { func (rr *DHCID) copy() RR {
return &DHCID{rr.Hdr, rr.Digest} return &DHCID{rr.Hdr, rr.Digest}
} }
func (rr *DLV) copy() RR {
return &DLV{*rr.DS.copy().(*DS)}
}
func (rr *DNAME) copy() RR { func (rr *DNAME) copy() RR {
return &DNAME{rr.Hdr, rr.Target} return &DNAME{rr.Hdr, rr.Target}
} }
@ -744,6 +779,12 @@ func (rr *HIP) copy() RR {
copy(RendezvousServers, rr.RendezvousServers) copy(RendezvousServers, rr.RendezvousServers)
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
} }
func (rr *HTTPS) copy() RR {
return &HTTPS{*rr.SVCB.copy().(*SVCB)}
}
func (rr *KEY) copy() RR {
return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *KX) copy() RR { func (rr *KX) copy() RR {
return &KX{rr.Hdr, rr.Preference, rr.Exchanger} return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
} }
@ -847,6 +888,9 @@ func (rr *RRSIG) copy() RR {
func (rr *RT) copy() RR { func (rr *RT) copy() RR {
return &RT{rr.Hdr, rr.Preference, rr.Host} return &RT{rr.Hdr, rr.Preference, rr.Host}
} }
func (rr *SIG) copy() RR {
return &SIG{*rr.RRSIG.copy().(*RRSIG)}
}
func (rr *SMIMEA) copy() RR { func (rr *SMIMEA) copy() RR {
return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
} }
@ -864,6 +908,13 @@ func (rr *SRV) copy() RR {
func (rr *SSHFP) copy() RR { func (rr *SSHFP) copy() RR {
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint} return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
} }
func (rr *SVCB) copy() RR {
Value := make([]SVCBKeyValue, len(rr.Value))
for i, e := range rr.Value {
Value[i] = e.copy()
}
return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
}
func (rr *TA) copy() RR { func (rr *TA) copy() RR {
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
} }
@ -896,3 +947,6 @@ func (rr *URI) copy() RR {
func (rr *X25) copy() RR { func (rr *X25) copy() RR {
return &X25{rr.Hdr, rr.PSDNAddress} return &X25{rr.Hdr, rr.PSDNAddress}
} }
func (rr *ZONEMD) copy() RR {
return &ZONEMD{rr.Hdr, rr.Serial, rr.Scheme, rr.Hash, rr.Digest}
}

3
vendor/golang.org/x/crypto/AUTHORS generated vendored
View File

@ -1,3 +0,0 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at https://tip.golang.org/AUTHORS.

View File

@ -1,3 +0,0 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at https://tip.golang.org/CONTRIBUTORS.

27
vendor/golang.org/x/crypto/LICENSE generated vendored
View File

@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/crypto/PATENTS generated vendored
View File

@ -1,22 +0,0 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

View File

@ -1,222 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// In Go 1.13, the ed25519 package was promoted to the standard library as
// crypto/ed25519, and this package became a wrapper for the standard library one.
//
// +build !go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
package ed25519
// This code is a port of the public domain, “ref10” implementation of ed25519
// from SUPERCOP.
import (
"bytes"
"crypto"
cryptorand "crypto/rand"
"crypto/sha512"
"errors"
"io"
"strconv"
"golang.org/x/crypto/ed25519/internal/edwards25519"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
type PrivateKey []byte
// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
publicKey := make([]byte, PublicKeySize)
copy(publicKey, priv[32:])
return PublicKey(publicKey)
}
// Seed returns the private key seed corresponding to priv. It is provided for
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
// in this package.
func (priv PrivateKey) Seed() []byte {
seed := make([]byte, SeedSize)
copy(seed, priv[:32])
return seed
}
// Sign signs the given message with priv.
// Ed25519 performs two passes over messages to be signed and therefore cannot
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
// indicate the message hasn't been hashed. This can be achieved by passing
// crypto.Hash(0) as the value for opts.
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
if opts.HashFunc() != crypto.Hash(0) {
return nil, errors.New("ed25519: cannot sign hashed message")
}
return Sign(priv, message), nil
}
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptorand.Reader
}
seed := make([]byte, SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
return nil, nil, err
}
privateKey := NewKeyFromSeed(seed)
publicKey := make([]byte, PublicKeySize)
copy(publicKey, privateKey[32:])
return publicKey, privateKey, nil
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
digest := sha512.Sum512(seed)
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
var A edwards25519.ExtendedGroupElement
var hBytes [32]byte
copy(hBytes[:], digest[:])
edwards25519.GeScalarMultBase(&A, &hBytes)
var publicKeyBytes [32]byte
A.ToBytes(&publicKeyBytes)
privateKey := make([]byte, PrivateKeySize)
copy(privateKey, seed)
copy(privateKey[32:], publicKeyBytes[:])
return privateKey
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
h := sha512.New()
h.Write(privateKey[:32])
var digest1, messageDigest, hramDigest [64]byte
var expandedSecretKey [32]byte
h.Sum(digest1[:0])
copy(expandedSecretKey[:], digest1[:])
expandedSecretKey[0] &= 248
expandedSecretKey[31] &= 63
expandedSecretKey[31] |= 64
h.Reset()
h.Write(digest1[32:])
h.Write(message)
h.Sum(messageDigest[:0])
var messageDigestReduced [32]byte
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
var R edwards25519.ExtendedGroupElement
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
var encodedR [32]byte
R.ToBytes(&encodedR)
h.Reset()
h.Write(encodedR[:])
h.Write(privateKey[32:])
h.Write(message)
h.Sum(hramDigest[:0])
var hramDigestReduced [32]byte
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
var s [32]byte
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
signature := make([]byte, SignatureSize)
copy(signature[:], encodedR[:])
copy(signature[32:], s[:])
return signature
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
if l := len(publicKey); l != PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
if len(sig) != SignatureSize || sig[63]&224 != 0 {
return false
}
var A edwards25519.ExtendedGroupElement
var publicKeyBytes [32]byte
copy(publicKeyBytes[:], publicKey)
if !A.FromBytes(&publicKeyBytes) {
return false
}
edwards25519.FeNeg(&A.X, &A.X)
edwards25519.FeNeg(&A.T, &A.T)
h := sha512.New()
h.Write(sig[:32])
h.Write(publicKey[:])
h.Write(message)
var digest [64]byte
h.Sum(digest[:0])
var hReduced [32]byte
edwards25519.ScReduce(&hReduced, &digest)
var R edwards25519.ProjectiveGroupElement
var s [32]byte
copy(s[:], sig[32:])
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
// the range [0, order) in order to prevent signature malleability.
if !edwards25519.ScMinimal(&s) {
return false
}
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
var checkR [32]byte
R.ToBytes(&checkR)
return bytes.Equal(sig[:32], checkR[:])
}

View File

@ -1,73 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
// Beginning with Go 1.13, the functionality of this package was moved to the
// standard library as crypto/ed25519. This package only acts as a compatibility
// wrapper.
package ed25519
import (
"crypto/ed25519"
"io"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
//
// This type is an alias for crypto/ed25519's PublicKey type.
// See the crypto/ed25519 package for the methods on this type.
type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
//
// This type is an alias for crypto/ed25519's PrivateKey type.
// See the crypto/ed25519 package for the methods on this type.
type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,8 @@
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package socket package socket

View File

@ -2,6 +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.
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
// +build aix darwin dragonfly freebsd netbsd openbsd // +build aix darwin dragonfly freebsd netbsd openbsd
package socket package socket

View File

@ -2,7 +2,8 @@
// 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 arm mips mipsle 386 //go:build (arm || mips || mipsle || 386 || ppc) && linux
// +build arm mips mipsle 386 ppc
// +build linux // +build linux
package socket package socket

View File

@ -2,6 +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.
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux // +build linux

View File

@ -2,8 +2,8 @@
// 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 //go:build amd64 && solaris
// +build solaris // +build amd64,solaris
package socket package socket

View File

@ -2,13 +2,24 @@
// 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
package socket package socket
type cmsghdr struct{} func controlHeaderLen() int {
return 0
}
const sizeofCmsghdr = 0 func controlMessageLen(dataLen int) int {
return 0
}
func controlMessageSpace(dataLen int) int {
return 0
}
type cmsghdr struct{}
func (h *cmsghdr) len() int { return 0 } func (h *cmsghdr) len() int { return 0 }
func (h *cmsghdr) lvl() int { return 0 } func (h *cmsghdr) lvl() int { return 0 }

View File

@ -0,0 +1,22 @@
// Copyright 2020 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.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
import "golang.org/x/sys/unix"
func controlHeaderLen() int {
return unix.CmsgLen(0)
}
func controlMessageLen(dataLen int) int {
return unix.CmsgLen(dataLen)
}
func controlMessageSpace(dataLen int) int {
return unix.CmsgSpace(dataLen)
}

View File

@ -0,0 +1,25 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socket
import "syscall"
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = int32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
func controlHeaderLen() int {
return syscall.CmsgLen(0)
}
func controlMessageLen(dataLen int) int {
return syscall.CmsgLen(dataLen)
}
func controlMessageSpace(dataLen int) int {
return syscall.CmsgSpace(dataLen)
}

View File

@ -0,0 +1,26 @@
// Copyright 2021 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.
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
import (
"syscall"
)
// ioComplete checks the flags and result of a syscall, to be used as return
// value in a syscall.RawConn.Read or Write callback.
func ioComplete(flags int, operr error) bool {
if flags&syscall.MSG_DONTWAIT != 0 {
// Caller explicitly said don't wait, so always return immediately.
return true
}
if operr == syscall.EAGAIN || operr == syscall.EWOULDBLOCK {
// No data available, block for I/O and try again.
return false
}
return true
}

View File

@ -0,0 +1,22 @@
// Copyright 2021 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.
//go:build aix || windows || zos
// +build aix windows zos
package socket
import (
"syscall"
)
// ioComplete checks the flags and result of a syscall, to be used as return
// value in a syscall.RawConn.Read or Write callback.
func ioComplete(flags int, operr error) bool {
if operr == syscall.EAGAIN || operr == syscall.EWOULDBLOCK {
// No data available, block for I/O and try again.
return false
}
return true
}

View File

@ -2,7 +2,8 @@
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package socket package socket

View File

@ -2,7 +2,8 @@
// 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 arm mips mipsle 386 //go:build (arm || mips || mipsle || 386 || ppc) && (darwin || dragonfly || freebsd || linux || netbsd || openbsd)
// +build arm mips mipsle 386 ppc
// +build darwin dragonfly freebsd linux netbsd openbsd // +build darwin dragonfly freebsd linux netbsd openbsd
package socket package socket

View File

@ -2,8 +2,9 @@
// 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.
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos)
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build aix darwin dragonfly freebsd linux netbsd openbsd // +build aix darwin dragonfly freebsd linux netbsd openbsd zos
package socket package socket

View File

@ -2,8 +2,8 @@
// 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 //go:build amd64 && solaris
// +build solaris // +build amd64,solaris
package socket package socket

View File

@ -2,7 +2,8 @@
// 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
package socket package socket

View File

@ -2,6 +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.
//go:build !aix && !linux && !netbsd
// +build !aix,!linux,!netbsd // +build !aix,!linux,!netbsd
package socket package socket

View File

@ -2,29 +2,18 @@
// 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.
//go:build aix || linux || netbsd
// +build aix linux netbsd // +build aix linux netbsd
package socket package socket
import "net" import (
"net"
"sync"
)
type mmsghdrs []mmsghdr type mmsghdrs []mmsghdr
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
for i := range hs {
vs := make([]iovec, len(ms[i].Buffers))
var sa []byte
if parseFn != nil {
sa = make([]byte, sizeofSockaddrInet6)
}
if marshalFn != nil {
sa = marshalFn(ms[i].Addr)
}
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
}
return nil
}
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error { func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
for i := range hs { for i := range hs {
ms[i].N = int(hs[i].Len) ms[i].N = int(hs[i].Len)
@ -40,3 +29,86 @@ func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr,
} }
return nil return nil
} }
// mmsghdrsPacker packs Message-slices into mmsghdrs (re-)using pre-allocated buffers.
type mmsghdrsPacker struct {
// hs are the pre-allocated mmsghdrs.
hs mmsghdrs
// sockaddrs is the pre-allocated buffer for the Hdr.Name buffers.
// We use one large buffer for all messages and slice it up.
sockaddrs []byte
// vs are the pre-allocated iovecs.
// We allocate one large buffer for all messages and slice it up. This allows to reuse the buffer
// if the number of buffers per message is distributed differently between calls.
vs []iovec
}
func (p *mmsghdrsPacker) prepare(ms []Message) {
n := len(ms)
if n <= cap(p.hs) {
p.hs = p.hs[:n]
} else {
p.hs = make(mmsghdrs, n)
}
if n*sizeofSockaddrInet6 <= cap(p.sockaddrs) {
p.sockaddrs = p.sockaddrs[:n*sizeofSockaddrInet6]
} else {
p.sockaddrs = make([]byte, n*sizeofSockaddrInet6)
}
nb := 0
for _, m := range ms {
nb += len(m.Buffers)
}
if nb <= cap(p.vs) {
p.vs = p.vs[:nb]
} else {
p.vs = make([]iovec, nb)
}
}
func (p *mmsghdrsPacker) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr, []byte) int) mmsghdrs {
p.prepare(ms)
hs := p.hs
vsRest := p.vs
saRest := p.sockaddrs
for i := range hs {
nvs := len(ms[i].Buffers)
vs := vsRest[:nvs]
vsRest = vsRest[nvs:]
var sa []byte
if parseFn != nil {
sa = saRest[:sizeofSockaddrInet6]
saRest = saRest[sizeofSockaddrInet6:]
} else if marshalFn != nil {
n := marshalFn(ms[i].Addr, saRest)
if n > 0 {
sa = saRest[:n]
saRest = saRest[n:]
}
}
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
}
return hs
}
var defaultMmsghdrsPool = mmsghdrsPool{
p: sync.Pool{
New: func() interface{} {
return new(mmsghdrsPacker)
},
},
}
type mmsghdrsPool struct {
p sync.Pool
}
func (p *mmsghdrsPool) Get() *mmsghdrsPacker {
return p.p.Get().(*mmsghdrsPacker)
}
func (p *mmsghdrsPool) Put(packer *mmsghdrsPacker) {
p.p.Put(packer)
}

View File

@ -2,6 +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.
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
// +build aix darwin dragonfly freebsd netbsd openbsd // +build aix darwin dragonfly freebsd netbsd openbsd
package socket package socket

View File

@ -2,6 +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.
//go:build aix || darwin || dragonfly || freebsd || netbsd
// +build aix darwin dragonfly freebsd netbsd // +build aix darwin dragonfly freebsd netbsd
package socket package socket

View File

@ -17,6 +17,9 @@ func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
if sa != nil { if sa != nil {
h.Name = (*byte)(unsafe.Pointer(&sa[0])) h.Name = (*byte)(unsafe.Pointer(&sa[0]))
h.Namelen = uint32(len(sa)) h.Namelen = uint32(len(sa))
} else {
h.Name = nil
h.Namelen = 0
} }
} }

View File

@ -2,7 +2,8 @@
// 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 arm mips mipsle 386 //go:build (arm || mips || mipsle || 386 || ppc) && linux
// +build arm mips mipsle 386 ppc
// +build linux // +build linux
package socket package socket

View File

@ -2,6 +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.
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux // +build linux

View File

@ -2,8 +2,8 @@
// 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 //go:build amd64 && solaris
// +build solaris // +build amd64,solaris
package socket package socket

View File

@ -2,7 +2,8 @@
// 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
package socket package socket

View File

@ -0,0 +1,36 @@
// Copyright 2020 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.
//go:build s390x && zos
// +build s390x,zos
package socket
import "unsafe"
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
for i := range vs {
vs[i].set(bs[i])
}
if len(vs) > 0 {
h.Iov = &vs[0]
h.Iovlen = int32(len(vs))
}
if len(oob) > 0 {
h.Control = (*byte)(unsafe.Pointer(&oob[0]))
h.Controllen = uint32(len(oob))
}
if sa != nil {
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
h.Namelen = uint32(len(sa))
}
}
func (h *msghdr) controllen() int {
return int(h.Controllen)
}
func (h *msghdr) flags() int {
return int(h.Flags)
}

13
vendor/golang.org/x/net/internal/socket/norace.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// 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.
//go:build !race
// +build !race
package socket
func (m *Message) raceRead() {
}
func (m *Message) raceWrite() {
}

38
vendor/golang.org/x/net/internal/socket/race.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// 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.
//go:build race
// +build race
package socket
import (
"runtime"
"unsafe"
)
// This package reads and writes the Message buffers using a
// direct system call, which the race detector can't see.
// These functions tell the race detector what is going on during the syscall.
func (m *Message) raceRead() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
func (m *Message) raceWrite() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}

View File

@ -17,18 +17,45 @@ type Conn struct {
c syscall.RawConn c syscall.RawConn
} }
// tcpConn is an interface implemented by net.TCPConn.
// It can be used for interface assertions to check if a net.Conn is a TCP connection.
type tcpConn interface {
SyscallConn() (syscall.RawConn, error)
SetLinger(int) error
}
var _ tcpConn = (*net.TCPConn)(nil)
// udpConn is an interface implemented by net.UDPConn.
// It can be used for interface assertions to check if a net.Conn is a UDP connection.
type udpConn interface {
SyscallConn() (syscall.RawConn, error)
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
}
var _ udpConn = (*net.UDPConn)(nil)
// ipConn is an interface implemented by net.IPConn.
// It can be used for interface assertions to check if a net.Conn is an IP connection.
type ipConn interface {
SyscallConn() (syscall.RawConn, error)
ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *net.IPAddr, err error)
}
var _ ipConn = (*net.IPConn)(nil)
// NewConn returns a new raw connection. // NewConn returns a new raw connection.
func NewConn(c net.Conn) (*Conn, error) { func NewConn(c net.Conn) (*Conn, error) {
var err error var err error
var cc Conn var cc Conn
switch c := c.(type) { switch c := c.(type) {
case *net.TCPConn: case tcpConn:
cc.network = "tcp" cc.network = "tcp"
cc.c, err = c.SyscallConn() cc.c, err = c.SyscallConn()
case *net.UDPConn: case udpConn:
cc.network = "udp" cc.network = "udp"
cc.c, err = c.SyscallConn() cc.c, err = c.SyscallConn()
case *net.IPConn: case ipConn:
cc.network = "ip" cc.network = "ip"
cc.c, err = c.SyscallConn() cc.c, err = c.SyscallConn()
default: default:

View File

@ -2,6 +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.
//go:build linux
// +build linux // +build linux
package socket package socket
@ -9,26 +10,24 @@ package socket
import ( import (
"net" "net"
"os" "os"
"syscall"
) )
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
hs := make(mmsghdrs, len(ms)) for i := range ms {
ms[i].raceWrite()
}
packer := defaultMmsghdrsPool.Get()
defer defaultMmsghdrsPool.Put(packer)
var parseFn func([]byte, string) (net.Addr, error) var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" { if c.network != "tcp" {
parseFn = parseInetAddr parseFn = parseInetAddr
} }
if err := hs.pack(ms, parseFn, nil); err != nil { hs := packer.pack(ms, parseFn, nil)
return 0, err
}
var operr error var operr error
var n int var n int
fn := func(s uintptr) bool { fn := func(s uintptr) bool {
n, operr = recvmmsg(s, hs, flags) n, operr = recvmmsg(s, hs, flags)
if operr == syscall.EAGAIN { return ioComplete(flags, operr)
return false
}
return true
} }
if err := c.c.Read(fn); err != nil { if err := c.c.Read(fn); err != nil {
return n, err return n, err
@ -43,22 +42,21 @@ func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
} }
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
hs := make(mmsghdrs, len(ms)) for i := range ms {
var marshalFn func(net.Addr) []byte ms[i].raceRead()
}
packer := defaultMmsghdrsPool.Get()
defer defaultMmsghdrsPool.Put(packer)
var marshalFn func(net.Addr, []byte) int
if c.network != "tcp" { if c.network != "tcp" {
marshalFn = marshalInetAddr marshalFn = marshalInetAddr
} }
if err := hs.pack(ms, nil, marshalFn); err != nil { hs := packer.pack(ms, nil, marshalFn)
return 0, err
}
var operr error var operr error
var n int var n int
fn := func(s uintptr) bool { fn := func(s uintptr) bool {
n, operr = sendmmsg(s, hs, flags) n, operr = sendmmsg(s, hs, flags)
if operr == syscall.EAGAIN { return ioComplete(flags, operr)
return false
}
return true
} }
if err := c.c.Write(fn); err != nil { if err := c.c.Write(fn); err != nil {
return n, err return n, err

View File

@ -2,16 +2,17 @@
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris windows //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows || zos
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos
package socket package socket
import ( import (
"os" "os"
"syscall"
) )
func (c *Conn) recvMsg(m *Message, flags int) error { func (c *Conn) recvMsg(m *Message, flags int) error {
m.raceWrite()
var h msghdr var h msghdr
vs := make([]iovec, len(m.Buffers)) vs := make([]iovec, len(m.Buffers))
var sa []byte var sa []byte
@ -23,10 +24,7 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
var n int var n int
fn := func(s uintptr) bool { fn := func(s uintptr) bool {
n, operr = recvmsg(s, &h, flags) n, operr = recvmsg(s, &h, flags)
if operr == syscall.EAGAIN { return ioComplete(flags, operr)
return false
}
return true
} }
if err := c.c.Read(fn); err != nil { if err := c.c.Read(fn); err != nil {
return err return err
@ -48,21 +46,21 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
} }
func (c *Conn) sendMsg(m *Message, flags int) error { func (c *Conn) sendMsg(m *Message, flags int) error {
m.raceRead()
var h msghdr var h msghdr
vs := make([]iovec, len(m.Buffers)) vs := make([]iovec, len(m.Buffers))
var sa []byte var sa []byte
if m.Addr != nil { if m.Addr != nil {
sa = marshalInetAddr(m.Addr) var a [sizeofSockaddrInet6]byte
n := marshalInetAddr(m.Addr, a[:])
sa = a[:n]
} }
h.pack(vs, m.Buffers, m.OOB, sa) h.pack(vs, m.Buffers, m.OOB, sa)
var operr error var operr error
var n int var n int
fn := func(s uintptr) bool { fn := func(s uintptr) bool {
n, operr = sendmsg(s, &h, flags) n, operr = sendmsg(s, &h, flags)
if operr == syscall.EAGAIN { return ioComplete(flags, operr)
return false
}
return true
} }
if err := c.c.Write(fn); err != nil { if err := c.c.Write(fn); err != nil {
return err return err

View File

@ -2,6 +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.
//go:build !linux
// +build !linux // +build !linux
package socket package socket

View File

@ -2,7 +2,8 @@
// 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos
package socket package socket

View File

@ -90,17 +90,9 @@ func (o *Option) SetInt(c *Conn, v int) error {
return o.set(c, b) return o.set(c, b)
} }
func controlHeaderLen() int {
return roundup(sizeofCmsghdr)
}
func controlMessageLen(dataLen int) int {
return roundup(sizeofCmsghdr) + dataLen
}
// ControlMessageSpace returns the whole length of control message. // ControlMessageSpace returns the whole length of control message.
func ControlMessageSpace(dataLen int) int { func ControlMessageSpace(dataLen int) int {
return roundup(sizeofCmsghdr) + roundup(dataLen) return controlMessageSpace(dataLen)
} }
// A ControlMessage represents the head message in a stream of control // A ControlMessage represents the head message in a stream of control

View File

@ -9,13 +9,8 @@ import (
"unsafe" "unsafe"
) )
var ( // NativeEndian is the machine native endian implementation of ByteOrder.
// NativeEndian is the machine native endian implementation of var NativeEndian binary.ByteOrder
// ByteOrder.
NativeEndian binary.ByteOrder
kernelAlign int
)
func init() { func init() {
i := uint32(1) i := uint32(1)
@ -25,9 +20,4 @@ func init() {
} else { } else {
NativeEndian = binary.BigEndian NativeEndian = binary.BigEndian
} }
kernelAlign = probeProtocolStack()
}
func roundup(l int) int {
return (l + kernelAlign - 1) &^ (kernelAlign - 1)
} }

View File

@ -2,6 +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.
//go:build aix || darwin || dragonfly || freebsd || openbsd
// +build aix darwin dragonfly freebsd openbsd // +build aix darwin dragonfly freebsd openbsd
package socket package socket

View File

@ -1,23 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix freebsd netbsd openbsd
package socket
import (
"runtime"
"unsafe"
)
func probeProtocolStack() int {
if (runtime.GOOS == "netbsd" || runtime.GOOS == "openbsd") && runtime.GOARCH == "arm" {
return 8
}
if runtime.GOOS == "aix" {
return 1
}
var p uintptr
return int(unsafe.Sizeof(p))
}

View File

@ -2,7 +2,8 @@
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package socket package socket
@ -14,4 +15,7 @@ const (
sysAF_INET6 = unix.AF_INET6 sysAF_INET6 = unix.AF_INET6
sysSOCK_RAW = unix.SOCK_RAW sysSOCK_RAW = unix.SOCK_RAW
sizeofSockaddrInet4 = unix.SizeofSockaddrInet4
sizeofSockaddrInet6 = unix.SizeofSockaddrInet6
) )

View File

@ -1,7 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socket
func probeProtocolStack() int { return 4 }

View File

@ -2,6 +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.
//go:build aix || (go1.12 && darwin)
// +build aix go1.12,darwin // +build aix go1.12,darwin
package socket package socket

View File

@ -2,6 +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.
//go:build linux && !s390x && !386
// +build linux,!s390x,!386 // +build linux,!s390x,!386
package socket package socket
@ -11,11 +12,6 @@ import (
"unsafe" "unsafe"
) )
func probeProtocolStack() int {
var p uintptr
return int(unsafe.Sizeof(p))
}
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
return int(n), errnoErr(errno) return int(n), errnoErr(errno)

View File

@ -9,8 +9,6 @@ import (
"unsafe" "unsafe"
) )
func probeProtocolStack() int { return 4 }
const ( const (
sysSETSOCKOPT = 0xe sysSETSOCKOPT = 0xe
sysGETSOCKOPT = 0xf sysGETSOCKOPT = 0xf

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