cleaned dependencies
This commit is contained in:
parent
5734c3019a
commit
38e095d380
@ -1,7 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/micro/mdns"
|
"net"
|
||||||
|
|
||||||
|
"github.com/hashicorp/mdns"
|
||||||
|
|
||||||
|
"github.com/paulbsd/go-aptproxy/src/server"
|
||||||
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -21,7 +25,7 @@ func main() {
|
|||||||
|
|
||||||
// Create the HTTP server and initialize the cache
|
// Create the HTTP server and initialize the cache
|
||||||
addr := fmt.Sprintf("%s:%d", *host, *port)
|
addr := fmt.Sprintf("%s:%d", *host, *port)
|
||||||
httpServer, err := NewServer(addr, *directory)
|
httpServer, err := server.NewServer(addr, *directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -36,19 +40,13 @@ func main() {
|
|||||||
log.Println("Stopping HTTP server...")
|
log.Println("Stopping HTTP server...")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Respond to mDNS queries
|
|
||||||
h, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
service, err := mdns.NewMDNSService(
|
service, err := mdns.NewMDNSService(
|
||||||
h,
|
"thinkpad",
|
||||||
"_apt_proxy._tcp",
|
"_apt_proxy._tcp",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
*port,
|
*port,
|
||||||
nil,
|
[]net.IP{GetOutboundIP()},
|
||||||
[]string{"go-aptproxy - Smarter APT Proxy"},
|
[]string{"go-aptproxy - Smarter APT Proxy"},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -72,3 +70,16 @@ func main() {
|
|||||||
<-c
|
<-c
|
||||||
log.Println("Caught SIGINT")
|
log.Println("Caught SIGINT")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get preferred outbound ip of this machine
|
||||||
|
func GetOutboundIP() net.IP {
|
||||||
|
conn, err := net.Dial("udp", "8.8.8.8:53")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||||
|
|
||||||
|
return localAddr.IP
|
||||||
|
}
|
13
go.mod
13
go.mod
@ -1,19 +1,16 @@
|
|||||||
module go-aptproxy
|
module github.com/paulbsd/go-aptproxy
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.5.1
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
|
github.com/hashicorp/mdns v1.0.4
|
||||||
github.com/hectane/go-asyncserver v0.1.0
|
github.com/hectane/go-asyncserver v0.1.0
|
||||||
github.com/micro/mdns v0.3.0
|
|
||||||
github.com/nathan-osman/go-aptproxy v0.0.0-20160507053712-02fe4d04b5fb
|
|
||||||
github.com/pquerna/cachecontrol v0.1.0
|
github.com/pquerna/cachecontrol v0.1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/miekg/dns v1.1.3 // indirect
|
github.com/miekg/dns v1.1.43 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 // indirect
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
|
||||||
)
|
)
|
||||||
|
31
go.sum
31
go.sum
@ -2,14 +2,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||||
|
github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
|
||||||
|
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||||
github.com/hectane/go-asyncserver v0.1.0 h1:miQMVjLchB0fklo4nKoUp3votMOCSJhddVlPSmyiieM=
|
github.com/hectane/go-asyncserver v0.1.0 h1:miQMVjLchB0fklo4nKoUp3votMOCSJhddVlPSmyiieM=
|
||||||
github.com/hectane/go-asyncserver v0.1.0/go.mod h1:waBaOSU0nKsRCHYMISp/+MSakn6C5HyDSF3y0NUknu0=
|
github.com/hectane/go-asyncserver v0.1.0/go.mod h1:waBaOSU0nKsRCHYMISp/+MSakn6C5HyDSF3y0NUknu0=
|
||||||
github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE=
|
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||||
github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc=
|
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||||
github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM=
|
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||||
github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
|
||||||
github.com/nathan-osman/go-aptproxy v0.0.0-20160507053712-02fe4d04b5fb h1:wyxHQadQph4aRZhnsIP04eLgVP5GodIUYcto+TLITCE=
|
|
||||||
github.com/nathan-osman/go-aptproxy v0.0.0-20160507053712-02fe4d04b5fb/go.mod h1:5Ix064b/k8CMKEnpquzB2sDr5D9Wm1pf+DVQi9Q+UVg=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
|
github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
|
||||||
@ -17,15 +16,23 @@ github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQ
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/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-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c h1:DHcbWVXeY+0Y8HHKR+rbLwnoh2F4tNCY7rTiHJ30RmA=
|
||||||
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
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/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
0
cache/cache.go → src/cache/cache.go
vendored
0
cache/cache.go → src/cache/cache.go
vendored
0
cache/entry.go → src/cache/entry.go
vendored
0
cache/entry.go → src/cache/entry.go
vendored
@ -1,7 +1,7 @@
|
|||||||
package main
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go-aptproxy/cache"
|
"github.com/paulbsd/go-aptproxy/src/cache"
|
||||||
|
|
||||||
server "github.com/hectane/go-asyncserver"
|
server "github.com/hectane/go-asyncserver"
|
||||||
"github.com/pquerna/cachecontrol/cacheobject"
|
"github.com/pquerna/cachecontrol/cacheobject"
|
2
vendor/github.com/micro/mdns/LICENSE → vendor/github.com/hashicorp/mdns/LICENSE
generated
vendored
2
vendor/github.com/micro/mdns/LICENSE → vendor/github.com/hashicorp/mdns/LICENSE
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) {}
|
Copyright (c) 2014 Armon Dadgar
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
37
vendor/github.com/hashicorp/mdns/README.md
generated
vendored
Normal file
37
vendor/github.com/hashicorp/mdns/README.md
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
mdns
|
||||||
|
====
|
||||||
|
|
||||||
|
Simple mDNS client/server library in Golang. mDNS or Multicast DNS can be
|
||||||
|
used to discover services on the local network without the use of an authoritative
|
||||||
|
DNS server. This enables peer-to-peer discovery. It is important to note that many
|
||||||
|
networks restrict the use of multicasting, which prevents mDNS from functioning.
|
||||||
|
Notably, multicast cannot be used in any sort of cloud, or shared infrastructure
|
||||||
|
environment. However it works well in most office, home, or private infrastructure
|
||||||
|
environments.
|
||||||
|
|
||||||
|
Using the library is very simple, here is an example of publishing a service entry:
|
||||||
|
|
||||||
|
// Setup our service export
|
||||||
|
host, _ := os.Hostname()
|
||||||
|
info := []string{"My awesome service"}
|
||||||
|
service, _ := mdns.NewMDNSService(host, "_foobar._tcp", "", "", 8000, nil, info)
|
||||||
|
|
||||||
|
// Create the mDNS server, defer shutdown
|
||||||
|
server, _ := mdns.NewServer(&mdns.Config{Zone: service})
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
Doing a lookup for service providers is also very simple:
|
||||||
|
|
||||||
|
// Make a channel for results and start listening
|
||||||
|
entriesCh := make(chan *mdns.ServiceEntry, 4)
|
||||||
|
go func() {
|
||||||
|
for entry := range entriesCh {
|
||||||
|
fmt.Printf("Got new entry: %v\n", entry)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Start the lookup
|
||||||
|
mdns.Lookup("_foobar._tcp", entriesCh)
|
||||||
|
close(entriesCh)
|
||||||
|
|
299
vendor/github.com/micro/mdns/client.go → vendor/github.com/hashicorp/mdns/client.go
generated
vendored
299
vendor/github.com/micro/mdns/client.go → vendor/github.com/hashicorp/mdns/client.go
generated
vendored
@ -1,12 +1,11 @@
|
|||||||
package mdns
|
package mdns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
@ -23,7 +22,6 @@ type ServiceEntry struct {
|
|||||||
Port int
|
Port int
|
||||||
Info string
|
Info string
|
||||||
InfoFields []string
|
InfoFields []string
|
||||||
TTL int
|
|
||||||
|
|
||||||
Addr net.IP // @Deprecated
|
Addr net.IP // @Deprecated
|
||||||
|
|
||||||
@ -40,8 +38,7 @@ func (s *ServiceEntry) complete() bool {
|
|||||||
type QueryParam struct {
|
type QueryParam struct {
|
||||||
Service string // Service to lookup
|
Service string // Service to lookup
|
||||||
Domain string // Lookup domain, default "local"
|
Domain string // Lookup domain, default "local"
|
||||||
Context context.Context // Context
|
Timeout time.Duration // Lookup timeout, default 1 second
|
||||||
Timeout time.Duration // Lookup timeout, default 1 second. Ignored if Context is provided
|
|
||||||
Interface *net.Interface // Multicast interface to use
|
Interface *net.Interface // Multicast interface to use
|
||||||
Entries chan<- *ServiceEntry // Entries Channel
|
Entries chan<- *ServiceEntry // Entries Channel
|
||||||
WantUnicastResponse bool // Unicast response desired, as per 5.4 in RFC
|
WantUnicastResponse bool // Unicast response desired, as per 5.4 in RFC
|
||||||
@ -72,7 +69,7 @@ func Query(params *QueryParam) error {
|
|||||||
|
|
||||||
// Set the multicast interface
|
// Set the multicast interface
|
||||||
if params.Interface != nil {
|
if params.Interface != nil {
|
||||||
if err := client.setInterface(params.Interface, false); err != nil {
|
if err := client.setInterface(params.Interface); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,77 +78,14 @@ func Query(params *QueryParam) error {
|
|||||||
if params.Domain == "" {
|
if params.Domain == "" {
|
||||||
params.Domain = "local"
|
params.Domain = "local"
|
||||||
}
|
}
|
||||||
|
if params.Timeout == 0 {
|
||||||
if params.Context == nil {
|
params.Timeout = time.Second
|
||||||
if params.Timeout == 0 {
|
|
||||||
params.Timeout = time.Second
|
|
||||||
}
|
|
||||||
params.Context, _ = context.WithTimeout(context.Background(), params.Timeout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the query
|
// Run the query
|
||||||
return client.query(params)
|
return client.query(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen listens indefinitely for multicast updates
|
|
||||||
func Listen(entries chan<- *ServiceEntry, exit chan struct{}) error {
|
|
||||||
// Create a new client
|
|
||||||
client, err := newClient()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
client.setInterface(nil, true)
|
|
||||||
|
|
||||||
// Start listening for response packets
|
|
||||||
msgCh := make(chan *dns.Msg, 32)
|
|
||||||
|
|
||||||
go client.recv(client.ipv4UnicastConn, msgCh)
|
|
||||||
go client.recv(client.ipv6UnicastConn, msgCh)
|
|
||||||
go client.recv(client.ipv4MulticastConn, msgCh)
|
|
||||||
go client.recv(client.ipv6MulticastConn, msgCh)
|
|
||||||
|
|
||||||
ip := make(map[string]*ServiceEntry)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-exit:
|
|
||||||
return nil
|
|
||||||
case <-client.closedCh:
|
|
||||||
return nil
|
|
||||||
case m := <-msgCh:
|
|
||||||
e := messageToEntry(m, ip)
|
|
||||||
if e == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this entry is complete
|
|
||||||
if e.complete() {
|
|
||||||
if e.sent {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.sent = true
|
|
||||||
entries <- e
|
|
||||||
ip = make(map[string]*ServiceEntry)
|
|
||||||
} else {
|
|
||||||
// Fire off a node specific query
|
|
||||||
m := new(dns.Msg)
|
|
||||||
m.SetQuestion(e.Name, dns.TypePTR)
|
|
||||||
m.RecursionDesired = false
|
|
||||||
if err := client.sendQuery(m); err != nil {
|
|
||||||
log.Printf("[ERR] mdns: Failed to query instance %s: %v", e.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup is the same as Query, however it uses all the default parameters
|
// Lookup is the same as Query, however it uses all the default parameters
|
||||||
func Lookup(service string, entries chan<- *ServiceEntry) error {
|
func Lookup(service string, entries chan<- *ServiceEntry) error {
|
||||||
params := DefaultParams(service)
|
params := DefaultParams(service)
|
||||||
@ -168,9 +102,8 @@ type client struct {
|
|||||||
ipv4MulticastConn *net.UDPConn
|
ipv4MulticastConn *net.UDPConn
|
||||||
ipv6MulticastConn *net.UDPConn
|
ipv6MulticastConn *net.UDPConn
|
||||||
|
|
||||||
closed bool
|
closed int32
|
||||||
closedCh chan struct{} // TODO(reddaly): This doesn't appear to be used.
|
closedCh chan struct{} // TODO(reddaly): This doesn't appear to be used.
|
||||||
closeLock sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new mdns Client that can be used to query
|
// NewClient creates a new mdns Client that can be used to query
|
||||||
@ -178,67 +111,32 @@ type client struct {
|
|||||||
func newClient() (*client, error) {
|
func newClient() (*client, error) {
|
||||||
// TODO(reddaly): At least attempt to bind to the port required in the spec.
|
// TODO(reddaly): At least attempt to bind to the port required in the spec.
|
||||||
// Create a IPv4 listener
|
// Create a IPv4 listener
|
||||||
uconn4, err4 := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
uconn4, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||||
uconn6, err6 := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero, Port: 0})
|
if err != nil {
|
||||||
if err4 != nil && err6 != nil {
|
log.Printf("[ERR] mdns: Failed to bind to udp4 port: %v", err)
|
||||||
log.Printf("[ERR] mdns: Failed to bind to udp port: %v %v", err4, err6)
|
}
|
||||||
|
uconn6, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero, Port: 0})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERR] mdns: Failed to bind to udp6 port: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if uconn4 == nil && uconn6 == nil {
|
if uconn4 == nil && uconn6 == nil {
|
||||||
return nil, fmt.Errorf("failed to bind to any unicast udp port")
|
return nil, fmt.Errorf("failed to bind to any unicast udp port")
|
||||||
}
|
}
|
||||||
|
|
||||||
if uconn4 == nil {
|
mconn4, err := net.ListenMulticastUDP("udp4", nil, ipv4Addr)
|
||||||
uconn4 = &net.UDPConn{}
|
if err != nil {
|
||||||
|
log.Printf("[ERR] mdns: Failed to bind to udp4 port: %v", err)
|
||||||
}
|
}
|
||||||
|
mconn6, err := net.ListenMulticastUDP("udp6", nil, ipv6Addr)
|
||||||
if uconn6 == nil {
|
if err != nil {
|
||||||
uconn6 = &net.UDPConn{}
|
log.Printf("[ERR] mdns: Failed to bind to udp6 port: %v", err)
|
||||||
}
|
|
||||||
|
|
||||||
mconn4, err4 := net.ListenUDP("udp4", mdnsWildcardAddrIPv4)
|
|
||||||
mconn6, err6 := net.ListenUDP("udp6", mdnsWildcardAddrIPv6)
|
|
||||||
if err4 != nil && err6 != nil {
|
|
||||||
log.Printf("[ERR] mdns: Failed to bind to udp port: %v %v", err4, err6)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if mconn4 == nil && mconn6 == nil {
|
if mconn4 == nil && mconn6 == nil {
|
||||||
return nil, fmt.Errorf("failed to bind to any multicast udp port")
|
return nil, fmt.Errorf("failed to bind to any multicast udp port")
|
||||||
}
|
}
|
||||||
|
|
||||||
if mconn4 == nil {
|
|
||||||
mconn4 = &net.UDPConn{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mconn6 == nil {
|
|
||||||
mconn6 = &net.UDPConn{}
|
|
||||||
}
|
|
||||||
|
|
||||||
p1 := ipv4.NewPacketConn(mconn4)
|
|
||||||
p2 := ipv6.NewPacketConn(mconn6)
|
|
||||||
p1.SetMulticastLoopback(true)
|
|
||||||
p2.SetMulticastLoopback(true)
|
|
||||||
|
|
||||||
ifaces, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var errCount1, errCount2 int
|
|
||||||
|
|
||||||
for _, iface := range ifaces {
|
|
||||||
if err := p1.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
|
|
||||||
errCount1++
|
|
||||||
}
|
|
||||||
if err := p2.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
|
|
||||||
errCount2++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ifaces) == errCount1 && len(ifaces) == errCount2 {
|
|
||||||
return nil, fmt.Errorf("Failed to join multicast group on all interfaces!")
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &client{
|
c := &client{
|
||||||
ipv4MulticastConn: mconn4,
|
ipv4MulticastConn: mconn4,
|
||||||
ipv6MulticastConn: mconn6,
|
ipv6MulticastConn: mconn6,
|
||||||
@ -251,14 +149,12 @@ func newClient() (*client, error) {
|
|||||||
|
|
||||||
// Close is used to cleanup the client
|
// Close is used to cleanup the client
|
||||||
func (c *client) Close() error {
|
func (c *client) Close() error {
|
||||||
c.closeLock.Lock()
|
if !atomic.CompareAndSwapInt32(&c.closed, 0, 1) {
|
||||||
defer c.closeLock.Unlock()
|
// something else already closed it
|
||||||
|
|
||||||
if c.closed {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c.closed = true
|
|
||||||
|
|
||||||
|
log.Printf("[INFO] mdns: Closing client %v", *c)
|
||||||
close(c.closedCh)
|
close(c.closedCh)
|
||||||
|
|
||||||
if c.ipv4UnicastConn != nil {
|
if c.ipv4UnicastConn != nil {
|
||||||
@ -277,31 +173,25 @@ func (c *client) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setInterface is used to set the query interface, uses sytem
|
// setInterface is used to set the query interface, uses system
|
||||||
// default if not provided
|
// default if not provided
|
||||||
func (c *client) setInterface(iface *net.Interface, loopback bool) error {
|
func (c *client) setInterface(iface *net.Interface) error {
|
||||||
p := ipv4.NewPacketConn(c.ipv4UnicastConn)
|
p := ipv4.NewPacketConn(c.ipv4UnicastConn)
|
||||||
if err := p.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
|
if err := p.SetMulticastInterface(iface); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p2 := ipv6.NewPacketConn(c.ipv6UnicastConn)
|
p2 := ipv6.NewPacketConn(c.ipv6UnicastConn)
|
||||||
if err := p2.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
|
if err := p2.SetMulticastInterface(iface); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p = ipv4.NewPacketConn(c.ipv4MulticastConn)
|
p = ipv4.NewPacketConn(c.ipv4MulticastConn)
|
||||||
if err := p.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
|
if err := p.SetMulticastInterface(iface); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p2 = ipv6.NewPacketConn(c.ipv6MulticastConn)
|
p2 = ipv6.NewPacketConn(c.ipv6MulticastConn)
|
||||||
if err := p2.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
|
if err := p2.SetMulticastInterface(iface); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if loopback {
|
|
||||||
p.SetMulticastLoopback(true)
|
|
||||||
p2.SetMulticastLoopback(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,10 +227,51 @@ func (c *client) query(params *QueryParam) error {
|
|||||||
// Map the in-progress responses
|
// Map the in-progress responses
|
||||||
inprogress := make(map[string]*ServiceEntry)
|
inprogress := make(map[string]*ServiceEntry)
|
||||||
|
|
||||||
|
// Listen until we reach the timeout
|
||||||
|
finish := time.After(params.Timeout)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case resp := <-msgCh:
|
case resp := <-msgCh:
|
||||||
inp := messageToEntry(resp, inprogress)
|
var inp *ServiceEntry
|
||||||
|
for _, answer := range append(resp.Answer, resp.Extra...) {
|
||||||
|
// TODO(reddaly): Check that response corresponds to serviceAddr?
|
||||||
|
switch rr := answer.(type) {
|
||||||
|
case *dns.PTR:
|
||||||
|
// Create new entry for this
|
||||||
|
inp = ensureName(inprogress, rr.Ptr)
|
||||||
|
|
||||||
|
case *dns.SRV:
|
||||||
|
// Check for a target mismatch
|
||||||
|
if rr.Target != rr.Hdr.Name {
|
||||||
|
alias(inprogress, rr.Hdr.Name, rr.Target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the port
|
||||||
|
inp = ensureName(inprogress, rr.Hdr.Name)
|
||||||
|
inp.Host = rr.Target
|
||||||
|
inp.Port = int(rr.Port)
|
||||||
|
|
||||||
|
case *dns.TXT:
|
||||||
|
// Pull out the txt
|
||||||
|
inp = ensureName(inprogress, rr.Hdr.Name)
|
||||||
|
inp.Info = strings.Join(rr.Txt, "|")
|
||||||
|
inp.InfoFields = rr.Txt
|
||||||
|
inp.hasTXT = true
|
||||||
|
|
||||||
|
case *dns.A:
|
||||||
|
// Pull out the IP
|
||||||
|
inp = ensureName(inprogress, rr.Hdr.Name)
|
||||||
|
inp.Addr = rr.A // @Deprecated
|
||||||
|
inp.AddrV4 = rr.A
|
||||||
|
|
||||||
|
case *dns.AAAA:
|
||||||
|
// Pull out the IP
|
||||||
|
inp = ensureName(inprogress, rr.Hdr.Name)
|
||||||
|
inp.Addr = rr.AAAA // @Deprecated
|
||||||
|
inp.AddrV6 = rr.AAAA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if inp == nil {
|
if inp == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -353,8 +284,7 @@ func (c *client) query(params *QueryParam) error {
|
|||||||
inp.sent = true
|
inp.sent = true
|
||||||
select {
|
select {
|
||||||
case params.Entries <- inp:
|
case params.Entries <- inp:
|
||||||
case <-params.Context.Done():
|
default:
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fire off a node specific query
|
// Fire off a node specific query
|
||||||
@ -365,7 +295,7 @@ func (c *client) query(params *QueryParam) error {
|
|||||||
log.Printf("[ERR] mdns: Failed to query instance %s: %v", inp.Name, err)
|
log.Printf("[ERR] mdns: Failed to query instance %s: %v", inp.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <-params.Context.Done():
|
case <-finish:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,10 +308,16 @@ func (c *client) sendQuery(q *dns.Msg) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if c.ipv4UnicastConn != nil {
|
if c.ipv4UnicastConn != nil {
|
||||||
c.ipv4UnicastConn.WriteToUDP(buf, ipv4Addr)
|
_, err = c.ipv4UnicastConn.WriteToUDP(buf, ipv4Addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if c.ipv6UnicastConn != nil {
|
if c.ipv6UnicastConn != nil {
|
||||||
c.ipv6UnicastConn.WriteToUDP(buf, ipv6Addr)
|
_, err = c.ipv6UnicastConn.WriteToUDP(buf, ipv6Addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -392,19 +328,20 @@ func (c *client) recv(l *net.UDPConn, msgCh chan *dns.Msg) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf := make([]byte, 65536)
|
buf := make([]byte, 65536)
|
||||||
for {
|
for atomic.LoadInt32(&c.closed) == 0 {
|
||||||
c.closeLock.Lock()
|
n, err := l.Read(buf)
|
||||||
if c.closed {
|
|
||||||
c.closeLock.Unlock()
|
if atomic.LoadInt32(&c.closed) == 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.closeLock.Unlock()
|
|
||||||
n, err := l.Read(buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("[ERR] mdns: Failed to read packet: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msg := new(dns.Msg)
|
msg := new(dns.Msg)
|
||||||
if err := msg.Unpack(buf[:n]); err != nil {
|
if err := msg.Unpack(buf[:n]); err != nil {
|
||||||
|
log.Printf("[ERR] mdns: Failed to unpack packet: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
@ -432,63 +369,3 @@ func alias(inprogress map[string]*ServiceEntry, src, dst string) {
|
|||||||
srcEntry := ensureName(inprogress, src)
|
srcEntry := ensureName(inprogress, src)
|
||||||
inprogress[dst] = srcEntry
|
inprogress[dst] = srcEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
func messageToEntry(m *dns.Msg, inprogress map[string]*ServiceEntry) *ServiceEntry {
|
|
||||||
var inp *ServiceEntry
|
|
||||||
|
|
||||||
for _, answer := range append(m.Answer, m.Extra...) {
|
|
||||||
// TODO(reddaly): Check that response corresponds to serviceAddr?
|
|
||||||
switch rr := answer.(type) {
|
|
||||||
case *dns.PTR:
|
|
||||||
// Create new entry for this
|
|
||||||
inp = ensureName(inprogress, rr.Ptr)
|
|
||||||
if inp.complete() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case *dns.SRV:
|
|
||||||
// Check for a target mismatch
|
|
||||||
if rr.Target != rr.Hdr.Name {
|
|
||||||
alias(inprogress, rr.Hdr.Name, rr.Target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the port
|
|
||||||
inp = ensureName(inprogress, rr.Hdr.Name)
|
|
||||||
if inp.complete() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inp.Host = rr.Target
|
|
||||||
inp.Port = int(rr.Port)
|
|
||||||
case *dns.TXT:
|
|
||||||
// Pull out the txt
|
|
||||||
inp = ensureName(inprogress, rr.Hdr.Name)
|
|
||||||
if inp.complete() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inp.Info = strings.Join(rr.Txt, "|")
|
|
||||||
inp.InfoFields = rr.Txt
|
|
||||||
inp.hasTXT = true
|
|
||||||
case *dns.A:
|
|
||||||
// Pull out the IP
|
|
||||||
inp = ensureName(inprogress, rr.Hdr.Name)
|
|
||||||
if inp.complete() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inp.Addr = rr.A // @Deprecated
|
|
||||||
inp.AddrV4 = rr.A
|
|
||||||
case *dns.AAAA:
|
|
||||||
// Pull out the IP
|
|
||||||
inp = ensureName(inprogress, rr.Hdr.Name)
|
|
||||||
if inp.complete() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inp.Addr = rr.AAAA // @Deprecated
|
|
||||||
inp.AddrV6 = rr.AAAA
|
|
||||||
}
|
|
||||||
|
|
||||||
if inp != nil {
|
|
||||||
inp.TTL = int(answer.Header().Ttl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return inp
|
|
||||||
}
|
|
265
vendor/github.com/micro/mdns/server.go → vendor/github.com/hashicorp/mdns/server.go
generated
vendored
265
vendor/github.com/micro/mdns/server.go → vendor/github.com/hashicorp/mdns/server.go
generated
vendored
@ -3,38 +3,28 @@ package mdns
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"strings"
|
||||||
"time"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"golang.org/x/net/ipv4"
|
)
|
||||||
"golang.org/x/net/ipv6"
|
|
||||||
|
const (
|
||||||
|
ipv4mdns = "224.0.0.251"
|
||||||
|
ipv6mdns = "ff02::fb"
|
||||||
|
mdnsPort = 5353
|
||||||
|
forceUnicastResponses = false
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mdnsGroupIPv4 = net.ParseIP("224.0.0.251")
|
|
||||||
mdnsGroupIPv6 = net.ParseIP("ff02::fb")
|
|
||||||
|
|
||||||
// mDNS wildcard addresses
|
|
||||||
mdnsWildcardAddrIPv4 = &net.UDPAddr{
|
|
||||||
IP: net.ParseIP("224.0.0.0"),
|
|
||||||
Port: 5353,
|
|
||||||
}
|
|
||||||
mdnsWildcardAddrIPv6 = &net.UDPAddr{
|
|
||||||
IP: net.ParseIP("ff02::"),
|
|
||||||
Port: 5353,
|
|
||||||
}
|
|
||||||
|
|
||||||
// mDNS endpoint addresses
|
|
||||||
ipv4Addr = &net.UDPAddr{
|
ipv4Addr = &net.UDPAddr{
|
||||||
IP: mdnsGroupIPv4,
|
IP: net.ParseIP(ipv4mdns),
|
||||||
Port: 5353,
|
Port: mdnsPort,
|
||||||
}
|
}
|
||||||
ipv6Addr = &net.UDPAddr{
|
ipv6Addr = &net.UDPAddr{
|
||||||
IP: mdnsGroupIPv6,
|
IP: net.ParseIP(ipv6mdns),
|
||||||
Port: 5353,
|
Port: mdnsPort,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,8 +38,9 @@ type Config struct {
|
|||||||
// is used.
|
// is used.
|
||||||
Iface *net.Interface
|
Iface *net.Interface
|
||||||
|
|
||||||
// Port If it is not 0, replace the port 5353 with this port number.
|
// LogEmptyResponses indicates the server should print an informative message
|
||||||
Port int
|
// when there is an mDNS query for which the server has no response.
|
||||||
|
LogEmptyResponses bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// mDNS server is used to listen for mDNS queries and respond if we
|
// mDNS server is used to listen for mDNS queries and respond if we
|
||||||
@ -60,66 +51,19 @@ type Server struct {
|
|||||||
ipv4List *net.UDPConn
|
ipv4List *net.UDPConn
|
||||||
ipv6List *net.UDPConn
|
ipv6List *net.UDPConn
|
||||||
|
|
||||||
shutdown bool
|
shutdown int32
|
||||||
shutdownCh chan struct{}
|
shutdownCh chan struct{}
|
||||||
shutdownLock sync.Mutex
|
|
||||||
wg sync.WaitGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer is used to create a new mDNS server from a config
|
// NewServer is used to create a new mDNS server from a config
|
||||||
func NewServer(config *Config) (*Server, error) {
|
func NewServer(config *Config) (*Server, error) {
|
||||||
if config.Port != 0 {
|
|
||||||
mdnsWildcardAddrIPv4.Port = config.Port
|
|
||||||
mdnsWildcardAddrIPv6.Port = config.Port
|
|
||||||
ipv4Addr.Port = config.Port
|
|
||||||
ipv6Addr.Port = config.Port
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the listeners
|
// Create the listeners
|
||||||
// Create wildcard connections (because :5353 can be already taken by other apps)
|
ipv4List, _ := net.ListenMulticastUDP("udp4", config.Iface, ipv4Addr)
|
||||||
ipv4List, _ := net.ListenUDP("udp4", mdnsWildcardAddrIPv4)
|
ipv6List, _ := net.ListenMulticastUDP("udp6", config.Iface, ipv6Addr)
|
||||||
ipv6List, _ := net.ListenUDP("udp6", mdnsWildcardAddrIPv6)
|
|
||||||
|
// Check if we have any listener
|
||||||
if ipv4List == nil && ipv6List == nil {
|
if ipv4List == nil && ipv6List == nil {
|
||||||
return nil, fmt.Errorf("[ERR] mdns: Failed to bind to any udp port!")
|
return nil, fmt.Errorf("No multicast listeners could be started")
|
||||||
}
|
|
||||||
|
|
||||||
if ipv4List == nil {
|
|
||||||
ipv4List = &net.UDPConn{}
|
|
||||||
}
|
|
||||||
if ipv6List == nil {
|
|
||||||
ipv6List = &net.UDPConn{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join multicast groups to receive announcements
|
|
||||||
p1 := ipv4.NewPacketConn(ipv4List)
|
|
||||||
p2 := ipv6.NewPacketConn(ipv6List)
|
|
||||||
p1.SetMulticastLoopback(true)
|
|
||||||
p2.SetMulticastLoopback(true)
|
|
||||||
|
|
||||||
if config.Iface != nil {
|
|
||||||
if err := p1.JoinGroup(config.Iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := p2.JoinGroup(config.Iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ifaces, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
errCount1, errCount2 := 0, 0
|
|
||||||
for _, iface := range ifaces {
|
|
||||||
if err := p1.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
|
|
||||||
errCount1++
|
|
||||||
}
|
|
||||||
if err := p2.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
|
|
||||||
errCount2++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(ifaces) == errCount1 && len(ifaces) == errCount2 {
|
|
||||||
return nil, fmt.Errorf("Failed to join multicast group on all interfaces!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
@ -129,27 +73,25 @@ func NewServer(config *Config) (*Server, error) {
|
|||||||
shutdownCh: make(chan struct{}),
|
shutdownCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
go s.recv(s.ipv4List)
|
if ipv4List != nil {
|
||||||
go s.recv(s.ipv6List)
|
go s.recv(s.ipv4List)
|
||||||
|
}
|
||||||
|
|
||||||
s.wg.Add(1)
|
if ipv6List != nil {
|
||||||
go s.probe()
|
go s.recv(s.ipv6List)
|
||||||
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown is used to shutdown the listener
|
// Shutdown is used to shutdown the listener
|
||||||
func (s *Server) Shutdown() error {
|
func (s *Server) Shutdown() error {
|
||||||
s.shutdownLock.Lock()
|
if !atomic.CompareAndSwapInt32(&s.shutdown, 0, 1) {
|
||||||
defer s.shutdownLock.Unlock()
|
// something else already closed us
|
||||||
|
|
||||||
if s.shutdown {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s.shutdown = true
|
|
||||||
close(s.shutdownCh)
|
close(s.shutdownCh)
|
||||||
s.unregister()
|
|
||||||
|
|
||||||
if s.ipv4List != nil {
|
if s.ipv4List != nil {
|
||||||
s.ipv4List.Close()
|
s.ipv4List.Close()
|
||||||
@ -157,8 +99,6 @@ func (s *Server) Shutdown() error {
|
|||||||
if s.ipv6List != nil {
|
if s.ipv6List != nil {
|
||||||
s.ipv6List.Close()
|
s.ipv6List.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.wg.Wait()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,14 +108,9 @@ func (s *Server) recv(c *net.UDPConn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf := make([]byte, 65536)
|
buf := make([]byte, 65536)
|
||||||
for {
|
for atomic.LoadInt32(&s.shutdown) == 0 {
|
||||||
s.shutdownLock.Lock()
|
|
||||||
if s.shutdown {
|
|
||||||
s.shutdownLock.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.shutdownLock.Unlock()
|
|
||||||
n, from, err := c.ReadFrom(buf)
|
n, from, err := c.ReadFrom(buf)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -192,10 +127,6 @@ func (s *Server) parsePacket(packet []byte, from net.Addr) error {
|
|||||||
log.Printf("[ERR] mdns: Failed to unpack packet: %v", err)
|
log.Printf("[ERR] mdns: Failed to unpack packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO: This is a bit of a hack
|
|
||||||
// We decided to ignore some mDNS answers for the time being
|
|
||||||
// See: https://tools.ietf.org/html/rfc6762#section-7.2
|
|
||||||
msg.Truncated = false
|
|
||||||
return s.handleQuery(&msg, from)
|
return s.handleQuery(&msg, from)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,13 +218,21 @@ func (s *Server) handleQuery(query *dns.Msg, from net.Addr) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.config.LogEmptyResponses && len(multicastAnswer) == 0 && len(unicastAnswer) == 0 {
|
||||||
|
questions := make([]string, len(query.Question))
|
||||||
|
for i, q := range query.Question {
|
||||||
|
questions[i] = q.Name
|
||||||
|
}
|
||||||
|
log.Printf("no responses for query with questions: %s", strings.Join(questions, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
if mresp := resp(false); mresp != nil {
|
if mresp := resp(false); mresp != nil {
|
||||||
if err := s.sendResponse(mresp, from); err != nil {
|
if err := s.sendResponse(mresp, from, false); err != nil {
|
||||||
return fmt.Errorf("mdns: error sending multicast response: %v", err)
|
return fmt.Errorf("mdns: error sending multicast response: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if uresp := resp(true); uresp != nil {
|
if uresp := resp(true); uresp != nil {
|
||||||
if err := s.sendResponse(uresp, from); err != nil {
|
if err := s.sendResponse(uresp, from, true); err != nil {
|
||||||
return fmt.Errorf("mdns: error sending unicast response: %v", err)
|
return fmt.Errorf("mdns: error sending unicast response: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,109 +261,14 @@ func (s *Server) handleQuestion(q dns.Question) (multicastRecs, unicastRecs []dn
|
|||||||
// In the Question Section of a Multicast DNS query, the top bit of the
|
// In the Question Section of a Multicast DNS query, the top bit of the
|
||||||
// qclass field is used to indicate that unicast responses are preferred
|
// qclass field is used to indicate that unicast responses are preferred
|
||||||
// for this particular question. (See Section 5.4.)
|
// for this particular question. (See Section 5.4.)
|
||||||
if q.Qclass&(1<<15) != 0 {
|
if q.Qclass&(1<<15) != 0 || forceUnicastResponses {
|
||||||
return nil, records
|
return nil, records
|
||||||
}
|
}
|
||||||
return records, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) probe() {
|
|
||||||
defer s.wg.Done()
|
|
||||||
|
|
||||||
sd, ok := s.config.Zone.(*MDNSService)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
name := fmt.Sprintf("%s.%s.%s.", sd.Instance, trimDot(sd.Service), trimDot(sd.Domain))
|
|
||||||
|
|
||||||
q := new(dns.Msg)
|
|
||||||
q.SetQuestion(name, dns.TypePTR)
|
|
||||||
q.RecursionDesired = false
|
|
||||||
|
|
||||||
srv := &dns.SRV{
|
|
||||||
Hdr: dns.RR_Header{
|
|
||||||
Name: name,
|
|
||||||
Rrtype: dns.TypeSRV,
|
|
||||||
Class: dns.ClassINET,
|
|
||||||
Ttl: defaultTTL,
|
|
||||||
},
|
|
||||||
Priority: 0,
|
|
||||||
Weight: 0,
|
|
||||||
Port: uint16(sd.Port),
|
|
||||||
Target: sd.HostName,
|
|
||||||
}
|
|
||||||
txt := &dns.TXT{
|
|
||||||
Hdr: dns.RR_Header{
|
|
||||||
Name: name,
|
|
||||||
Rrtype: dns.TypeTXT,
|
|
||||||
Class: dns.ClassINET,
|
|
||||||
Ttl: defaultTTL,
|
|
||||||
},
|
|
||||||
Txt: sd.TXT,
|
|
||||||
}
|
|
||||||
q.Ns = []dns.RR{srv, txt}
|
|
||||||
|
|
||||||
randomizer := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
if err := s.SendMulticast(q); err != nil {
|
|
||||||
log.Println("[ERR] mdns: failed to send probe:", err.Error())
|
|
||||||
}
|
|
||||||
time.Sleep(time.Duration(randomizer.Intn(250)) * time.Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := new(dns.Msg)
|
|
||||||
resp.MsgHdr.Response = true
|
|
||||||
|
|
||||||
// set for query
|
|
||||||
q.SetQuestion(name, dns.TypeANY)
|
|
||||||
|
|
||||||
resp.Answer = append(resp.Answer, s.config.Zone.Records(q.Question[0])...)
|
|
||||||
|
|
||||||
// reset
|
|
||||||
q.SetQuestion(name, dns.TypePTR)
|
|
||||||
|
|
||||||
// From RFC6762
|
|
||||||
// The Multicast DNS responder MUST send at least two unsolicited
|
|
||||||
// responses, one second apart. To provide increased robustness against
|
|
||||||
// packet loss, a responder MAY send up to eight unsolicited responses,
|
|
||||||
// provided that the interval between unsolicited responses increases by
|
|
||||||
// at least a factor of two with every response sent.
|
|
||||||
timeout := 1 * time.Second
|
|
||||||
timer := time.NewTimer(timeout)
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
if err := s.SendMulticast(resp); err != nil {
|
|
||||||
log.Println("[ERR] mdns: failed to send announcement:", err.Error())
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-timer.C:
|
|
||||||
timeout *= 2
|
|
||||||
timer.Reset(timeout)
|
|
||||||
case <-s.shutdownCh:
|
|
||||||
timer.Stop()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// multicastResponse us used to send a multicast response packet
|
|
||||||
func (s *Server) SendMulticast(msg *dns.Msg) error {
|
|
||||||
buf, err := msg.Pack()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if s.ipv4List != nil {
|
|
||||||
s.ipv4List.WriteToUDP(buf, ipv4Addr)
|
|
||||||
}
|
|
||||||
if s.ipv6List != nil {
|
|
||||||
s.ipv6List.WriteToUDP(buf, ipv6Addr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendResponse is used to send a response packet
|
// sendResponse is used to send a response packet
|
||||||
func (s *Server) sendResponse(resp *dns.Msg, from net.Addr) error {
|
func (s *Server) sendResponse(resp *dns.Msg, from net.Addr, unicast bool) error {
|
||||||
// TODO(reddaly): Respect the unicast argument, and allow sending responses
|
// TODO(reddaly): Respect the unicast argument, and allow sending responses
|
||||||
// over multicast.
|
// over multicast.
|
||||||
buf, err := resp.Pack()
|
buf, err := resp.Pack()
|
||||||
@ -442,22 +286,3 @@ func (s *Server) sendResponse(resp *dns.Msg, from net.Addr) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) unregister() error {
|
|
||||||
sd, ok := s.config.Zone.(*MDNSService)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sd.TTL = 0
|
|
||||||
name := fmt.Sprintf("%s.%s.%s.", sd.Instance, trimDot(sd.Service), trimDot(sd.Domain))
|
|
||||||
|
|
||||||
q := new(dns.Msg)
|
|
||||||
q.SetQuestion(name, dns.TypeANY)
|
|
||||||
|
|
||||||
resp := new(dns.Msg)
|
|
||||||
resp.MsgHdr.Response = true
|
|
||||||
resp.Answer = append(resp.Answer, s.config.Zone.Records(q.Question[0])...)
|
|
||||||
|
|
||||||
return s.SendMulticast(resp)
|
|
||||||
}
|
|
33
vendor/github.com/micro/mdns/zone.go → vendor/github.com/hashicorp/mdns/zone.go
generated
vendored
33
vendor/github.com/micro/mdns/zone.go → vendor/github.com/hashicorp/mdns/zone.go
generated
vendored
@ -23,14 +23,14 @@ type Zone interface {
|
|||||||
|
|
||||||
// MDNSService is used to export a named service by implementing a Zone
|
// MDNSService is used to export a named service by implementing a Zone
|
||||||
type MDNSService struct {
|
type MDNSService struct {
|
||||||
Instance string // Instance name (e.g. "hostService name")
|
Instance string // Instance name (e.g. "hostService name")
|
||||||
Service string // Service name (e.g. "_http._tcp.")
|
Service string // Service name (e.g. "_http._tcp.")
|
||||||
Domain string // If blank, assumes "local"
|
Domain string // If blank, assumes "local"
|
||||||
HostName string // Host machine DNS name (e.g. "mymachine.net.")
|
HostName string // Host machine DNS name (e.g. "mymachine.net.")
|
||||||
Port int // Service Port
|
Port int // Service Port
|
||||||
IPs []net.IP // IP addresses for the service's host
|
IPs []net.IP // IP addresses for the service's host
|
||||||
TXT []string // Service TXT records
|
TXT []string // Service TXT records
|
||||||
TTL uint32
|
|
||||||
serviceAddr string // Fully qualified service address
|
serviceAddr string // Fully qualified service address
|
||||||
instanceAddr string // Fully qualified instance address
|
instanceAddr string // Fully qualified instance address
|
||||||
enumAddr string // _services._dns-sd._udp.<domain>
|
enumAddr string // _services._dns-sd._udp.<domain>
|
||||||
@ -95,13 +95,13 @@ func NewMDNSService(instance, service, domain, hostName string, port int, ips []
|
|||||||
|
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
var err error
|
var err error
|
||||||
ips, err = net.LookupIP(trimDot(hostName))
|
ips, err = net.LookupIP(hostName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Try appending the host domain suffix and lookup again
|
// Try appending the host domain suffix and lookup again
|
||||||
// (required for Linux-based hosts)
|
// (required for Linux-based hosts)
|
||||||
tmpHostName := fmt.Sprintf("%s%s", hostName, domain)
|
tmpHostName := fmt.Sprintf("%s%s", hostName, domain)
|
||||||
|
|
||||||
ips, err = net.LookupIP(trimDot(tmpHostName))
|
ips, err = net.LookupIP(tmpHostName)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not determine host IP addresses for %s", hostName)
|
return nil, fmt.Errorf("could not determine host IP addresses for %s", hostName)
|
||||||
@ -122,7 +122,6 @@ func NewMDNSService(instance, service, domain, hostName string, port int, ips []
|
|||||||
Port: port,
|
Port: port,
|
||||||
IPs: ips,
|
IPs: ips,
|
||||||
TXT: txt,
|
TXT: txt,
|
||||||
TTL: defaultTTL,
|
|
||||||
serviceAddr: fmt.Sprintf("%s.%s.", trimDot(service), trimDot(domain)),
|
serviceAddr: fmt.Sprintf("%s.%s.", trimDot(service), trimDot(domain)),
|
||||||
instanceAddr: fmt.Sprintf("%s.%s.%s.", instance, trimDot(service), trimDot(domain)),
|
instanceAddr: fmt.Sprintf("%s.%s.%s.", instance, trimDot(service), trimDot(domain)),
|
||||||
enumAddr: fmt.Sprintf("_services._dns-sd._udp.%s.", trimDot(domain)),
|
enumAddr: fmt.Sprintf("_services._dns-sd._udp.%s.", trimDot(domain)),
|
||||||
@ -163,7 +162,7 @@ func (m *MDNSService) serviceEnum(q dns.Question) []dns.RR {
|
|||||||
Name: q.Name,
|
Name: q.Name,
|
||||||
Rrtype: dns.TypePTR,
|
Rrtype: dns.TypePTR,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
Ptr: m.serviceAddr,
|
Ptr: m.serviceAddr,
|
||||||
}
|
}
|
||||||
@ -185,7 +184,7 @@ func (m *MDNSService) serviceRecords(q dns.Question) []dns.RR {
|
|||||||
Name: q.Name,
|
Name: q.Name,
|
||||||
Rrtype: dns.TypePTR,
|
Rrtype: dns.TypePTR,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
Ptr: m.instanceAddr,
|
Ptr: m.instanceAddr,
|
||||||
}
|
}
|
||||||
@ -230,7 +229,7 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR {
|
|||||||
Name: m.HostName,
|
Name: m.HostName,
|
||||||
Rrtype: dns.TypeA,
|
Rrtype: dns.TypeA,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
A: ip4,
|
A: ip4,
|
||||||
})
|
})
|
||||||
@ -255,7 +254,7 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR {
|
|||||||
Name: m.HostName,
|
Name: m.HostName,
|
||||||
Rrtype: dns.TypeAAAA,
|
Rrtype: dns.TypeAAAA,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
AAAA: ip16,
|
AAAA: ip16,
|
||||||
})
|
})
|
||||||
@ -270,7 +269,7 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR {
|
|||||||
Name: q.Name,
|
Name: q.Name,
|
||||||
Rrtype: dns.TypeSRV,
|
Rrtype: dns.TypeSRV,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
@ -298,7 +297,7 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR {
|
|||||||
Name: q.Name,
|
Name: q.Name,
|
||||||
Rrtype: dns.TypeTXT,
|
Rrtype: dns.TypeTXT,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: m.TTL,
|
Ttl: defaultTTL,
|
||||||
},
|
},
|
||||||
Txt: m.TXT,
|
Txt: m.TXT,
|
||||||
}
|
}
|
70
vendor/github.com/micro/mdns/README.md
generated
vendored
70
vendor/github.com/micro/mdns/README.md
generated
vendored
@ -1,70 +0,0 @@
|
|||||||
# MDNS [](https://godoc.org/github.com/micro/mdns)
|
|
||||||
|
|
||||||
MDNS is a simple mdns client/server library by Hashicorp.
|
|
||||||
|
|
||||||
We maintain a fork with updates for PRs and issues they have not merged or addressed.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
MDNS or Multicast DNS can be used to discover services on the local network without the use of an authoritative
|
|
||||||
DNS server. This enables peer-to-peer discovery. It is important to note that many
|
|
||||||
networks restrict the use of multicasting, which prevents mDNS from functioning.
|
|
||||||
Notably, multicast cannot be used in any sort of cloud, or shared infrastructure
|
|
||||||
environment. However it works well in most office, home, or private infrastructure
|
|
||||||
environments.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Using the library is very simple, here is an example of publishing a service entry:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/micro/mdns"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// Setup our service export
|
|
||||||
host, _ := os.Hostname()
|
|
||||||
info := []string{"My awesome service"}
|
|
||||||
service, _ := mdns.NewMDNSService(host, "_foobar._tcp", "", "", 8000, nil, info)
|
|
||||||
|
|
||||||
// Create the mDNS server, defer shutdown
|
|
||||||
server, _ := mdns.NewServer(&mdns.Config{Zone: service})
|
|
||||||
|
|
||||||
defer server.Shutdown()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Doing a lookup for service providers is also very simple:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/micro/mdns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// Make a channel for results and start listening
|
|
||||||
entriesCh := make(chan *mdns.ServiceEntry, 8)
|
|
||||||
go func() {
|
|
||||||
for entry := range entriesCh {
|
|
||||||
fmt.Printf("Got new entry: %v\n", entry)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Start the lookup
|
|
||||||
err := mdns.Lookup("_foobar._tcp", entriesCh)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
close(entriesCh)
|
|
||||||
}
|
|
||||||
```
|
|
84
vendor/github.com/micro/mdns/dns_sd.go
generated
vendored
84
vendor/github.com/micro/mdns/dns_sd.go
generated
vendored
@ -1,84 +0,0 @@
|
|||||||
package mdns
|
|
||||||
|
|
||||||
import "github.com/miekg/dns"
|
|
||||||
|
|
||||||
// DNSSDService is a service that complies with the DNS-SD (RFC 6762) and MDNS
|
|
||||||
// (RFC 6762) specs for local, multicast-DNS-based discovery.
|
|
||||||
//
|
|
||||||
// DNSSDService implements the Zone interface and wraps an MDNSService instance.
|
|
||||||
// To deploy an mDNS service that is compliant with DNS-SD, it's recommended to
|
|
||||||
// register only the wrapped instance with the server.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
// service := &mdns.DNSSDService{
|
|
||||||
// MDNSService: &mdns.MDNSService{
|
|
||||||
// Instance: "My Foobar Service",
|
|
||||||
// Service: "_foobar._tcp",
|
|
||||||
// Port: 8000,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// server, err := mdns.NewServer(&mdns.Config{Zone: service})
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatalf("Error creating server: %v", err)
|
|
||||||
// }
|
|
||||||
// defer server.Shutdown()
|
|
||||||
type DNSSDService struct {
|
|
||||||
MDNSService *MDNSService
|
|
||||||
}
|
|
||||||
|
|
||||||
// Records returns DNS records in response to a DNS question.
|
|
||||||
//
|
|
||||||
// This function returns the DNS response of the underlying MDNSService
|
|
||||||
// instance. It also returns a PTR record for a request for "
|
|
||||||
// _services._dns-sd._udp.<Domain>", as described in section 9 of RFC 6763
|
|
||||||
// ("Service Type Enumeration"), to allow browsing of the underlying MDNSService
|
|
||||||
// instance.
|
|
||||||
func (s *DNSSDService) Records(q dns.Question) []dns.RR {
|
|
||||||
var recs []dns.RR
|
|
||||||
if q.Name == "_services._dns-sd._udp."+s.MDNSService.Domain+"." {
|
|
||||||
recs = s.dnssdMetaQueryRecords(q)
|
|
||||||
}
|
|
||||||
return append(recs, s.MDNSService.Records(q)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// dnssdMetaQueryRecords returns the DNS records in response to a "meta-query"
|
|
||||||
// issued to browse for DNS-SD services, as per section 9. of RFC6763.
|
|
||||||
//
|
|
||||||
// A meta-query has a name of the form "_services._dns-sd._udp.<Domain>" where
|
|
||||||
// Domain is a fully-qualified domain, such as "local."
|
|
||||||
func (s *DNSSDService) dnssdMetaQueryRecords(q dns.Question) []dns.RR {
|
|
||||||
// Intended behavior, as described in the RFC:
|
|
||||||
// ...it may be useful for network administrators to find the list of
|
|
||||||
// advertised service types on the network, even if those Service Names
|
|
||||||
// are just opaque identifiers and not particularly informative in
|
|
||||||
// isolation.
|
|
||||||
//
|
|
||||||
// For this purpose, a special meta-query is defined. A DNS query for PTR
|
|
||||||
// records with the name "_services._dns-sd._udp.<Domain>" yields a set of
|
|
||||||
// PTR records, where the rdata of each PTR record is the two-abel
|
|
||||||
// <Service> name, plus the same domain, e.g., "_http._tcp.<Domain>".
|
|
||||||
// Including the domain in the PTR rdata allows for slightly better name
|
|
||||||
// compression in Unicast DNS responses, but only the first two labels are
|
|
||||||
// relevant for the purposes of service type enumeration. These two-label
|
|
||||||
// service types can then be used to construct subsequent Service Instance
|
|
||||||
// Enumeration PTR queries, in this <Domain> or others, to discover
|
|
||||||
// instances of that service type.
|
|
||||||
return []dns.RR{
|
|
||||||
&dns.PTR{
|
|
||||||
Hdr: dns.RR_Header{
|
|
||||||
Name: q.Name,
|
|
||||||
Rrtype: dns.TypePTR,
|
|
||||||
Class: dns.ClassINET,
|
|
||||||
Ttl: defaultTTL,
|
|
||||||
},
|
|
||||||
Ptr: s.MDNSService.serviceAddr,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Announcement returns DNS records that should be broadcast during the initial
|
|
||||||
// availability of the service, as described in section 8.3 of RFC 6762.
|
|
||||||
// TODO(reddaly): Add this when Announcement is added to the mdns.Zone interface.
|
|
||||||
//func (s *DNSSDService) Announcement() []dns.RR {
|
|
||||||
// return s.MDNSService.Announcement()
|
|
||||||
//}
|
|
18
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
18
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
@ -1,18 +0,0 @@
|
|||||||
language: go
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.10.x
|
|
||||||
- 1.11.x
|
|
||||||
- tip
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# don't use the miekg/dns when testing forks
|
|
||||||
- mkdir -p $GOPATH/src/github.com/miekg
|
|
||||||
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
1
vendor/github.com/miekg/dns/CODEOWNERS
generated
vendored
Normal file
1
vendor/github.com/miekg/dns/CODEOWNERS
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* @miekg @tmthrgd
|
57
vendor/github.com/miekg/dns/Gopkg.lock
generated
vendored
57
vendor/github.com/miekg/dns/Gopkg.lock
generated
vendored
@ -1,57 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
packages = [
|
|
||||||
"ed25519",
|
|
||||||
"ed25519/internal/edwards25519",
|
|
||||||
]
|
|
||||||
pruneopts = ""
|
|
||||||
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = [
|
|
||||||
"bpf",
|
|
||||||
"context",
|
|
||||||
"internal/iana",
|
|
||||||
"internal/socket",
|
|
||||||
"ipv4",
|
|
||||||
"ipv6",
|
|
||||||
]
|
|
||||||
pruneopts = ""
|
|
||||||
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
|
|
||||||
name = "golang.org/x/sync"
|
|
||||||
packages = ["errgroup"]
|
|
||||||
pruneopts = ""
|
|
||||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = ["unix"]
|
|
||||||
pruneopts = ""
|
|
||||||
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
input-imports = [
|
|
||||||
"golang.org/x/crypto/ed25519",
|
|
||||||
"golang.org/x/net/ipv4",
|
|
||||||
"golang.org/x/net/ipv6",
|
|
||||||
"golang.org/x/sync/errgroup",
|
|
||||||
"golang.org/x/sys/unix",
|
|
||||||
]
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
38
vendor/github.com/miekg/dns/Gopkg.toml
generated
vendored
38
vendor/github.com/miekg/dns/Gopkg.toml
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
|
|
||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sync"
|
|
6
vendor/github.com/miekg/dns/LICENSE
generated
vendored
6
vendor/github.com/miekg/dns/LICENSE
generated
vendored
@ -1,7 +1,3 @@
|
|||||||
Extensions of the original work are copyright (c) 2011 Miek Gieben
|
|
||||||
|
|
||||||
As this is fork of the official Go code the same license applies:
|
|
||||||
|
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -30,3 +26,5 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
As this is fork of the official Go code the same license applies.
|
||||||
|
Extensions of the original work are copyright (c) 2011 Miek Gieben
|
||||||
|
2
vendor/github.com/miekg/dns/Makefile.release
generated
vendored
2
vendor/github.com/miekg/dns/Makefile.release
generated
vendored
@ -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
|
||||||
|
28
vendor/github.com/miekg/dns/README.md
generated
vendored
28
vendor/github.com/miekg/dns/README.md
generated
vendored
@ -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,19 +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://github.com/peterzen/goresolver
|
||||||
|
* 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.
|
||||||
|
|
||||||
@ -91,8 +98,8 @@ DNS Authors 2012-
|
|||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
|
This library uses Go modules and uses semantic versioning. Building is done with the `go` tool, so
|
||||||
work:
|
the following should work:
|
||||||
|
|
||||||
go get github.com/miekg/dns
|
go get github.com/miekg/dns
|
||||||
go build github.com/miekg/dns
|
go build github.com/miekg/dns
|
||||||
@ -124,6 +131,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
* 2915 - NAPTR record
|
* 2915 - NAPTR record
|
||||||
* 2929 - DNS IANA Considerations
|
* 2929 - DNS IANA Considerations
|
||||||
* 3110 - RSASHA1 DNS keys
|
* 3110 - RSASHA1 DNS keys
|
||||||
|
* 3123 - APL record
|
||||||
* 3225 - DO bit (DNSSEC OK)
|
* 3225 - DO bit (DNSSEC OK)
|
||||||
* 340{1,2,3} - NAPTR record
|
* 340{1,2,3} - NAPTR record
|
||||||
* 3445 - Limiting the scope of (DNS)KEY
|
* 3445 - Limiting the scope of (DNS)KEY
|
||||||
@ -150,6 +158,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
* 6844 - CAA record
|
* 6844 - CAA record
|
||||||
* 6891 - EDNS0 update
|
* 6891 - EDNS0 update
|
||||||
* 6895 - DNS IANA considerations
|
* 6895 - DNS IANA considerations
|
||||||
|
* 6944 - DNSSEC DNSKEY Algorithm Status
|
||||||
* 6975 - Algorithm Understanding in DNSSEC
|
* 6975 - Algorithm Understanding in DNSSEC
|
||||||
* 7043 - EUI48/EUI64 records
|
* 7043 - EUI48/EUI64 records
|
||||||
* 7314 - DNS (EDNS) EXPIRE Option
|
* 7314 - DNS (EDNS) EXPIRE Option
|
||||||
@ -161,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
|
||||||
|
|
||||||
|
22
vendor/github.com/miekg/dns/acceptfunc.go
generated
vendored
22
vendor/github.com/miekg/dns/acceptfunc.go
generated
vendored
@ -6,22 +6,31 @@ type MsgAcceptFunc func(dh Header) MsgAcceptAction
|
|||||||
|
|
||||||
// DefaultMsgAcceptFunc checks the request and will reject if:
|
// DefaultMsgAcceptFunc checks the request and will reject if:
|
||||||
//
|
//
|
||||||
// * isn't a request (don't respond in that case).
|
// * isn't a request (don't respond in that case)
|
||||||
|
//
|
||||||
// * opcode isn't OpcodeQuery or OpcodeNotify
|
// * opcode isn't OpcodeQuery or OpcodeNotify
|
||||||
|
//
|
||||||
// * Zero bit isn't zero
|
// * Zero bit isn't zero
|
||||||
|
//
|
||||||
// * has more than 1 question in the question section
|
// * has more than 1 question in the question section
|
||||||
|
//
|
||||||
// * has more than 1 RR in the Answer section
|
// * has more than 1 RR in the Answer section
|
||||||
|
//
|
||||||
// * has more than 0 RRs in the Authority section
|
// * has more than 0 RRs in the Authority section
|
||||||
|
//
|
||||||
// * has more than 2 RRs in the Additional section
|
// * has more than 2 RRs in the Additional section
|
||||||
|
//
|
||||||
var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
|
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
|
||||||
MsgIgnore // Ignore the error and send nothing back.
|
MsgIgnore // Ignore the error and send nothing back.
|
||||||
|
MsgRejectNotImplemented // Reject the message with a RcodeNotImplemented
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
||||||
@ -32,12 +41,9 @@ func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
|||||||
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
|
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
|
||||||
opcode := int(dh.Bits>>11) & 0xF
|
opcode := int(dh.Bits>>11) & 0xF
|
||||||
if opcode != OpcodeQuery && opcode != OpcodeNotify {
|
if opcode != OpcodeQuery && opcode != OpcodeNotify {
|
||||||
return MsgReject
|
return MsgRejectNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
if isZero := dh.Bits&_Z != 0; isZero {
|
|
||||||
return MsgReject
|
|
||||||
}
|
|
||||||
if dh.Qdcount != 1 {
|
if dh.Qdcount != 1 {
|
||||||
return MsgReject
|
return MsgReject
|
||||||
}
|
}
|
||||||
|
235
vendor/github.com/miekg/dns/client.go
generated
vendored
235
vendor/github.com/miekg/dns/client.go
generated
vendored
@ -3,10 +3,10 @@ package dns
|
|||||||
// A client implementation.
|
// A client implementation.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@ -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,36 +127,45 @@ 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) {
|
||||||
if !c.SingleInflight {
|
co, err := c.Dial(address)
|
||||||
return c.exchange(m, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
t := "nop"
|
|
||||||
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
|
||||||
t = t1
|
|
||||||
}
|
|
||||||
cl := "nop"
|
|
||||||
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
|
|
||||||
cl = cl1
|
|
||||||
}
|
|
||||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
|
||||||
return c.exchange(m, address)
|
|
||||||
})
|
|
||||||
if r != nil && shared {
|
|
||||||
r = r.Copy()
|
|
||||||
}
|
|
||||||
return r, rtt, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
|
||||||
var co *Conn
|
|
||||||
|
|
||||||
co, err = c.Dial(a)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
defer co.Close()
|
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 {
|
||||||
|
return c.exchange(m, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
q := m.Question[0]
|
||||||
|
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) {
|
||||||
|
return c.exchange(m, conn)
|
||||||
|
})
|
||||||
|
if r != nil && shared {
|
||||||
|
r = r.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, rtt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
|
||||||
opt := m.IsEdns0()
|
opt := m.IsEdns0()
|
||||||
// If EDNS0 is used use that for size.
|
// If EDNS0 is used use that for size.
|
||||||
@ -166,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())))
|
||||||
@ -175,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
|
||||||
@ -202,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
|
||||||
}
|
}
|
||||||
@ -221,24 +247,21 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
switch t := co.Conn.(type) {
|
if _, ok := co.Conn.(net.PacketConn); ok {
|
||||||
case *net.TCPConn, *tls.Conn:
|
|
||||||
r := t.(io.Reader)
|
|
||||||
|
|
||||||
// First two bytes specify the length of the entire message.
|
|
||||||
l, err := tcpMsgLen(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p = make([]byte, l)
|
|
||||||
n, err = tcpRead(r, p)
|
|
||||||
default:
|
|
||||||
if co.UDPSize > MinMsgSize {
|
if co.UDPSize > MinMsgSize {
|
||||||
p = make([]byte, co.UDPSize)
|
p = make([]byte, co.UDPSize)
|
||||||
} else {
|
} else {
|
||||||
p = make([]byte, MinMsgSize)
|
p = make([]byte, MinMsgSize)
|
||||||
}
|
}
|
||||||
n, err = co.Read(p)
|
n, err = co.Read(p)
|
||||||
|
} else {
|
||||||
|
var length uint16
|
||||||
|
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p = make([]byte, length)
|
||||||
|
n, err = io.ReadFull(co.Conn, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -258,74 +281,26 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
|||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
|
|
||||||
func tcpMsgLen(t io.Reader) (int, error) {
|
|
||||||
p := []byte{0, 0}
|
|
||||||
n, err := t.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// As seen with my local router/switch, returns 1 byte on the above read,
|
|
||||||
// resulting a a ShortRead. Just write it out (instead of loop) and read the
|
|
||||||
// other byte.
|
|
||||||
if n == 1 {
|
|
||||||
n1, err := t.Read(p[1:])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
n += n1
|
|
||||||
}
|
|
||||||
|
|
||||||
if n != 2 {
|
|
||||||
return 0, ErrShortRead
|
|
||||||
}
|
|
||||||
l := binary.BigEndian.Uint16(p)
|
|
||||||
if l == 0 {
|
|
||||||
return 0, ErrShortRead
|
|
||||||
}
|
|
||||||
return int(l), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
|
|
||||||
func tcpRead(t io.Reader, p []byte) (int, error) {
|
|
||||||
n, err := t.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
for n < len(p) {
|
|
||||||
j, err := t.Read(p[n:])
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
n += j
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read implements the net.Conn read method.
|
// Read implements the net.Conn read method.
|
||||||
func (co *Conn) Read(p []byte) (n int, err error) {
|
func (co *Conn) Read(p []byte) (n int, err error) {
|
||||||
if co.Conn == nil {
|
if co.Conn == nil {
|
||||||
return 0, ErrConnEmpty
|
return 0, ErrConnEmpty
|
||||||
}
|
}
|
||||||
if len(p) < 2 {
|
|
||||||
|
if _, ok := co.Conn.(net.PacketConn); ok {
|
||||||
|
// UDP connection
|
||||||
|
return co.Conn.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
var length uint16
|
||||||
|
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if int(length) > len(p) {
|
||||||
return 0, io.ErrShortBuffer
|
return 0, io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
switch t := co.Conn.(type) {
|
|
||||||
case *net.TCPConn, *tls.Conn:
|
|
||||||
r := t.(io.Reader)
|
|
||||||
|
|
||||||
l, err := tcpMsgLen(r)
|
return io.ReadFull(co.Conn, p[:length])
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if l > len(p) {
|
|
||||||
return l, io.ErrShortBuffer
|
|
||||||
}
|
|
||||||
return tcpRead(r, p[:l])
|
|
||||||
}
|
|
||||||
// UDP connection
|
|
||||||
return co.Conn.Read(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMsg sends a message through the connection co.
|
// WriteMsg sends a message through the connection co.
|
||||||
@ -335,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 {
|
||||||
@ -352,25 +331,19 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write implements the net.Conn Write method.
|
// Write implements the net.Conn Write method.
|
||||||
func (co *Conn) Write(p []byte) (n int, err error) {
|
func (co *Conn) Write(p []byte) (int, error) {
|
||||||
switch t := co.Conn.(type) {
|
if len(p) > MaxMsgSize {
|
||||||
case *net.TCPConn, *tls.Conn:
|
return 0, &Error{err: "message too large"}
|
||||||
w := t.(io.Writer)
|
|
||||||
|
|
||||||
lp := len(p)
|
|
||||||
if lp < 2 {
|
|
||||||
return 0, io.ErrShortBuffer
|
|
||||||
}
|
|
||||||
if lp > MaxMsgSize {
|
|
||||||
return 0, &Error{err: "message too large"}
|
|
||||||
}
|
|
||||||
l := make([]byte, 2, lp+2)
|
|
||||||
binary.BigEndian.PutUint16(l, uint16(lp))
|
|
||||||
p = append(l, p...)
|
|
||||||
n, err := io.Copy(w, bytes.NewReader(p))
|
|
||||||
return int(n), err
|
|
||||||
}
|
}
|
||||||
return co.Conn.Write(p)
|
|
||||||
|
if _, ok := co.Conn.(net.PacketConn); ok {
|
||||||
|
return co.Conn.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := make([]byte, 2+len(p))
|
||||||
|
binary.BigEndian.PutUint16(msg, uint16(len(p)))
|
||||||
|
copy(msg[2:], p)
|
||||||
|
return co.Conn.Write(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the appropriate timeout for a specific request
|
// Return the appropriate timeout for a specific request
|
||||||
@ -406,14 +379,14 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||||
// This function is going away, but can easily be mimicked:
|
// Deprecated: This function is going away, but can easily be mimicked:
|
||||||
//
|
//
|
||||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||||
// co.WriteMsg(m)
|
// co.WriteMsg(m)
|
||||||
|
8
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
8
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
@ -68,14 +68,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "search": // set search path to given servers
|
case "search": // set search path to given servers
|
||||||
c.Search = make([]string, len(f)-1)
|
c.Search = append([]string(nil), f[1:]...)
|
||||||
for i := 0; i < len(c.Search); i++ {
|
|
||||||
c.Search[i] = f[i+1]
|
|
||||||
}
|
|
||||||
|
|
||||||
case "options": // magic options
|
case "options": // magic options
|
||||||
for i := 1; i < len(f); i++ {
|
for _, s := range f[1:] {
|
||||||
s := f[i]
|
|
||||||
switch {
|
switch {
|
||||||
case len(s) >= 6 && s[:6] == "ndots:":
|
case len(s) >= 6 && s[:6] == "ndots:":
|
||||||
n, _ := strconv.Atoi(s[6:])
|
n, _ := strconv.Atoi(s[6:])
|
||||||
|
37
vendor/github.com/miekg/dns/defaults.go
generated
vendored
37
vendor/github.com/miekg/dns/defaults.go
generated
vendored
@ -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}
|
||||||
@ -146,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
|
|||||||
// record in the additional section will do. It returns the OPT record
|
// record in the additional section will do. It returns the OPT record
|
||||||
// found or nil.
|
// found or nil.
|
||||||
func (dns *Msg) IsEdns0() *OPT {
|
func (dns *Msg) IsEdns0() *OPT {
|
||||||
// EDNS0 is at the end of the additional section, start there.
|
// RFC 6891, Section 6.1.1 allows the OPT record to appear
|
||||||
// We might want to change this to *only* look at the last two
|
// anywhere in the additional record section, but it's usually at
|
||||||
// records. So we see TSIG and/or OPT - this a slightly bigger
|
// the end so start there.
|
||||||
// change though.
|
|
||||||
for i := len(dns.Extra) - 1; i >= 0; i-- {
|
for i := len(dns.Extra) - 1; i >= 0; i-- {
|
||||||
if dns.Extra[i].Header().Rrtype == TypeOPT {
|
if dns.Extra[i].Header().Rrtype == TypeOPT {
|
||||||
return dns.Extra[i].(*OPT)
|
return dns.Extra[i].(*OPT)
|
||||||
@ -158,6 +157,21 @@ func (dns *Msg) IsEdns0() *OPT {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// popEdns0 is like IsEdns0, but it removes the record from the message.
|
||||||
|
func (dns *Msg) popEdns0() *OPT {
|
||||||
|
// RFC 6891, Section 6.1.1 allows the OPT record to appear
|
||||||
|
// anywhere in the additional record section, but it's usually at
|
||||||
|
// the end so start there.
|
||||||
|
for i := len(dns.Extra) - 1; i >= 0; i-- {
|
||||||
|
if dns.Extra[i].Header().Rrtype == TypeOPT {
|
||||||
|
opt := dns.Extra[i].(*OPT)
|
||||||
|
dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsDomainName checks if s is a valid domain name, it returns the number of
|
// IsDomainName checks if s is a valid domain name, it returns the number of
|
||||||
// labels and true, when a domain name is valid. Note that non fully qualified
|
// labels and true, when a domain name is valid. Note that non fully qualified
|
||||||
// domain name is considered valid, in this case the last label is counted in
|
// domain name is considered valid, in this case the last label is counted in
|
||||||
@ -303,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
|
||||||
@ -329,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."...)
|
||||||
@ -350,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
|
||||||
}
|
}
|
||||||
|
34
vendor/github.com/miekg/dns/dns.go
generated
vendored
34
vendor/github.com/miekg/dns/dns.go
generated
vendored
@ -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.
|
||||||
@ -54,7 +57,7 @@ type RR interface {
|
|||||||
// parse parses an RR from zone file format.
|
// parse parses an RR from zone file format.
|
||||||
//
|
//
|
||||||
// This will only be called on a new and empty RR type with only the header populated.
|
// This will only be called on a new and empty RR type with only the header populated.
|
||||||
parse(c *zlexer, origin, file string) *ParseError
|
parse(c *zlexer, origin string) *ParseError
|
||||||
|
|
||||||
// isDuplicate returns whether the two RRs are duplicates.
|
// isDuplicate returns whether the two RRs are duplicates.
|
||||||
isDuplicate(r2 RR) bool
|
isDuplicate(r2 RR) bool
|
||||||
@ -105,13 +108,13 @@ func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
|
|||||||
panic("dns: internal error: unpack should never be called on RR_Header")
|
panic("dns: internal error: unpack should never be called on RR_Header")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError {
|
func (h *RR_Header) parse(c *zlexer, origin string) *ParseError {
|
||||||
panic("dns: internal error: parse should never be called on RR_Header")
|
panic("dns: internal error: parse should never be called on RR_Header")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
||||||
func (rr *RFC3597) ToRFC3597(r RR) error {
|
func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||||
buf := make([]byte, Len(r)*2)
|
buf := make([]byte, 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
|
||||||
}
|
}
|
||||||
|
145
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
145
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
@ -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.
|
||||||
@ -141,8 +138,8 @@ func (k *DNSKEY) KeyTag() uint16 {
|
|||||||
switch k.Algorithm {
|
switch k.Algorithm {
|
||||||
case RSAMD5:
|
case RSAMD5:
|
||||||
// Look at the bottom two bytes of the modules, which the last
|
// Look at the bottom two bytes of the modules, which the last
|
||||||
// item in the pubkey. We could do this faster by looking directly
|
// item in the pubkey.
|
||||||
// at the base64 values. But I'm lazy.
|
// This algorithm has been deprecated, but keep this key-tag calculation.
|
||||||
modulus, _ := fromBase64([]byte(k.PublicKey))
|
modulus, _ := fromBase64([]byte(k.PublicKey))
|
||||||
if len(modulus) > 1 {
|
if len(modulus) > 1 {
|
||||||
x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
|
x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
|
||||||
@ -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,10 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rr.Signature = toBase64(signature)
|
rr.Signature = toBase64(signature)
|
||||||
|
return nil
|
||||||
|
case RSAMD5, DSA, DSANSEC3SHA1:
|
||||||
|
// See RFC 6944.
|
||||||
|
return ErrAlg
|
||||||
default:
|
default:
|
||||||
h := hash.New()
|
h := hash.New()
|
||||||
h.Write(signdata)
|
h.Write(signdata)
|
||||||
@ -329,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) {
|
||||||
@ -343,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
|
||||||
@ -363,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) {
|
||||||
@ -402,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
|
||||||
@ -420,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)
|
||||||
@ -445,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 {
|
||||||
@ -509,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 {
|
||||||
@ -556,19 +554,18 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
|||||||
pubkey := new(rsa.PublicKey)
|
pubkey := new(rsa.PublicKey)
|
||||||
|
|
||||||
var expo uint64
|
var expo uint64
|
||||||
for i := 0; i < int(explen); i++ {
|
// The exponent of length explen is between keyoff and modoff.
|
||||||
|
for _, v := range keybuf[keyoff:modoff] {
|
||||||
expo <<= 8
|
expo <<= 8
|
||||||
expo |= uint64(keybuf[keyoff+i])
|
expo |= uint64(v)
|
||||||
}
|
}
|
||||||
if expo > 1<<31-1 {
|
if expo > 1<<31-1 {
|
||||||
// Larger exponent than supported by the crypto package.
|
// Larger exponent than supported by the crypto package.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pubkey.E = int(expo)
|
pubkey.E = int(expo)
|
||||||
|
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
|
||||||
pubkey.N = big.NewInt(0)
|
|
||||||
pubkey.N.SetBytes(keybuf[modoff:])
|
|
||||||
|
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,34 +590,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pubkey.X = big.NewInt(0)
|
pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
|
||||||
pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
|
pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
|
||||||
pubkey.Y = big.NewInt(0)
|
|
||||||
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
|
|
||||||
return pubkey
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = big.NewInt(0).SetBytes(q)
|
|
||||||
pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
|
|
||||||
pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
|
|
||||||
pubkey.Y = big.NewInt(0).SetBytes(y)
|
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
||||||
|
49
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
49
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
@ -2,14 +2,12 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
|
||||||
"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.
|
||||||
@ -20,11 +18,7 @@ import (
|
|||||||
// bits should be set to the size of the algorithm.
|
// bits should be set to the size of the algorithm.
|
||||||
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
||||||
switch k.Algorithm {
|
switch k.Algorithm {
|
||||||
case DSA, DSANSEC3SHA1:
|
case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
|
||||||
if bits != 1024 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
|
|
||||||
if bits < 512 || bits > 4096 {
|
if bits < 512 || bits > 4096 {
|
||||||
return nil, ErrKeySize
|
return nil, ErrKeySize
|
||||||
}
|
}
|
||||||
@ -44,23 +38,12 @@ 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 {
|
||||||
case DSA, DSANSEC3SHA1:
|
case RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
|
||||||
params := new(dsa.Parameters)
|
|
||||||
if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
priv := new(dsa.PrivateKey)
|
|
||||||
priv.PublicKey.Parameters = *params
|
|
||||||
err := dsa.GenerateKey(priv, rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
|
|
||||||
return priv, nil
|
|
||||||
case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, bits)
|
priv, err := rsa.GenerateKey(rand.Reader, bits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -120,16 +103,6 @@ func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the public key for DSA
|
|
||||||
func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
|
|
||||||
if _Q == nil || _P == nil || _G == nil || _Y == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
buf := dsaToBuf(_Q, _P, _G, _Y)
|
|
||||||
k.PublicKey = toBase64(buf)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the public key for Ed25519
|
// Set the public key for Ed25519
|
||||||
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
|
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
|
||||||
if _K == nil {
|
if _K == nil {
|
||||||
@ -164,15 +137,3 @@ func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
|
|||||||
buf = append(buf, intToBytes(_Y, intlen)...)
|
buf = append(buf, intToBytes(_Y, intlen)...)
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the public key for X and Y for Curve. The two
|
|
||||||
// values are just concatenated.
|
|
||||||
func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
|
|
||||||
t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
|
|
||||||
buf := []byte{byte(t)}
|
|
||||||
buf = append(buf, intToBytes(_Q, 20)...)
|
|
||||||
buf = append(buf, intToBytes(_P, 64+t*8)...)
|
|
||||||
buf = append(buf, intToBytes(_G, 64+t*8)...)
|
|
||||||
buf = append(buf, intToBytes(_Y, 64+t*8)...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
73
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
73
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
@ -3,15 +3,13 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
|
||||||
"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.
|
||||||
@ -44,26 +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 DSA:
|
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
|
||||||
priv, err := readPrivateKeyDSA(m)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pub := k.publicKeyDSA()
|
|
||||||
if pub == nil {
|
|
||||||
return nil, ErrKey
|
|
||||||
}
|
|
||||||
priv.PublicKey = *pub
|
|
||||||
return priv, nil
|
|
||||||
case RSAMD5:
|
|
||||||
fallthrough
|
|
||||||
case RSASHA1:
|
|
||||||
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
|
||||||
@ -74,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
|
||||||
@ -92,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,21 +84,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
|||||||
}
|
}
|
||||||
switch k {
|
switch k {
|
||||||
case "modulus":
|
case "modulus":
|
||||||
p.PublicKey.N = big.NewInt(0)
|
p.PublicKey.N = new(big.Int).SetBytes(v1)
|
||||||
p.PublicKey.N.SetBytes(v1)
|
|
||||||
case "publicexponent":
|
case "publicexponent":
|
||||||
i := big.NewInt(0)
|
i := new(big.Int).SetBytes(v1)
|
||||||
i.SetBytes(v1)
|
|
||||||
p.PublicKey.E = int(i.Int64()) // int64 should be large enough
|
p.PublicKey.E = int(i.Int64()) // int64 should be large enough
|
||||||
case "privateexponent":
|
case "privateexponent":
|
||||||
p.D = big.NewInt(0)
|
p.D = new(big.Int).SetBytes(v1)
|
||||||
p.D.SetBytes(v1)
|
|
||||||
case "prime1":
|
case "prime1":
|
||||||
p.Primes[0] = big.NewInt(0)
|
p.Primes[0] = new(big.Int).SetBytes(v1)
|
||||||
p.Primes[0].SetBytes(v1)
|
|
||||||
case "prime2":
|
case "prime2":
|
||||||
p.Primes[1] = big.NewInt(0)
|
p.Primes[1] = new(big.Int).SetBytes(v1)
|
||||||
p.Primes[1].SetBytes(v1)
|
|
||||||
}
|
}
|
||||||
case "exponent1", "exponent2", "coefficient":
|
case "exponent1", "exponent2", "coefficient":
|
||||||
// not used in Go (yet)
|
// not used in Go (yet)
|
||||||
@ -134,27 +104,9 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
|
|
||||||
p := new(dsa.PrivateKey)
|
|
||||||
p.X = big.NewInt(0)
|
|
||||||
for k, v := range m {
|
|
||||||
switch k {
|
|
||||||
case "private_value(x)":
|
|
||||||
v1, err := fromBase64([]byte(v))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.X.SetBytes(v1)
|
|
||||||
case "created", "publish", "activate":
|
|
||||||
/* not used in Go (yet) */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
|
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
|
||||||
p := new(ecdsa.PrivateKey)
|
p := new(ecdsa.PrivateKey)
|
||||||
p.D = big.NewInt(0)
|
p.D = new(big.Int)
|
||||||
// TODO: validate that the required flags are present
|
// TODO: validate that the required flags are present
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
switch k {
|
switch k {
|
||||||
@ -322,6 +274,11 @@ func (kl *klexer) Next() (lex, bool) {
|
|||||||
commt = false
|
commt = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if kl.key && str.Len() == 0 {
|
||||||
|
// ignore empty lines
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
kl.key = true
|
kl.key = true
|
||||||
|
|
||||||
l.value = zValue
|
l.value = zValue
|
||||||
|
36
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
36
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
@ -2,21 +2,21 @@ 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"
|
||||||
|
|
||||||
|
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] + ")"
|
||||||
@ -31,12 +31,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
|||||||
prime2 := toBase64(p.Primes[1].Bytes())
|
prime2 := toBase64(p.Primes[1].Bytes())
|
||||||
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
|
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
|
||||||
// and from: http://code.google.com/p/go/issues/detail?id=987
|
// and from: http://code.google.com/p/go/issues/detail?id=987
|
||||||
one := big.NewInt(1)
|
p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
|
||||||
p1 := big.NewInt(0).Sub(p.Primes[0], one)
|
q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
|
||||||
q1 := big.NewInt(0).Sub(p.Primes[1], one)
|
exp1 := new(big.Int).Mod(p.D, p1)
|
||||||
exp1 := big.NewInt(0).Mod(p.D, p1)
|
exp2 := new(big.Int).Mod(p.D, q1)
|
||||||
exp2 := big.NewInt(0).Mod(p.D, q1)
|
coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
|
||||||
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
|
|
||||||
|
|
||||||
exponent1 := toBase64(exp1.Bytes())
|
exponent1 := toBase64(exp1.Bytes())
|
||||||
exponent2 := toBase64(exp2.Bytes())
|
exponent2 := toBase64(exp2.Bytes())
|
||||||
@ -66,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 +
|
||||||
|
45
vendor/github.com/miekg/dns/doc.go
generated
vendored
45
vendor/github.com/miekg/dns/doc.go
generated
vendored
@ -83,7 +83,7 @@ with:
|
|||||||
|
|
||||||
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
||||||
|
|
||||||
When this functions returns you will get dns message. A dns message consists
|
When this functions returns you will get DNS message. A DNS message consists
|
||||||
out of four sections.
|
out of four sections.
|
||||||
The question section: in.Question, the answer section: in.Answer,
|
The question section: in.Question, the answer section: in.Answer,
|
||||||
the authority section: in.Ns and the additional section: in.Extra.
|
the authority section: in.Ns and the additional section: in.Extra.
|
||||||
@ -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)
|
||||||
@ -221,7 +245,7 @@ RFC 6895 sets aside a range of type codes for private use. This range is 65,280
|
|||||||
- 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
- 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
||||||
can be used, before requesting an official type code from IANA.
|
can be used, before requesting an official type code from IANA.
|
||||||
|
|
||||||
See https://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
|
See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
EDNS0
|
EDNS0
|
||||||
@ -238,9 +262,8 @@ Basic use pattern for creating an (empty) OPT RR:
|
|||||||
|
|
||||||
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
|
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
|
||||||
Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
|
Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
|
||||||
EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
|
EDNS0_SUBNET (RFC 7871). Note that these options may be combined in an OPT RR.
|
||||||
may be combined in an OPT RR. Basic use pattern for a server to check if (and
|
Basic use pattern for a server to check if (and which) options are set:
|
||||||
which) options are set:
|
|
||||||
|
|
||||||
// o is a dns.OPT
|
// o is a dns.OPT
|
||||||
for _, s := range o.Option {
|
for _, s := range o.Option {
|
||||||
@ -261,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.
|
||||||
|
11
vendor/github.com/miekg/dns/duplicate.go
generated
vendored
11
vendor/github.com/miekg/dns/duplicate.go
generated
vendored
@ -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 is 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()) {
|
||||||
@ -27,12 +26,12 @@ func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Rrtype != r2.Rrtype {
|
if r1.Rrtype != r2.Rrtype {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Name, r2.Name) {
|
if !isDuplicateName(r1.Name, r2.Name) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// ignore TTL
|
// ignore TTL
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// isDulicateName checks if the domain names s1 and s2 are equal.
|
// isDuplicateName checks if the domain names s1 and s2 are equal.
|
||||||
func isDulicateName(s1, s2 string) bool { return equal(s1, s2) }
|
func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }
|
||||||
|
239
vendor/github.com/miekg/dns/edns.go
generated
vendored
239
vendor/github.com/miekg/dns/edns.go
generated
vendored
@ -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
|
||||||
@ -80,19 +118,19 @@ func (rr *OPT) String() string {
|
|||||||
|
|
||||||
func (rr *OPT) len(off int, compression map[string]struct{}) int {
|
func (rr *OPT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
for i := 0; i < len(rr.Option); i++ {
|
for _, o := range rr.Option {
|
||||||
l += 4 // Account for 2-byte option code and 2-byte option length.
|
l += 4 // Account for 2-byte option code and 2-byte option length.
|
||||||
lo, _ := rr.Option[i].pack()
|
lo, _ := o.pack()
|
||||||
l += len(lo)
|
l += len(lo)
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *OPT) parse(c *zlexer, origin, file 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.
|
||||||
@ -159,6 +207,8 @@ type EDNS0 interface {
|
|||||||
unpack([]byte) error
|
unpack([]byte) error
|
||||||
// String returns the string representation of the option.
|
// String returns the string representation of the option.
|
||||||
String() string
|
String() string
|
||||||
|
// copy returns a deep-copy of the option.
|
||||||
|
copy() EDNS0
|
||||||
}
|
}
|
||||||
|
|
||||||
// EDNS0_NSID option is used to retrieve a nameserver
|
// EDNS0_NSID option is used to retrieve a nameserver
|
||||||
@ -190,6 +240,7 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
|
|||||||
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
|
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
|
||||||
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
||||||
func (e *EDNS0_NSID) String() string { return e.Nsid }
|
func (e *EDNS0_NSID) String() string { return e.Nsid }
|
||||||
|
func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
|
||||||
|
|
||||||
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
|
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
|
||||||
// an idea of where the client lives. See RFC 7871. It can then give back a different
|
// an idea of where the client lives. See RFC 7871. It can then give back a different
|
||||||
@ -307,6 +358,16 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_SUBNET) copy() EDNS0 {
|
||||||
|
return &EDNS0_SUBNET{
|
||||||
|
e.Code,
|
||||||
|
e.Family,
|
||||||
|
e.SourceNetmask,
|
||||||
|
e.SourceScope,
|
||||||
|
e.Address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
|
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
|
||||||
//
|
//
|
||||||
// o := new(dns.OPT)
|
// o := new(dns.OPT)
|
||||||
@ -342,11 +403,12 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
|
|||||||
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
|
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
|
||||||
func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
|
func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
|
||||||
func (e *EDNS0_COOKIE) String() string { return e.Cookie }
|
func (e *EDNS0_COOKIE) String() string { return e.Cookie }
|
||||||
|
func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} }
|
||||||
|
|
||||||
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
|
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
|
||||||
// an expiration on an update RR. This is helpful for clients that cannot clean
|
// an expiration on an update RR. This is helpful for clients that cannot clean
|
||||||
// up after themselves. This is a draft RFC and more information can be found at
|
// up after themselves. This is a draft RFC and more information can be found at
|
||||||
// http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
// https://tools.ietf.org/html/draft-sekar-dns-ul-02
|
||||||
//
|
//
|
||||||
// o := new(dns.OPT)
|
// o := new(dns.OPT)
|
||||||
// o.Hdr.Name = "."
|
// o.Hdr.Name = "."
|
||||||
@ -356,23 +418,36 @@ func (e *EDNS0_COOKIE) String() string { return e.Cookie }
|
|||||||
// e.Lease = 120 // in seconds
|
// e.Lease = 120 // in seconds
|
||||||
// o.Option = append(o.Option, e)
|
// o.Option = append(o.Option, e)
|
||||||
type EDNS0_UL struct {
|
type EDNS0_UL struct {
|
||||||
Code uint16 // Always EDNS0UL
|
Code uint16 // Always EDNS0UL
|
||||||
Lease uint32
|
Lease uint32
|
||||||
|
KeyLease uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option implements the EDNS0 interface.
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
||||||
func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
|
func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) }
|
||||||
|
func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} }
|
||||||
|
|
||||||
// Copied: http://golang.org/src/pkg/net/dnsmsg.go
|
// Copied: http://golang.org/src/pkg/net/dnsmsg.go
|
||||||
func (e *EDNS0_UL) pack() ([]byte, error) {
|
func (e *EDNS0_UL) pack() ([]byte, error) {
|
||||||
b := make([]byte, 4)
|
var b []byte
|
||||||
|
if e.KeyLease == 0 {
|
||||||
|
b = make([]byte, 4)
|
||||||
|
} else {
|
||||||
|
b = make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint32(b[4:], e.KeyLease)
|
||||||
|
}
|
||||||
binary.BigEndian.PutUint32(b, e.Lease)
|
binary.BigEndian.PutUint32(b, e.Lease)
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_UL) unpack(b []byte) error {
|
func (e *EDNS0_UL) unpack(b []byte) error {
|
||||||
if len(b) < 4 {
|
switch len(b) {
|
||||||
|
case 4:
|
||||||
|
e.KeyLease = 0
|
||||||
|
case 8:
|
||||||
|
e.KeyLease = binary.BigEndian.Uint32(b[4:])
|
||||||
|
default:
|
||||||
return ErrBuf
|
return ErrBuf
|
||||||
}
|
}
|
||||||
e.Lease = binary.BigEndian.Uint32(b)
|
e.Lease = binary.BigEndian.Uint32(b)
|
||||||
@ -421,8 +496,11 @@ func (e *EDNS0_LLQ) String() string {
|
|||||||
" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
|
" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_LLQ) copy() EDNS0 {
|
||||||
|
return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
|
||||||
|
}
|
||||||
|
|
||||||
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
|
// EDNS0_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
|
||||||
@ -435,15 +513,16 @@ func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
|||||||
|
|
||||||
func (e *EDNS0_DAU) String() string {
|
func (e *EDNS0_DAU) String() string {
|
||||||
s := ""
|
s := ""
|
||||||
for i := 0; i < len(e.AlgCode); i++ {
|
for _, alg := range e.AlgCode {
|
||||||
if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
|
if a, ok := AlgorithmToString[alg]; ok {
|
||||||
s += " " + a
|
s += " " + a
|
||||||
} else {
|
} else {
|
||||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
s += " " + strconv.Itoa(int(alg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
|
||||||
|
|
||||||
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
|
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_DHU struct {
|
type EDNS0_DHU struct {
|
||||||
@ -458,15 +537,16 @@ func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
|||||||
|
|
||||||
func (e *EDNS0_DHU) String() string {
|
func (e *EDNS0_DHU) String() string {
|
||||||
s := ""
|
s := ""
|
||||||
for i := 0; i < len(e.AlgCode); i++ {
|
for _, alg := range e.AlgCode {
|
||||||
if a, ok := HashToString[e.AlgCode[i]]; ok {
|
if a, ok := HashToString[alg]; ok {
|
||||||
s += " " + a
|
s += " " + a
|
||||||
} else {
|
} else {
|
||||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
s += " " + strconv.Itoa(int(alg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
|
||||||
|
|
||||||
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
|
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_N3U struct {
|
type EDNS0_N3U struct {
|
||||||
@ -482,17 +562,18 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
|
|||||||
func (e *EDNS0_N3U) String() string {
|
func (e *EDNS0_N3U) String() string {
|
||||||
// Re-use the hash map
|
// Re-use the hash map
|
||||||
s := ""
|
s := ""
|
||||||
for i := 0; i < len(e.AlgCode); i++ {
|
for _, alg := range e.AlgCode {
|
||||||
if a, ok := HashToString[e.AlgCode[i]]; ok {
|
if a, ok := HashToString[alg]; ok {
|
||||||
s += " " + a
|
s += " " + a
|
||||||
} else {
|
} else {
|
||||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
s += " " + strconv.Itoa(int(alg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
|
||||||
|
|
||||||
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
|
// EDNS0_EXPIRE 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
|
||||||
@ -501,6 +582,7 @@ type EDNS0_EXPIRE struct {
|
|||||||
// Option implements the EDNS0 interface.
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
|
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
|
||||||
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
|
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
|
||||||
|
func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire} }
|
||||||
|
|
||||||
func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
|
func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
@ -509,6 +591,10 @@ func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_EXPIRE) unpack(b []byte) error {
|
func (e *EDNS0_EXPIRE) unpack(b []byte) error {
|
||||||
|
if len(b) == 0 {
|
||||||
|
// zero-length EXPIRE query, see RFC 7314 Section 2
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if len(b) < 4 {
|
if len(b) < 4 {
|
||||||
return ErrBuf
|
return ErrBuf
|
||||||
}
|
}
|
||||||
@ -539,6 +625,11 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
|
|||||||
func (e *EDNS0_LOCAL) String() string {
|
func (e *EDNS0_LOCAL) String() string {
|
||||||
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_LOCAL) copy() EDNS0 {
|
||||||
|
b := make([]byte, len(e.Data))
|
||||||
|
copy(b, e.Data)
|
||||||
|
return &EDNS0_LOCAL{e.Code, b}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
||||||
b := make([]byte, len(e.Data))
|
b := make([]byte, len(e.Data))
|
||||||
@ -611,6 +702,7 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
|
||||||
|
|
||||||
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
||||||
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
||||||
@ -624,3 +716,106 @@ func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
|
|||||||
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
|
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
|
||||||
func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
|
func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
|
||||||
func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
|
func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
|
||||||
|
func (e *EDNS0_PADDING) copy() EDNS0 {
|
||||||
|
b := make([]byte, len(e.Padding))
|
||||||
|
copy(b, e.Padding)
|
||||||
|
return &EDNS0_PADDING{b}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
6
vendor/github.com/miekg/dns/format.go
generated
vendored
6
vendor/github.com/miekg/dns/format.go
generated
vendored
@ -31,6 +31,9 @@ func Field(r RR, i int) string {
|
|||||||
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
|
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
|
||||||
case `dns:"a"`:
|
case `dns:"a"`:
|
||||||
// TODO(miek): Hmm store this as 16 bytes
|
// TODO(miek): Hmm store this as 16 bytes
|
||||||
|
if d.Len() < net.IPv4len {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
if d.Len() < net.IPv6len {
|
if d.Len() < net.IPv6len {
|
||||||
return net.IPv4(byte(d.Index(0).Uint()),
|
return net.IPv4(byte(d.Index(0).Uint()),
|
||||||
byte(d.Index(1).Uint()),
|
byte(d.Index(1).Uint()),
|
||||||
@ -42,6 +45,9 @@ func Field(r RR, i int) string {
|
|||||||
byte(d.Index(14).Uint()),
|
byte(d.Index(14).Uint()),
|
||||||
byte(d.Index(15).Uint())).String()
|
byte(d.Index(15).Uint())).String()
|
||||||
case `dns:"aaaa"`:
|
case `dns:"aaaa"`:
|
||||||
|
if d.Len() < net.IPv6len {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return net.IP{
|
return net.IP{
|
||||||
byte(d.Index(0).Uint()),
|
byte(d.Index(0).Uint()),
|
||||||
byte(d.Index(1).Uint()),
|
byte(d.Index(1).Uint()),
|
||||||
|
11
vendor/github.com/miekg/dns/fuzz.go
generated
vendored
11
vendor/github.com/miekg/dns/fuzz.go
generated
vendored
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
func Fuzz(data []byte) int {
|
||||||
msg := new(Msg)
|
msg := new(Msg)
|
||||||
|
|
||||||
@ -16,7 +18,14 @@ func Fuzz(data []byte) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FuzzNewRR(data []byte) int {
|
func FuzzNewRR(data []byte) int {
|
||||||
if _, err := NewRR(string(data)); err != nil {
|
str := string(data)
|
||||||
|
// Do not fuzz lines that include the $INCLUDE keyword and hint the fuzzer
|
||||||
|
// at avoiding them.
|
||||||
|
// See GH#1025 for context.
|
||||||
|
if strings.Contains(strings.ToUpper(str), "$INCLUDE") {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if _, err := NewRR(str); err != nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
|
33
vendor/github.com/miekg/dns/generate.go
generated
vendored
33
vendor/github.com/miekg/dns/generate.go
generated
vendored
@ -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,20 +40,24 @@ 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)
|
||||||
}
|
}
|
||||||
if end < 0 || start < 0 || end < start {
|
if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
|
||||||
return zp.setParseError("bad range in $GENERATE range", l)
|
return zp.setParseError("bad range in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
zp.c.Next() // _BLANK
|
// _BLANK
|
||||||
|
l, ok := zp.c.Next()
|
||||||
|
if !ok || l.value != zBlank {
|
||||||
|
return zp.setParseError("garbage after $GENERATE range", l)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a complete new string, which we then parse again.
|
// Create a complete new string, which we then parse again.
|
||||||
var s string
|
var s string
|
||||||
@ -81,6 +85,7 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
|||||||
}
|
}
|
||||||
zp.sub = NewZoneParser(r, zp.origin, zp.file)
|
zp.sub = NewZoneParser(r, zp.origin, zp.file)
|
||||||
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
|
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
|
||||||
|
zp.sub.generateDisallowed = true
|
||||||
zp.sub.SetDefaultTTL(defaultTtl)
|
zp.sub.SetDefaultTTL(defaultTtl)
|
||||||
return zp.subNext()
|
return zp.subNext()
|
||||||
}
|
}
|
||||||
@ -89,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
|
||||||
|
|
||||||
@ -168,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] == '{' {
|
||||||
@ -203,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
|
||||||
@ -224,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"
|
||||||
}
|
}
|
||||||
|
68
vendor/github.com/miekg/dns/labels.go
generated
vendored
68
vendor/github.com/miekg/dns/labels.go
generated
vendored
@ -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
|
||||||
@ -28,9 +28,7 @@ func SplitDomainName(s string) (labels []string) {
|
|||||||
case 1:
|
case 1:
|
||||||
// no-op
|
// no-op
|
||||||
default:
|
default:
|
||||||
end := 0
|
for _, end := range idx[1:] {
|
||||||
for i := 1; i < len(idx); i++ {
|
|
||||||
end = idx[i]
|
|
||||||
labels = append(labels, s[begin:end-1])
|
labels = append(labels, s[begin:end-1])
|
||||||
begin = end
|
begin = end
|
||||||
}
|
}
|
||||||
@ -85,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 == "." {
|
||||||
@ -128,20 +126,23 @@ func Split(s string) []int {
|
|||||||
// The bool end is true when the end of the string has been reached.
|
// The bool end is true when the end of the string has been reached.
|
||||||
// Also see PrevLabel.
|
// Also see PrevLabel.
|
||||||
func NextLabel(s string, offset int) (i int, end bool) {
|
func NextLabel(s string, offset int) (i int, end bool) {
|
||||||
quote := false
|
if s == "" {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
for i = offset; i < len(s)-1; i++ {
|
for i = offset; i < len(s)-1; i++ {
|
||||||
switch s[i] {
|
if s[i] != '.' {
|
||||||
case '\\':
|
continue
|
||||||
quote = !quote
|
|
||||||
default:
|
|
||||||
quote = false
|
|
||||||
case '.':
|
|
||||||
if quote {
|
|
||||||
quote = !quote
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return i + 1, false
|
|
||||||
}
|
}
|
||||||
|
j := i - 1
|
||||||
|
for j >= 0 && s[j] == '\\' {
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j-i)%2 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return i + 1, false
|
||||||
}
|
}
|
||||||
return i + 1, true
|
return i + 1, true
|
||||||
}
|
}
|
||||||
@ -151,17 +152,38 @@ func NextLabel(s string, offset int) (i int, end bool) {
|
|||||||
// The bool start is true when the start of the string has been overshot.
|
// The bool start is true when the start of the string has been overshot.
|
||||||
// Also see NextLabel.
|
// Also see NextLabel.
|
||||||
func PrevLabel(s string, n int) (i int, start bool) {
|
func PrevLabel(s string, n int) (i int, start bool) {
|
||||||
|
if s == "" {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return len(s), false
|
return len(s), false
|
||||||
}
|
}
|
||||||
lab := Split(s)
|
|
||||||
if lab == nil {
|
l := len(s) - 1
|
||||||
return 0, true
|
if s[l] == '.' {
|
||||||
|
l--
|
||||||
}
|
}
|
||||||
if n > len(lab) {
|
|
||||||
return 0, true
|
for ; l >= 0 && n > 0; l-- {
|
||||||
|
if s[l] != '.' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
j := l - 1
|
||||||
|
for j >= 0 && s[j] == '\\' {
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j-l)%2 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
n--
|
||||||
|
if n == 0 {
|
||||||
|
return l + 1, false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return lab[len(lab)-n], false
|
|
||||||
|
return 0, n > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// equal compares a and b while ignoring case. It returns true when equal otherwise false.
|
// equal compares a and b while ignoring case. It returns true when equal otherwise false.
|
||||||
|
142
vendor/github.com/miekg/dns/msg.go
generated
vendored
142
vendor/github.com/miekg/dns/msg.go
generated
vendored
@ -11,14 +11,12 @@ package dns
|
|||||||
//go:generate go run msg_generate.go
|
//go:generate go run msg_generate.go
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -73,53 +71,23 @@ var (
|
|||||||
ErrTime error = &Error{err: "bad time"} // ErrTime indicates a timing error in TSIG authentication.
|
ErrTime error = &Error{err: "bad time"} // ErrTime indicates a timing error in TSIG authentication.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Id by default, returns a 16 bits random number to be used as a
|
// Id by default returns a 16-bit random number to be used as a message id. The
|
||||||
// message id. The random provided should be good enough. This being a
|
// number is drawn from a cryptographically secure random number generator.
|
||||||
// variable the function can be reassigned to a custom function.
|
// This being a variable the function can be reassigned to a custom function.
|
||||||
// For instance, to make it return a static value:
|
// For instance, to make it return a static value for testing:
|
||||||
//
|
//
|
||||||
// dns.Id = func() uint16 { return 3 }
|
// dns.Id = func() uint16 { return 3 }
|
||||||
var Id = id
|
var Id = id
|
||||||
|
|
||||||
var (
|
|
||||||
idLock sync.Mutex
|
|
||||||
idRand *rand.Rand
|
|
||||||
)
|
|
||||||
|
|
||||||
// id returns a 16 bits random number to be used as a
|
// id returns a 16 bits random number to be used as a
|
||||||
// message id. The random provided should be good enough.
|
// message id. The random provided should be good enough.
|
||||||
func id() uint16 {
|
func id() uint16 {
|
||||||
idLock.Lock()
|
var output uint16
|
||||||
|
err := binary.Read(rand.Reader, binary.BigEndian, &output)
|
||||||
if idRand == nil {
|
if err != nil {
|
||||||
// This (partially) works around
|
panic("dns: reading random id failed: " + err.Error())
|
||||||
// https://github.com/golang/go/issues/11833 by only
|
|
||||||
// seeding idRand upon the first call to id.
|
|
||||||
|
|
||||||
var seed int64
|
|
||||||
var buf [8]byte
|
|
||||||
|
|
||||||
if _, err := crand.Read(buf[:]); err == nil {
|
|
||||||
seed = int64(binary.LittleEndian.Uint64(buf[:]))
|
|
||||||
} else {
|
|
||||||
seed = rand.Int63()
|
|
||||||
}
|
|
||||||
|
|
||||||
idRand = rand.New(rand.NewSource(seed))
|
|
||||||
}
|
}
|
||||||
|
return output
|
||||||
// The call to idRand.Uint32 must be within the
|
|
||||||
// mutex lock because *rand.Rand is not safe for
|
|
||||||
// concurrent use.
|
|
||||||
//
|
|
||||||
// There is no added performance overhead to calling
|
|
||||||
// idRand.Uint32 inside a mutex lock over just
|
|
||||||
// calling rand.Uint32 as the global math/rand rng
|
|
||||||
// is internally protected by a sync.Mutex.
|
|
||||||
id := uint16(idRand.Uint32())
|
|
||||||
|
|
||||||
idLock.Unlock()
|
|
||||||
return id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgHdr is a a manually-unpacked version of (id, bits).
|
// MsgHdr is a a manually-unpacked version of (id, bits).
|
||||||
@ -429,18 +397,13 @@ Loop:
|
|||||||
if budget <= 0 {
|
if budget <= 0 {
|
||||||
return "", lenmsg, ErrLongDomain
|
return "", lenmsg, ErrLongDomain
|
||||||
}
|
}
|
||||||
for j := off; j < off+c; j++ {
|
for _, b := range msg[off : off+c] {
|
||||||
switch b := msg[j]; 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, '.')
|
||||||
@ -489,11 +452,11 @@ func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
|
|||||||
return offset, nil
|
return offset, nil
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
for i := range txt {
|
for _, s := range txt {
|
||||||
if len(txt[i]) > len(tmp) {
|
if len(s) > len(tmp) {
|
||||||
return offset, ErrBuf
|
return offset, ErrBuf
|
||||||
}
|
}
|
||||||
offset, err = packTxtString(txt[i], msg, offset, tmp)
|
offset, err = packTxtString(s, msg, offset, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return offset, err
|
return offset, err
|
||||||
}
|
}
|
||||||
@ -661,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 {
|
||||||
@ -693,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)
|
||||||
@ -773,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 {
|
||||||
@ -934,31 +903,31 @@ func (dns *Msg) String() string {
|
|||||||
s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
|
s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
|
||||||
if len(dns.Question) > 0 {
|
if len(dns.Question) > 0 {
|
||||||
s += "\n;; QUESTION SECTION:\n"
|
s += "\n;; QUESTION SECTION:\n"
|
||||||
for i := 0; i < len(dns.Question); i++ {
|
for _, r := range dns.Question {
|
||||||
s += dns.Question[i].String() + "\n"
|
s += r.String() + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dns.Answer) > 0 {
|
if len(dns.Answer) > 0 {
|
||||||
s += "\n;; ANSWER SECTION:\n"
|
s += "\n;; ANSWER SECTION:\n"
|
||||||
for i := 0; i < len(dns.Answer); i++ {
|
for _, r := range dns.Answer {
|
||||||
if dns.Answer[i] != nil {
|
if r != nil {
|
||||||
s += dns.Answer[i].String() + "\n"
|
s += r.String() + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dns.Ns) > 0 {
|
if len(dns.Ns) > 0 {
|
||||||
s += "\n;; AUTHORITY SECTION:\n"
|
s += "\n;; AUTHORITY SECTION:\n"
|
||||||
for i := 0; i < len(dns.Ns); i++ {
|
for _, r := range dns.Ns {
|
||||||
if dns.Ns[i] != nil {
|
if r != nil {
|
||||||
s += dns.Ns[i].String() + "\n"
|
s += r.String() + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dns.Extra) > 0 {
|
if len(dns.Extra) > 0 {
|
||||||
s += "\n;; ADDITIONAL SECTION:\n"
|
s += "\n;; ADDITIONAL SECTION:\n"
|
||||||
for i := 0; i < len(dns.Extra); i++ {
|
for _, r := range dns.Extra {
|
||||||
if dns.Extra[i] != nil {
|
if r != nil {
|
||||||
s += dns.Extra[i].String() + "\n"
|
s += r.String() + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1091,33 +1060,20 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
|
rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
|
||||||
var rri int
|
r1.Answer, rrArr = rrArr[:0:len(dns.Answer)], rrArr[len(dns.Answer):]
|
||||||
|
r1.Ns, rrArr = rrArr[:0:len(dns.Ns)], rrArr[len(dns.Ns):]
|
||||||
|
r1.Extra = rrArr[:0:len(dns.Extra)]
|
||||||
|
|
||||||
if len(dns.Answer) > 0 {
|
for _, r := range dns.Answer {
|
||||||
rrbegin := rri
|
r1.Answer = append(r1.Answer, r.copy())
|
||||||
for i := 0; i < len(dns.Answer); i++ {
|
|
||||||
rrArr[rri] = dns.Answer[i].copy()
|
|
||||||
rri++
|
|
||||||
}
|
|
||||||
r1.Answer = rrArr[rrbegin:rri:rri]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dns.Ns) > 0 {
|
for _, r := range dns.Ns {
|
||||||
rrbegin := rri
|
r1.Ns = append(r1.Ns, r.copy())
|
||||||
for i := 0; i < len(dns.Ns); i++ {
|
|
||||||
rrArr[rri] = dns.Ns[i].copy()
|
|
||||||
rri++
|
|
||||||
}
|
|
||||||
r1.Ns = rrArr[rrbegin:rri:rri]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dns.Extra) > 0 {
|
for _, r := range dns.Extra {
|
||||||
rrbegin := rri
|
r1.Extra = append(r1.Extra, r.copy())
|
||||||
for i := 0; i < len(dns.Extra); i++ {
|
|
||||||
rrArr[rri] = dns.Extra[i].copy()
|
|
||||||
rri++
|
|
||||||
}
|
|
||||||
r1.Extra = rrArr[rrbegin:rri:rri]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r1
|
return r1
|
||||||
|
349
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
349
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,12 +26,13 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func packDataA(a net.IP, msg []byte, off int) (int, error) {
|
func packDataA(a net.IP, msg []byte, off int) (int, error) {
|
||||||
// It must be a slice of 4, even if it is 16, we encode only the first 4
|
|
||||||
if off+net.IPv4len > len(msg) {
|
|
||||||
return len(msg), &Error{err: "overflow packing a"}
|
|
||||||
}
|
|
||||||
switch len(a) {
|
switch len(a) {
|
||||||
case net.IPv4len, net.IPv6len:
|
case net.IPv4len, net.IPv6len:
|
||||||
|
// It must be a slice of 4, even if it is 16, we encode only the first 4
|
||||||
|
if off+net.IPv4len > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflow packing a"}
|
||||||
|
}
|
||||||
|
|
||||||
copy(msg[off:], a.To4())
|
copy(msg[off:], a.To4())
|
||||||
off += net.IPv4len
|
off += net.IPv4len
|
||||||
case 0:
|
case 0:
|
||||||
@ -51,12 +53,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
|
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
|
||||||
if off+net.IPv6len > len(msg) {
|
|
||||||
return len(msg), &Error{err: "overflow packing aaaa"}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(aaaa) {
|
switch len(aaaa) {
|
||||||
case net.IPv6len:
|
case net.IPv6len:
|
||||||
|
if off+net.IPv6len > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflow packing aaaa"}
|
||||||
|
}
|
||||||
|
|
||||||
copy(msg[off:], aaaa)
|
copy(msg[off:], aaaa)
|
||||||
off += net.IPv6len
|
off += net.IPv6len
|
||||||
case 0:
|
case 0:
|
||||||
@ -264,24 +266,36 @@ func unpackString(msg []byte, off int) (string, int, error) {
|
|||||||
return "", off, &Error{err: "overflow unpacking txt"}
|
return "", off, &Error{err: "overflow unpacking txt"}
|
||||||
}
|
}
|
||||||
l := int(msg[off])
|
l := int(msg[off])
|
||||||
if off+l+1 > len(msg) {
|
off++
|
||||||
|
if off+l > len(msg) {
|
||||||
return "", off, &Error{err: "overflow unpacking txt"}
|
return "", off, &Error{err: "overflow unpacking txt"}
|
||||||
}
|
}
|
||||||
var s strings.Builder
|
var s strings.Builder
|
||||||
s.Grow(l)
|
consumed := 0
|
||||||
for _, b := range msg[off+1 : off+1+l] {
|
for i, b := range msg[off : off+l] {
|
||||||
switch {
|
switch {
|
||||||
case b == '"' || b == '\\':
|
case b == '"' || b == '\\':
|
||||||
|
if consumed == 0 {
|
||||||
|
s.Grow(l * 2)
|
||||||
|
}
|
||||||
|
s.Write(msg[off+consumed : off+i])
|
||||||
s.WriteByte('\\')
|
s.WriteByte('\\')
|
||||||
s.WriteByte(b)
|
s.WriteByte(b)
|
||||||
|
consumed = i + 1
|
||||||
case b < ' ' || b > '~': // unprintable
|
case b < ' ' || b > '~': // unprintable
|
||||||
|
if consumed == 0 {
|
||||||
|
s.Grow(l * 2)
|
||||||
|
}
|
||||||
|
s.Write(msg[off+consumed : off+i])
|
||||||
s.WriteString(escapeByte(b))
|
s.WriteString(escapeByte(b))
|
||||||
default:
|
consumed = i + 1
|
||||||
s.WriteByte(b)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
off += 1 + l
|
if consumed == 0 { // no escaping needed
|
||||||
return s.String(), off, nil
|
return string(msg[off : off+l]), off + l, nil
|
||||||
|
}
|
||||||
|
s.Write(msg[off+consumed : off+l])
|
||||||
|
return s.String(), off + l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func packString(s string, msg []byte, off int) (int, error) {
|
func packString(s string, msg []byte, off int) (int, error) {
|
||||||
@ -410,79 +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 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
|
||||||
@ -494,16 +441,14 @@ Option:
|
|||||||
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
|
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
|
||||||
for _, el := range options {
|
for _, el := range options {
|
||||||
b, err := el.pack()
|
b, err := el.pack()
|
||||||
if err != nil || off+3 > len(msg) {
|
if err != nil || off+4 > len(msg) {
|
||||||
return len(msg), &Error{err: "overflow packing opt"}
|
return len(msg), &Error{err: "overflow packing opt"}
|
||||||
}
|
}
|
||||||
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
|
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
|
||||||
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)
|
||||||
@ -553,8 +498,7 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Walk the bytes in the window and extract the type bits
|
// Walk the bytes in the window and extract the type bits
|
||||||
for j := 0; j < length; j++ {
|
for j, b := range msg[off : off+length] {
|
||||||
b := msg[off+j]
|
|
||||||
// Check the bits one by one, and set the type
|
// Check the bits one by one, and set the type
|
||||||
if b&0x80 == 0x80 {
|
if b&0x80 == 0x80 {
|
||||||
nsec = append(nsec, uint16(window*256+j*8+0))
|
nsec = append(nsec, uint16(window*256+j*8+0))
|
||||||
@ -587,13 +531,35 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
|
|||||||
return nsec, off, nil
|
return nsec, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// typeBitMapLen is a helper function which computes the "maximum" length of
|
||||||
|
// a the NSEC Type BitMap field.
|
||||||
|
func typeBitMapLen(bitmap []uint16) int {
|
||||||
|
var l int
|
||||||
|
var lastwindow, lastlength uint16
|
||||||
|
for _, t := range bitmap {
|
||||||
|
window := t / 256
|
||||||
|
length := (t-window*256)/8 + 1
|
||||||
|
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
|
||||||
|
l += int(lastlength) + 2
|
||||||
|
lastlength = 0
|
||||||
|
}
|
||||||
|
if window < lastwindow || length < lastlength {
|
||||||
|
// packDataNsec would return Error{err: "nsec bits out of order"} here, but
|
||||||
|
// when computing the length, we want do be liberal.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastwindow, lastlength = window, length
|
||||||
|
}
|
||||||
|
l += int(lastlength) + 2
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
|
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
|
||||||
if len(bitmap) == 0 {
|
if len(bitmap) == 0 {
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
var lastwindow, lastlength uint16
|
var lastwindow, lastlength uint16
|
||||||
for j := 0; j < len(bitmap); j++ {
|
for _, t := range bitmap {
|
||||||
t := bitmap[j]
|
|
||||||
window := t / 256
|
window := t / 256
|
||||||
length := (t-window*256)/8 + 1
|
length := (t-window*256)/8 + 1
|
||||||
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
|
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
|
||||||
@ -618,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
|
||||||
@ -639,11 +664,141 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
|
|||||||
|
|
||||||
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
var err error
|
var err error
|
||||||
for j := 0; j < len(names); j++ {
|
for _, name := range names {
|
||||||
off, err = packDomainName(names[j], msg, off, compression, compress)
|
off, err = packDomainName(name, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
|
||||||
|
var err error
|
||||||
|
for i := range data {
|
||||||
|
off, err = packDataAplPrefix(&data[i], msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
|
||||||
|
if len(p.Network.IP) != len(p.Network.Mask) {
|
||||||
|
return len(msg), &Error{err: "address and mask lengths don't match"}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
prefix, _ := p.Network.Mask.Size()
|
||||||
|
addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
|
||||||
|
|
||||||
|
switch len(p.Network.IP) {
|
||||||
|
case net.IPv4len:
|
||||||
|
off, err = packUint16(1, msg, off)
|
||||||
|
case net.IPv6len:
|
||||||
|
off, err = packUint16(2, msg, off)
|
||||||
|
default:
|
||||||
|
err = &Error{err: "unrecognized address family"}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
|
||||||
|
off, err = packUint8(uint8(prefix), msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
|
||||||
|
var n uint8
|
||||||
|
if p.Negation {
|
||||||
|
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
|
||||||
|
off, err = packUint8(n|adflen, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
|
||||||
|
if off+len(addr) > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflow packing APL prefix"}
|
||||||
|
}
|
||||||
|
off += copy(msg[off:], addr)
|
||||||
|
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
|
||||||
|
var result []APLPrefix
|
||||||
|
for off < len(msg) {
|
||||||
|
prefix, end, err := unpackDataAplPrefix(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return nil, len(msg), err
|
||||||
|
}
|
||||||
|
off = end
|
||||||
|
result = append(result, prefix)
|
||||||
|
}
|
||||||
|
return result, off, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
|
||||||
|
family, off, err := unpackUint16(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
|
||||||
|
}
|
||||||
|
prefix, off, err := unpackUint8(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
|
||||||
|
}
|
||||||
|
nlen, off, err := unpackUint8(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ip []byte
|
||||||
|
switch family {
|
||||||
|
case 1:
|
||||||
|
ip = make([]byte, net.IPv4len)
|
||||||
|
case 2:
|
||||||
|
ip = make([]byte, net.IPv6len)
|
||||||
|
default:
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
|
||||||
|
}
|
||||||
|
if int(prefix) > 8*len(ip) {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
|
||||||
|
}
|
||||||
|
afdlen := int(nlen & 0x7f)
|
||||||
|
if afdlen > len(ip) {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
|
||||||
|
}
|
||||||
|
if off+afdlen > len(msg) {
|
||||||
|
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
|
||||||
|
}
|
||||||
|
off += copy(ip, msg[off:off+afdlen])
|
||||||
|
if afdlen > 0 {
|
||||||
|
last := ip[afdlen-1]
|
||||||
|
if last == 0 {
|
||||||
|
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{
|
||||||
|
Negation: (nlen & 0x80) != 0,
|
||||||
|
Network: ipnet,
|
||||||
|
}, off, nil
|
||||||
|
}
|
||||||
|
117
vendor/github.com/miekg/dns/msg_truncate.go
generated
vendored
Normal file
117
vendor/github.com/miekg/dns/msg_truncate.go
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
// Truncate ensures the reply message will fit into the requested buffer
|
||||||
|
// size by removing records that exceed the requested size.
|
||||||
|
//
|
||||||
|
// It will first check if the reply fits without compression and then with
|
||||||
|
// compression. If it won't fit with compression, Truncate then walks the
|
||||||
|
// record adding as many records as possible without exceeding the
|
||||||
|
// requested buffer size.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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
|
||||||
|
// "required" RRs can be included in the response. Unfortunately, we have
|
||||||
|
// no way of knowing which RRs are required so we set the TC bit if any RR
|
||||||
|
// had to be omitted from the response.
|
||||||
|
//
|
||||||
|
// The appropriate buffer size can be retrieved from the requests OPT
|
||||||
|
// record, if present, and is transport specific otherwise. dns.MinMsgSize
|
||||||
|
// should be used for UDP requests without an OPT record, and
|
||||||
|
// dns.MaxMsgSize for TCP requests without an OPT record.
|
||||||
|
func (dns *Msg) Truncate(size int) {
|
||||||
|
if dns.IsTsig() != nil {
|
||||||
|
// To simplify this implementation, we don't perform
|
||||||
|
// truncation on responses with a TSIG record.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 6891 mandates that the payload size in an OPT record
|
||||||
|
// less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes.
|
||||||
|
//
|
||||||
|
// For ease of use, we impose that restriction here.
|
||||||
|
if size < MinMsgSize {
|
||||||
|
size = MinMsgSize
|
||||||
|
}
|
||||||
|
|
||||||
|
l := msgLenWithCompressionMap(dns, nil) // uncompressed length
|
||||||
|
if l <= size {
|
||||||
|
// Don't waste effort compressing this message.
|
||||||
|
dns.Compress = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dns.Compress = true
|
||||||
|
|
||||||
|
edns0 := dns.popEdns0()
|
||||||
|
if edns0 != nil {
|
||||||
|
// Account for the OPT record that gets added at the end,
|
||||||
|
// by subtracting that length from our budget.
|
||||||
|
//
|
||||||
|
// The EDNS(0) OPT record must have the root domain and
|
||||||
|
// it's length is thus unaffected by compression.
|
||||||
|
size -= Len(edns0)
|
||||||
|
}
|
||||||
|
|
||||||
|
compression := make(map[string]struct{})
|
||||||
|
|
||||||
|
l = headerSize
|
||||||
|
for _, r := range dns.Question {
|
||||||
|
l += r.len(l, compression)
|
||||||
|
}
|
||||||
|
|
||||||
|
var numAnswer int
|
||||||
|
if l < size {
|
||||||
|
l, numAnswer = truncateLoop(dns.Answer, size, l, compression)
|
||||||
|
}
|
||||||
|
|
||||||
|
var numNS int
|
||||||
|
if l < size {
|
||||||
|
l, numNS = truncateLoop(dns.Ns, size, l, compression)
|
||||||
|
}
|
||||||
|
|
||||||
|
var numExtra int
|
||||||
|
if l < size {
|
||||||
|
_, numExtra = truncateLoop(dns.Extra, size, l, compression)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the function documentation for when we set this.
|
||||||
|
dns.Truncated = dns.Truncated || len(dns.Answer) > numAnswer ||
|
||||||
|
len(dns.Ns) > numNS || len(dns.Extra) > numExtra
|
||||||
|
|
||||||
|
dns.Answer = dns.Answer[:numAnswer]
|
||||||
|
dns.Ns = dns.Ns[:numNS]
|
||||||
|
dns.Extra = dns.Extra[:numExtra]
|
||||||
|
|
||||||
|
if edns0 != nil {
|
||||||
|
// Add the OPT record back onto the additional section.
|
||||||
|
dns.Extra = append(dns.Extra, edns0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) {
|
||||||
|
for i, r := range rrs {
|
||||||
|
if r == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
l += r.len(l, compression)
|
||||||
|
if l > size {
|
||||||
|
// Return size, rather than l prior to this record,
|
||||||
|
// to prevent any further records being added.
|
||||||
|
return size, i
|
||||||
|
}
|
||||||
|
if l == size {
|
||||||
|
return l, i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l, len(rrs)
|
||||||
|
}
|
2
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
2
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
@ -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)
|
||||||
|
43
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
43
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
@ -1,24 +1,20 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import "strings"
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PrivateRdata is an interface used for implementing "Private Use" RR types, see
|
// PrivateRdata is an interface used for implementing "Private Use" RR types, see
|
||||||
// RFC 6895. This allows one to experiment with new RR types, without requesting an
|
// RFC 6895. This allows one to experiment with new RR types, without requesting an
|
||||||
// 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.
|
// Copy copies the Rdata into the PrivateRdata argument.
|
||||||
Copy(PrivateRdata) error
|
Copy(PrivateRdata) error
|
||||||
// Len returns the length in octets of the Rdata.
|
// Len returns the length in octets of the Rdata.
|
||||||
Len() int
|
Len() int
|
||||||
@ -29,22 +25,8 @@ type PrivateRdata interface {
|
|||||||
type PrivateRR struct {
|
type PrivateRR struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Data PrivateRdata
|
Data PrivateRdata
|
||||||
}
|
|
||||||
|
|
||||||
func mkPrivateRR(rrtype uint16) *PrivateRR {
|
generator func() PrivateRdata // for copy
|
||||||
// Panics if RR is not an instance of PrivateRR.
|
|
||||||
rrfunc, ok := TypeToRR[rrtype]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
|
|
||||||
}
|
|
||||||
|
|
||||||
anyrr := rrfunc()
|
|
||||||
rr, ok := anyrr.(*PrivateRR)
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
|
||||||
}
|
|
||||||
|
|
||||||
return rr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header return the RR header of r.
|
// Header return the RR header of r.
|
||||||
@ -61,13 +43,12 @@ func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
|
|||||||
|
|
||||||
func (r *PrivateRR) copy() RR {
|
func (r *PrivateRR) copy() RR {
|
||||||
// make new RR like this:
|
// make new RR like this:
|
||||||
rr := mkPrivateRR(r.Hdr.Rrtype)
|
rr := &PrivateRR{r.Hdr, r.generator(), r.generator}
|
||||||
rr.Hdr = r.Hdr
|
|
||||||
|
|
||||||
err := r.Data.Copy(rr.Data)
|
if err := r.Data.Copy(rr.Data); err != nil {
|
||||||
if err != nil {
|
panic("dns: got value that could not be used to copy Private rdata: " + err.Error())
|
||||||
panic("dns: got value that could not be used to copy Private rdata")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rr
|
return rr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +67,7 @@ func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
|
|||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError {
|
func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError {
|
||||||
var l lex
|
var l lex
|
||||||
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
|
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
|
||||||
Fetch:
|
Fetch:
|
||||||
@ -103,20 +84,20 @@ Fetch:
|
|||||||
|
|
||||||
err := r.Data.Parse(text)
|
err := r.Data.Parse(text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ParseError{file, err.Error(), l}
|
return &ParseError{"", err.Error(), l}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
||||||
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
||||||
rtypestr = strings.ToUpper(rtypestr)
|
rtypestr = strings.ToUpper(rtypestr)
|
||||||
|
|
||||||
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
|
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
|
||||||
TypeToString[rtype] = rtypestr
|
TypeToString[rtype] = rtypestr
|
||||||
StringToType[rtypestr] = rtype
|
StringToType[rtypestr] = rtype
|
||||||
}
|
}
|
||||||
|
251
vendor/github.com/miekg/dns/scan.go
generated
vendored
251
vendor/github.com/miekg/dns/scan.go
generated
vendored
@ -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,69 +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.
|
|
||||||
//
|
|
||||||
// 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
|
||||||
@ -203,6 +127,7 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) {
|
|||||||
//
|
//
|
||||||
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
|
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
|
||||||
// supported. Although $INCLUDE is disabled by default.
|
// supported. Although $INCLUDE is disabled by default.
|
||||||
|
// Note that $GENERATE's range support up to a maximum of 65535 steps.
|
||||||
//
|
//
|
||||||
// Basic usage pattern when reading from a string (z) containing the
|
// Basic usage pattern when reading from a string (z) containing the
|
||||||
// zone data:
|
// zone data:
|
||||||
@ -225,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
|
||||||
|
|
||||||
@ -245,7 +173,8 @@ type ZoneParser struct {
|
|||||||
|
|
||||||
includeDepth uint8
|
includeDepth uint8
|
||||||
|
|
||||||
includeAllowed bool
|
includeAllowed bool
|
||||||
|
generateDisallowed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewZoneParser returns an RFC 1035 style zonefile parser that reads
|
// NewZoneParser returns an RFC 1035 style zonefile parser that reads
|
||||||
@ -503,9 +432,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
|
|||||||
return zp.setParseError("expecting $TTL value, not this...", l)
|
return zp.setParseError("expecting $TTL value, not this...", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e := slurpRemainder(zp.c, zp.file); e != nil {
|
if err := slurpRemainder(zp.c); err != nil {
|
||||||
zp.parseErr = e
|
return zp.setParseError(err.err, err.lex)
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ttl, ok := stringToTTL(l.token)
|
ttl, ok := stringToTTL(l.token)
|
||||||
@ -527,9 +455,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
|
|||||||
return zp.setParseError("expecting $ORIGIN value, not this...", l)
|
return zp.setParseError("expecting $ORIGIN value, not this...", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e := slurpRemainder(zp.c, zp.file); e != nil {
|
if err := slurpRemainder(zp.c); err != nil {
|
||||||
zp.parseErr = e
|
return zp.setParseError(err.err, err.lex)
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name, ok := toAbsoluteName(l.token, zp.origin)
|
name, ok := toAbsoluteName(l.token, zp.origin)
|
||||||
@ -547,6 +474,9 @@ func (zp *ZoneParser) Next() (RR, bool) {
|
|||||||
|
|
||||||
st = zExpectDirGenerate
|
st = zExpectDirGenerate
|
||||||
case zExpectDirGenerate:
|
case zExpectDirGenerate:
|
||||||
|
if zp.generateDisallowed {
|
||||||
|
return zp.setParseError("nested $GENERATE directive not allowed", l)
|
||||||
|
}
|
||||||
if l.value != zString {
|
if l.value != zString {
|
||||||
return zp.setParseError("expecting $GENERATE value, not this...", l)
|
return zp.setParseError("expecting $GENERATE value, not this...", l)
|
||||||
}
|
}
|
||||||
@ -650,19 +580,69 @@ func (zp *ZoneParser) Next() (RR, bool) {
|
|||||||
|
|
||||||
st = zExpectRdata
|
st = zExpectRdata
|
||||||
case zExpectRdata:
|
case zExpectRdata:
|
||||||
r, e := setRR(*h, zp.c, zp.origin, zp.file)
|
var (
|
||||||
if e != nil {
|
rr RR
|
||||||
// If e.lex is nil than we have encounter a unknown RR type
|
parseAsRFC3597 bool
|
||||||
// in that case we substitute our current lex token
|
)
|
||||||
if e.lex.token == "" && e.lex.value == 0 {
|
if newFn, ok := TypeToRR[h.Rrtype]; ok {
|
||||||
e.lex = l // Uh, dirty
|
rr = newFn()
|
||||||
}
|
*rr.Header() = *h
|
||||||
|
|
||||||
zp.parseErr = e
|
// We may be parsing a known RR type using the RFC3597 format.
|
||||||
return nil, false
|
// 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 {
|
||||||
|
rr = &RFC3597{Hdr: *h}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, true
|
_, isPrivate := rr.(*PrivateRR)
|
||||||
|
if !isPrivate && zp.c.Peek().token == "" {
|
||||||
|
// This is a dynamic update rr.
|
||||||
|
|
||||||
|
// TODO(tmthrgd): Previously slurpRemainder was only called
|
||||||
|
// for certain RR types, which may have been important.
|
||||||
|
if err := slurpRemainder(zp.c); err != nil {
|
||||||
|
return zp.setParseError(err.err, err.lex)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rr, true
|
||||||
|
} else if l.value == zNewline {
|
||||||
|
return zp.setParseError("unexpected newline", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
// The setParseError call below will construct a new
|
||||||
|
// *ParseError with file set to zp.file.
|
||||||
|
|
||||||
|
// err.lex may be nil in which case we substitute our current
|
||||||
|
// lex token.
|
||||||
|
if err.lex == (lex{}) {
|
||||||
|
return zp.setParseError(err.err, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +662,8 @@ type zlexer struct {
|
|||||||
comBuf string
|
comBuf string
|
||||||
comment string
|
comment string
|
||||||
|
|
||||||
l lex
|
l lex
|
||||||
|
cachedL *lex
|
||||||
|
|
||||||
brace int
|
brace int
|
||||||
quote bool
|
quote bool
|
||||||
@ -748,13 +729,37 @@ func (zl *zlexer) readByte() (byte, bool) {
|
|||||||
return c, true
|
return c, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (zl *zlexer) Peek() lex {
|
||||||
|
if zl.nextL {
|
||||||
|
return zl.l
|
||||||
|
}
|
||||||
|
|
||||||
|
l, ok := zl.Next()
|
||||||
|
if !ok {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
if zl.nextL {
|
||||||
|
// Cache l. Next returns zl.cachedL then zl.l.
|
||||||
|
zl.cachedL = &l
|
||||||
|
} else {
|
||||||
|
// In this case l == zl.l, so we just tell Next to return zl.l.
|
||||||
|
zl.nextL = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func (zl *zlexer) Next() (lex, bool) {
|
func (zl *zlexer) Next() (lex, bool) {
|
||||||
l := &zl.l
|
l := &zl.l
|
||||||
if zl.nextL {
|
switch {
|
||||||
|
case zl.cachedL != nil:
|
||||||
|
l, zl.cachedL = zl.cachedL, nil
|
||||||
|
return *l, true
|
||||||
|
case zl.nextL:
|
||||||
zl.nextL = false
|
zl.nextL = false
|
||||||
return *l, true
|
return *l, true
|
||||||
}
|
case l.err:
|
||||||
if l.err {
|
|
||||||
// Parsing errors should be sticky.
|
// Parsing errors should be sticky.
|
||||||
return lex{value: zEOF}, false
|
return lex{value: zEOF}, false
|
||||||
}
|
}
|
||||||
@ -908,6 +913,11 @@ func (zl *zlexer) Next() (lex, bool) {
|
|||||||
// was inside braces and we delayed adding it until now.
|
// was inside braces and we delayed adding it until now.
|
||||||
com[comi] = ' ' // convert newline to space
|
com[comi] = ' ' // convert newline to space
|
||||||
comi++
|
comi++
|
||||||
|
if comi >= len(com) {
|
||||||
|
l.token = "comment length insufficient for parsing"
|
||||||
|
l.err = true
|
||||||
|
return *l, true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
com[comi] = ';'
|
com[comi] = ';'
|
||||||
@ -1216,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
|
||||||
@ -1233,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
|
||||||
}
|
}
|
||||||
@ -1281,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
|
||||||
@ -1292,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
|
||||||
@ -1302,18 +1333,18 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Eat" the rest of the "line"
|
// "Eat" the rest of the "line"
|
||||||
func slurpRemainder(c *zlexer, f string) *ParseError {
|
func slurpRemainder(c *zlexer) *ParseError {
|
||||||
l, _ := c.Next()
|
l, _ := c.Next()
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zBlank:
|
case zBlank:
|
||||||
l, _ = c.Next()
|
l, _ = c.Next()
|
||||||
if l.value != zNewline && l.value != zEOF {
|
if l.value != zNewline && l.value != zEOF {
|
||||||
return &ParseError{f, "garbage after rdata", l}
|
return &ParseError{"", "garbage after rdata", l}
|
||||||
}
|
}
|
||||||
case zNewline:
|
case zNewline:
|
||||||
case zEOF:
|
case zEOF:
|
||||||
default:
|
default:
|
||||||
return &ParseError{f, "garbage after rdata", l}
|
return &ParseError{"", "garbage after rdata", l}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1324,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}
|
||||||
}
|
}
|
||||||
|
1193
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
1193
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
File diff suppressed because it is too large
Load Diff
37
vendor/github.com/miekg/dns/serve_mux.go
generated
vendored
37
vendor/github.com/miekg/dns/serve_mux.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,33 +35,9 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q = CanonicalName(q)
|
||||||
|
|
||||||
var handler Handler
|
var handler Handler
|
||||||
|
|
||||||
// TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575
|
|
||||||
// lands in a go release, replace the following with strings.ToLower.
|
|
||||||
var sb strings.Builder
|
|
||||||
for i := 0; i < len(q); i++ {
|
|
||||||
c := q[i]
|
|
||||||
if !(c >= 'A' && c <= 'Z') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Grow(len(q))
|
|
||||||
sb.WriteString(q[:i])
|
|
||||||
|
|
||||||
for ; i < len(q); i++ {
|
|
||||||
c := q[i]
|
|
||||||
if c >= 'A' && c <= 'Z' {
|
|
||||||
c += 'a' - 'A'
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.WriteByte(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
q = sb.String()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
|
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
|
||||||
if h, ok := mux.z[q[off:]]; ok {
|
if h, ok := mux.z[q[off:]]; ok {
|
||||||
if t != TypeDS {
|
if t != TypeDS {
|
||||||
@ -90,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()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,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()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,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
|
||||||
@ -127,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
352
vendor/github.com/miekg/dns/server.go
generated
vendored
352
vendor/github.com/miekg/dns/server.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@ -12,26 +11,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Default maximum number of TCP queries before we close the socket.
|
// Default maximum number of TCP queries before we close the socket.
|
||||||
const maxTCPQueries = 128
|
const maxTCPQueries = 128
|
||||||
|
|
||||||
// The maximum number of idle workers.
|
|
||||||
//
|
|
||||||
// This controls the maximum number of workers that are allowed to stay
|
|
||||||
// idle waiting for incoming requests before being torn down.
|
|
||||||
//
|
|
||||||
// If this limit is reached, the server will just keep spawning new
|
|
||||||
// workers (goroutines) for each incoming request. In this case, each
|
|
||||||
// worker will only be used for a single request.
|
|
||||||
const maxIdleWorkersCount = 10000
|
|
||||||
|
|
||||||
// The maximum length of time a worker may idle for before being destroyed.
|
|
||||||
const idleWorkerTimeout = 10 * time.Second
|
|
||||||
|
|
||||||
// aLongTimeAgo is a non-zero time, far in the past, used for
|
// aLongTimeAgo is a non-zero time, far in the past, used for
|
||||||
// immediate cancelation of network operations.
|
// immediate cancelation of network operations.
|
||||||
var aLongTimeAgo = time.Unix(1, 0)
|
var aLongTimeAgo = time.Unix(1, 0)
|
||||||
@ -81,21 +66,28 @@ type ConnectionStater interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type response struct {
|
type response struct {
|
||||||
msg []byte
|
|
||||||
closed bool // connection has been closed
|
closed bool // connection has been closed
|
||||||
hijacked bool // connection has been hijacked by handler
|
hijacked bool // connection has been hijacked by handler
|
||||||
tsigTimersOnly bool
|
tsigTimersOnly bool
|
||||||
tsigStatus error
|
tsigStatus error
|
||||||
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
|
||||||
wg *sync.WaitGroup // for gracefull shutdown
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
@ -156,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)
|
||||||
}
|
}
|
||||||
@ -170,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.
|
||||||
@ -218,11 +228,6 @@ type Server struct {
|
|||||||
// By default DefaultMsgAcceptFunc will be used.
|
// By default DefaultMsgAcceptFunc will be used.
|
||||||
MsgAcceptFunc MsgAcceptFunc
|
MsgAcceptFunc MsgAcceptFunc
|
||||||
|
|
||||||
// UDP packet or TCP connection queue
|
|
||||||
queue chan *response
|
|
||||||
// Workers count
|
|
||||||
workersCount int32
|
|
||||||
|
|
||||||
// Shutdown handling
|
// Shutdown handling
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
started bool
|
started bool
|
||||||
@ -240,51 +245,6 @@ func (srv *Server) isStarted() bool {
|
|||||||
return started
|
return started
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) worker(w *response) {
|
|
||||||
srv.serve(w)
|
|
||||||
|
|
||||||
for {
|
|
||||||
count := atomic.LoadInt32(&srv.workersCount)
|
|
||||||
if count > maxIdleWorkersCount {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer atomic.AddInt32(&srv.workersCount, -1)
|
|
||||||
|
|
||||||
inUse := false
|
|
||||||
timeout := time.NewTimer(idleWorkerTimeout)
|
|
||||||
defer timeout.Stop()
|
|
||||||
LOOP:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case w, ok := <-srv.queue:
|
|
||||||
if !ok {
|
|
||||||
break LOOP
|
|
||||||
}
|
|
||||||
inUse = true
|
|
||||||
srv.serve(w)
|
|
||||||
case <-timeout.C:
|
|
||||||
if !inUse {
|
|
||||||
break LOOP
|
|
||||||
}
|
|
||||||
inUse = false
|
|
||||||
timeout.Reset(idleWorkerTimeout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (srv *Server) spawnWorker(w *response) {
|
|
||||||
select {
|
|
||||||
case srv.queue <- w:
|
|
||||||
default:
|
|
||||||
go srv.worker(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeUDPBuffer(size int) func() interface{} {
|
func makeUDPBuffer(size int) func() interface{} {
|
||||||
return func() interface{} {
|
return func() interface{} {
|
||||||
return make([]byte, size)
|
return make([]byte, size)
|
||||||
@ -292,8 +252,6 @@ func makeUDPBuffer(size int) func() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) init() {
|
func (srv *Server) init() {
|
||||||
srv.queue = make(chan *response)
|
|
||||||
|
|
||||||
srv.shutdown = make(chan struct{})
|
srv.shutdown = make(chan struct{})
|
||||||
srv.conns = make(map[net.Conn]struct{})
|
srv.conns = make(map[net.Conn]struct{})
|
||||||
|
|
||||||
@ -301,7 +259,10 @@ func (srv *Server) init() {
|
|||||||
srv.UDPSize = MinMsgSize
|
srv.UDPSize = MinMsgSize
|
||||||
}
|
}
|
||||||
if srv.MsgAcceptFunc == nil {
|
if srv.MsgAcceptFunc == nil {
|
||||||
srv.MsgAcceptFunc = defaultMsgAcceptFunc
|
srv.MsgAcceptFunc = DefaultMsgAcceptFunc
|
||||||
|
}
|
||||||
|
if srv.Handler == nil {
|
||||||
|
srv.Handler = DefaultServeMux
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
|
srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
|
||||||
@ -328,7 +289,6 @@ func (srv *Server) ListenAndServe() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
srv.init()
|
srv.init()
|
||||||
defer close(srv.queue)
|
|
||||||
|
|
||||||
switch srv.Net {
|
switch srv.Net {
|
||||||
case "tcp", "tcp4", "tcp6":
|
case "tcp", "tcp4", "tcp6":
|
||||||
@ -361,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
|
||||||
@ -383,26 +344,23 @@ func (srv *Server) ActivateAndServe() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
srv.init()
|
srv.init()
|
||||||
defer close(srv.queue)
|
|
||||||
|
|
||||||
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"}
|
||||||
}
|
}
|
||||||
@ -499,29 +457,31 @@ func (srv *Server) serveTCP(l net.Listener) error {
|
|||||||
srv.conns[rw] = struct{}{}
|
srv.conns[rw] = struct{}{}
|
||||||
srv.lock.Unlock()
|
srv.lock.Unlock()
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
srv.spawnWorker(&response{
|
go srv.serveTCPConn(&wg, rw)
|
||||||
tsigSecret: srv.TsigSecret,
|
|
||||||
tcp: rw,
|
|
||||||
wg: &wg,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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()
|
||||||
@ -531,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
|
||||||
@ -548,45 +518,21 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
srv.spawnWorker(&response{
|
go srv.serveUDPPacket(&wg, m, l, sUDP, sPC)
|
||||||
msg: m,
|
|
||||||
tsigSecret: srv.TsigSecret,
|
|
||||||
udp: l,
|
|
||||||
udpSession: s,
|
|
||||||
wg: &wg,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) serve(w *response) {
|
// Serve a new TCP connection.
|
||||||
|
func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
|
||||||
|
w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
|
||||||
if srv.DecorateWriter != nil {
|
if srv.DecorateWriter != nil {
|
||||||
w.writer = srv.DecorateWriter(w)
|
w.writer = srv.DecorateWriter(w)
|
||||||
} else {
|
} else {
|
||||||
w.writer = w
|
w.writer = w
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.udp != nil {
|
|
||||||
// serve UDP
|
|
||||||
srv.serveDNS(w)
|
|
||||||
|
|
||||||
w.wg.Done()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if !w.hijacked {
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
srv.lock.Lock()
|
|
||||||
delete(srv.conns, w.tcp)
|
|
||||||
srv.lock.Unlock()
|
|
||||||
|
|
||||||
w.wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
reader := Reader(defaultReader{srv})
|
reader := Reader(defaultReader{srv})
|
||||||
if srv.DecorateReader != nil {
|
if srv.DecorateReader != nil {
|
||||||
reader = srv.DecorateReader(reader)
|
reader = srv.DecorateReader(reader)
|
||||||
@ -605,14 +551,13 @@ func (srv *Server) serve(w *response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
|
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
|
||||||
var err error
|
m, err := reader.ReadTCP(w.tcp, timeout)
|
||||||
w.msg, err = reader.ReadTCP(w.tcp, timeout)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(tmthrgd): handle error
|
// TODO(tmthrgd): handle error
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
srv.serveDNS(w)
|
srv.serveDNS(m, w)
|
||||||
if w.tcp == nil {
|
if w.closed {
|
||||||
break // Close() was called
|
break // Close() was called
|
||||||
}
|
}
|
||||||
if w.hijacked {
|
if w.hijacked {
|
||||||
@ -622,17 +567,33 @@ func (srv *Server) serve(w *response) {
|
|||||||
// idle timeout.
|
// idle timeout.
|
||||||
timeout = idleTimeout
|
timeout = idleTimeout
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (srv *Server) disposeBuffer(w *response) {
|
if !w.hijacked {
|
||||||
if w.udp != nil && cap(w.msg) == srv.UDPSize {
|
w.Close()
|
||||||
srv.udpPool.Put(w.msg[:srv.UDPSize])
|
|
||||||
}
|
}
|
||||||
w.msg = nil
|
|
||||||
|
srv.lock.Lock()
|
||||||
|
delete(srv.conns, w.tcp)
|
||||||
|
srv.lock.Unlock()
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) serveDNS(w *response) {
|
// Serve a new UDP request.
|
||||||
dh, off, err := unpackMsgHdr(w.msg, 0)
|
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: udpSession, pcSession: pcSession}
|
||||||
|
if srv.DecorateWriter != nil {
|
||||||
|
w.writer = srv.DecorateWriter(w)
|
||||||
|
} else {
|
||||||
|
w.writer = w
|
||||||
|
}
|
||||||
|
|
||||||
|
srv.serveDNS(m, w)
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) serveDNS(m []byte, w *response) {
|
||||||
|
dh, off, err := unpackMsgHdr(m, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Let client hang, they are sending crap; any reply can be used to amplify.
|
// Let client hang, they are sending crap; any reply can be used to amplify.
|
||||||
return
|
return
|
||||||
@ -641,26 +602,32 @@ func (srv *Server) serveDNS(w *response) {
|
|||||||
req := new(Msg)
|
req := new(Msg)
|
||||||
req.setHdr(dh)
|
req.setHdr(dh)
|
||||||
|
|
||||||
switch srv.MsgAcceptFunc(dh) {
|
switch action := srv.MsgAcceptFunc(dh); action {
|
||||||
case MsgAccept:
|
case MsgAccept:
|
||||||
case MsgIgnore:
|
if req.unpack(dh, m, off) == nil {
|
||||||
return
|
break
|
||||||
case MsgReject:
|
}
|
||||||
|
|
||||||
|
fallthrough
|
||||||
|
case MsgReject, MsgRejectNotImplemented:
|
||||||
|
opcode := req.Opcode
|
||||||
req.SetRcodeFormatError(req)
|
req.SetRcodeFormatError(req)
|
||||||
|
req.Zero = false
|
||||||
|
if action == MsgRejectNotImplemented {
|
||||||
|
req.Opcode = opcode
|
||||||
|
req.Rcode = RcodeNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// Are we allowed to delete any OPT records here?
|
// Are we allowed to delete any OPT records here?
|
||||||
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
||||||
|
|
||||||
w.WriteMsg(req)
|
w.WriteMsg(req)
|
||||||
srv.disposeBuffer(w)
|
fallthrough
|
||||||
return
|
case MsgIgnore:
|
||||||
}
|
if w.udp != nil && cap(m) == srv.UDPSize {
|
||||||
|
srv.udpPool.Put(m[:srv.UDPSize])
|
||||||
|
}
|
||||||
|
|
||||||
if err := req.unpack(dh, w.msg, off); err != nil {
|
|
||||||
req.SetRcodeFormatError(req)
|
|
||||||
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
|
||||||
|
|
||||||
w.WriteMsg(req)
|
|
||||||
srv.disposeBuffer(w)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,7 +635,7 @@ func (srv *Server) serveDNS(w *response) {
|
|||||||
if w.tsigSecret != nil {
|
if w.tsigSecret != nil {
|
||||||
if t := req.IsTsig(); t != nil {
|
if t := req.IsTsig(); t != nil {
|
||||||
if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
|
if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
|
||||||
w.tsigStatus = TsigVerify(w.msg, secret, "", false)
|
w.tsigStatus = TsigVerify(m, secret, "", false)
|
||||||
} else {
|
} else {
|
||||||
w.tsigStatus = ErrSecret
|
w.tsigStatus = ErrSecret
|
||||||
}
|
}
|
||||||
@ -677,14 +644,11 @@ func (srv *Server) serveDNS(w *response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.disposeBuffer(w)
|
if w.udp != nil && cap(m) == srv.UDPSize {
|
||||||
|
srv.udpPool.Put(m[:srv.UDPSize])
|
||||||
handler := srv.Handler
|
|
||||||
if handler == nil {
|
|
||||||
handler = DefaultServeMux
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.ServeDNS(w, req) // Writes back to the client
|
srv.Handler.ServeDNS(w, req) // Writes back to the client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||||
@ -698,36 +662,16 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
|
|||||||
}
|
}
|
||||||
srv.lock.RUnlock()
|
srv.lock.RUnlock()
|
||||||
|
|
||||||
l := make([]byte, 2)
|
var length uint16
|
||||||
n, err := conn.Read(l)
|
if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
|
||||||
if err != nil || n != 2 {
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, ErrShortRead
|
|
||||||
}
|
}
|
||||||
length := binary.BigEndian.Uint16(l)
|
|
||||||
if length == 0 {
|
m := make([]byte, length)
|
||||||
return nil, ErrShortRead
|
if _, err := io.ReadFull(conn, m); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
m := make([]byte, int(length))
|
|
||||||
n, err = conn.Read(m[:int(length)])
|
|
||||||
if err != nil || n == 0 {
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, ErrShortRead
|
|
||||||
}
|
|
||||||
i := n
|
|
||||||
for i < int(length) {
|
|
||||||
j, err := conn.Read(m[i:int(length)])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
i += j
|
|
||||||
}
|
|
||||||
n = i
|
|
||||||
m = m[:n]
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,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 {
|
||||||
@ -782,21 +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 {
|
||||||
case w.tcp != nil:
|
return WriteToSessionUDP(u, m, w.udpSession)
|
||||||
lm := len(m)
|
|
||||||
if lm < 2 {
|
|
||||||
return 0, io.ErrShortBuffer
|
|
||||||
}
|
}
|
||||||
if lm > MaxMsgSize {
|
return w.udp.WriteTo(m, w.pcSession)
|
||||||
|
case w.tcp != nil:
|
||||||
|
if len(m) > MaxMsgSize {
|
||||||
return 0, &Error{err: "message too large"}
|
return 0, &Error{err: "message too large"}
|
||||||
}
|
}
|
||||||
l := make([]byte, 2, 2+lm)
|
|
||||||
binary.BigEndian.PutUint16(l, uint16(lm))
|
|
||||||
m = append(l, m...)
|
|
||||||
|
|
||||||
n, err := io.Copy(w.tcp, bytes.NewReader(m))
|
msg := make([]byte, 2+len(m))
|
||||||
return int(n), err
|
binary.BigEndian.PutUint16(msg, uint16(len(m)))
|
||||||
|
copy(msg[2:], m)
|
||||||
|
return w.tcp.Write(msg)
|
||||||
default:
|
default:
|
||||||
panic("dns: internal error: udp and tcp both nil")
|
panic("dns: internal error: udp and tcp both nil")
|
||||||
}
|
}
|
||||||
@ -819,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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
vendor/github.com/miekg/dns/sig0.go
generated
vendored
26
vendor/github.com/miekg/dns/sig0.go
generated
vendored
@ -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,19 +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 := big.NewInt(0)
|
|
||||||
r.SetBytes(sig[:len(sig)/2])
|
|
||||||
s := big.NewInt(0)
|
|
||||||
s.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 {
|
||||||
@ -198,10 +184,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||||||
}
|
}
|
||||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||||
pk := k.publicKeyECDSA()
|
pk := k.publicKeyECDSA()
|
||||||
r := big.NewInt(0)
|
r := new(big.Int).SetBytes(sig[:len(sig)/2])
|
||||||
r.SetBytes(sig[:len(sig)/2])
|
s := new(big.Int).SetBytes(sig[len(sig)/2:])
|
||||||
s := big.NewInt(0)
|
|
||||||
s.SetBytes(sig[len(sig)/2:])
|
|
||||||
if pk != nil {
|
if pk != nil {
|
||||||
if ecdsa.Verify(pk, hashed, r, s) {
|
if ecdsa.Verify(pk, hashed, r, s) {
|
||||||
return nil
|
return nil
|
||||||
|
755
vendor/github.com/miekg/dns/svcb.go
generated
vendored
Normal file
755
vendor/github.com/miekg/dns/svcb.go
generated
vendored
Normal 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
|
||||||
|
}
|
164
vendor/github.com/miekg/dns/tsig.go
generated
vendored
164
vendor/github.com/miekg/dns/tsig.go
generated
vendored
@ -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 {
|
||||||
@ -40,7 +92,7 @@ type TSIG struct {
|
|||||||
// TSIG has no official presentation format, but this will suffice.
|
// TSIG has no official presentation format, but this will suffice.
|
||||||
|
|
||||||
func (rr *TSIG) String() string {
|
func (rr *TSIG) String() string {
|
||||||
s := "\n;; TSIG PSEUDOSECTION:\n"
|
s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format
|
||||||
s += rr.Hdr.String() +
|
s += rr.Hdr.String() +
|
||||||
" " + rr.Algorithm +
|
" " + rr.Algorithm +
|
||||||
" " + tsigTimeToString(rr.TimeSigned) +
|
" " + tsigTimeToString(rr.TimeSigned) +
|
||||||
@ -54,8 +106,8 @@ func (rr *TSIG) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *TSIG) parse(c *zlexer, origin, file 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.
|
||||||
|
269
vendor/github.com/miekg/dns/types.go
generated
vendored
269
vendor/github.com/miekg/dns/types.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -61,6 +62,7 @@ const (
|
|||||||
TypeCERT uint16 = 37
|
TypeCERT uint16 = 37
|
||||||
TypeDNAME uint16 = 39
|
TypeDNAME uint16 = 39
|
||||||
TypeOPT uint16 = 41 // EDNS
|
TypeOPT uint16 = 41 // EDNS
|
||||||
|
TypeAPL uint16 = 42
|
||||||
TypeDS uint16 = 43
|
TypeDS uint16 = 43
|
||||||
TypeSSHFP uint16 = 44
|
TypeSSHFP uint16 = 44
|
||||||
TypeRRSIG uint16 = 46
|
TypeRRSIG uint16 = 46
|
||||||
@ -79,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
|
||||||
@ -146,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
|
||||||
@ -163,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.
|
||||||
@ -207,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
|
||||||
@ -229,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
|
||||||
@ -238,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, file 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.
|
||||||
@ -253,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, file 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.
|
||||||
@ -404,7 +420,7 @@ type RP struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rr *RP) String() string {
|
func (rr *RP) String() string {
|
||||||
return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
|
return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SOA RR. See RFC 1035.
|
// SOA RR. See RFC 1035.
|
||||||
@ -438,25 +454,47 @@ func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
|||||||
|
|
||||||
func sprintName(s string) string {
|
func sprintName(s string) string {
|
||||||
var dst strings.Builder
|
var dst strings.Builder
|
||||||
dst.Grow(len(s))
|
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
|
if s[i] == '.' {
|
||||||
dst.WriteString(s[i : i+2])
|
if dst.Len() != 0 {
|
||||||
i += 2
|
dst.WriteByte('.')
|
||||||
|
}
|
||||||
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
b, n := nextByte(s, i)
|
b, n := nextByte(s, i)
|
||||||
switch {
|
if n == 0 {
|
||||||
case n == 0:
|
// Drop "dangling" incomplete escapes.
|
||||||
i++ // dangling back slash
|
if dst.Len() == 0 {
|
||||||
case b == '.':
|
return s[:i]
|
||||||
dst.WriteByte('.')
|
}
|
||||||
default:
|
break
|
||||||
writeDomainNameByte(&dst, b)
|
}
|
||||||
|
if isDomainNameLabelSpecial(b) {
|
||||||
|
if dst.Len() == 0 {
|
||||||
|
dst.Grow(len(s) * 2)
|
||||||
|
dst.WriteString(s[:i])
|
||||||
|
}
|
||||||
|
dst.WriteByte('\\')
|
||||||
|
dst.WriteByte(b)
|
||||||
|
} else if b < ' ' || b > '~' { // unprintable, use \DDD
|
||||||
|
if dst.Len() == 0 {
|
||||||
|
dst.Grow(len(s) * 2)
|
||||||
|
dst.WriteString(s[:i])
|
||||||
|
}
|
||||||
|
dst.WriteString(escapeByte(b))
|
||||||
|
} else {
|
||||||
|
if dst.Len() != 0 {
|
||||||
|
dst.WriteByte(b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += n
|
i += n
|
||||||
}
|
}
|
||||||
|
if dst.Len() == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
return dst.String()
|
return dst.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,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
|
||||||
}
|
}
|
||||||
@ -510,16 +543,6 @@ func sprintTxt(txt []string) string {
|
|||||||
return out.String()
|
return out.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeDomainNameByte(s *strings.Builder, b byte) {
|
|
||||||
switch b {
|
|
||||||
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
|
|
||||||
s.WriteByte('\\')
|
|
||||||
s.WriteByte(b)
|
|
||||||
default:
|
|
||||||
writeTXTStringByte(s, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeTXTStringByte(s *strings.Builder, b byte) {
|
func writeTXTStringByte(s *strings.Builder, b byte) {
|
||||||
switch {
|
switch {
|
||||||
case b == '"' || b == '\\':
|
case b == '"' || b == '\\':
|
||||||
@ -566,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
|
||||||
@ -738,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 {
|
||||||
@ -845,8 +879,8 @@ type NSEC struct {
|
|||||||
|
|
||||||
func (rr *NSEC) String() string {
|
func (rr *NSEC) String() string {
|
||||||
s := rr.Hdr.String() + sprintName(rr.NextDomain)
|
s := rr.Hdr.String() + sprintName(rr.NextDomain)
|
||||||
for i := 0; i < len(rr.TypeBitMap); i++ {
|
for _, t := range rr.TypeBitMap {
|
||||||
s += " " + Type(rr.TypeBitMap[i]).String()
|
s += " " + Type(t).String()
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@ -854,14 +888,7 @@ func (rr *NSEC) String() string {
|
|||||||
func (rr *NSEC) len(off int, compression map[string]struct{}) int {
|
func (rr *NSEC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += domainNameLen(rr.NextDomain, off+l, compression, false)
|
l += domainNameLen(rr.NextDomain, off+l, compression, false)
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
l += typeBitMapLen(rr.TypeBitMap)
|
||||||
for _, t := range rr.TypeBitMap {
|
|
||||||
window := t / 256
|
|
||||||
if uint32(window) != lastwindow {
|
|
||||||
l += 1 + 32
|
|
||||||
}
|
|
||||||
lastwindow = uint32(window)
|
|
||||||
}
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,8 +1038,8 @@ func (rr *NSEC3) String() string {
|
|||||||
" " + strconv.Itoa(int(rr.Iterations)) +
|
" " + strconv.Itoa(int(rr.Iterations)) +
|
||||||
" " + saltToString(rr.Salt) +
|
" " + saltToString(rr.Salt) +
|
||||||
" " + rr.NextDomain
|
" " + rr.NextDomain
|
||||||
for i := 0; i < len(rr.TypeBitMap); i++ {
|
for _, t := range rr.TypeBitMap {
|
||||||
s += " " + Type(rr.TypeBitMap[i]).String()
|
s += " " + Type(t).String()
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@ -1020,14 +1047,7 @@ func (rr *NSEC3) String() string {
|
|||||||
func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
|
func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
|
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
l += typeBitMapLen(rr.TypeBitMap)
|
||||||
for _, t := range rr.TypeBitMap {
|
|
||||||
window := t / 256
|
|
||||||
if uint32(window) != lastwindow {
|
|
||||||
l += 1 + 32
|
|
||||||
}
|
|
||||||
lastwindow = uint32(window)
|
|
||||||
}
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1111,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)
|
||||||
@ -1272,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)
|
||||||
}
|
}
|
||||||
@ -1335,8 +1357,8 @@ type CSYNC struct {
|
|||||||
func (rr *CSYNC) String() string {
|
func (rr *CSYNC) String() string {
|
||||||
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
|
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
|
||||||
|
|
||||||
for i := 0; i < len(rr.TypeBitMap); i++ {
|
for _, t := range rr.TypeBitMap {
|
||||||
s += " " + Type(rr.TypeBitMap[i]).String()
|
s += " " + Type(t).String()
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@ -1344,17 +1366,109 @@ func (rr *CSYNC) String() string {
|
|||||||
func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
|
func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 4 + 2
|
l += 4 + 2
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
l += typeBitMapLen(rr.TypeBitMap)
|
||||||
for _, t := range rr.TypeBitMap {
|
|
||||||
window := t / 256
|
|
||||||
if uint32(window) != lastwindow {
|
|
||||||
l += 1 + 32
|
|
||||||
}
|
|
||||||
lastwindow = uint32(window)
|
|
||||||
}
|
|
||||||
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.
|
||||||
|
type APL struct {
|
||||||
|
Hdr RR_Header
|
||||||
|
Prefixes []APLPrefix `dns:"apl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APLPrefix is an address prefix hold by an APL record.
|
||||||
|
type APLPrefix struct {
|
||||||
|
Negation bool
|
||||||
|
Network net.IPNet
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns presentation form of the APL record.
|
||||||
|
func (rr *APL) String() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString(rr.Hdr.String())
|
||||||
|
for i, p := range rr.Prefixes {
|
||||||
|
if i > 0 {
|
||||||
|
sb.WriteByte(' ')
|
||||||
|
}
|
||||||
|
sb.WriteString(p.str())
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// str returns presentation form of the APL prefix.
|
||||||
|
func (a *APLPrefix) str() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
if a.Negation {
|
||||||
|
sb.WriteByte('!')
|
||||||
|
}
|
||||||
|
|
||||||
|
switch len(a.Network.IP) {
|
||||||
|
case net.IPv4len:
|
||||||
|
sb.WriteByte('1')
|
||||||
|
case net.IPv6len:
|
||||||
|
sb.WriteByte('2')
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.WriteByte(':')
|
||||||
|
|
||||||
|
switch len(a.Network.IP) {
|
||||||
|
case net.IPv4len:
|
||||||
|
sb.WriteString(a.Network.IP.String())
|
||||||
|
case net.IPv6len:
|
||||||
|
// add prefix for IPv4-mapped IPv6
|
||||||
|
if v4 := a.Network.IP.To4(); v4 != nil {
|
||||||
|
sb.WriteString("::ffff:")
|
||||||
|
}
|
||||||
|
sb.WriteString(a.Network.IP.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.WriteByte('/')
|
||||||
|
|
||||||
|
prefix, _ := a.Network.Mask.Size()
|
||||||
|
sb.WriteString(strconv.Itoa(prefix))
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// equals reports whether two APL prefixes are identical.
|
||||||
|
func (a *APLPrefix) equals(b *APLPrefix) bool {
|
||||||
|
return a.Negation == b.Negation &&
|
||||||
|
bytes.Equal(a.Network.IP, b.Network.IP) &&
|
||||||
|
bytes.Equal(a.Network.Mask, b.Network.Mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy returns a copy of the APL prefix.
|
||||||
|
func (a *APLPrefix) copy() APLPrefix {
|
||||||
|
return APLPrefix{
|
||||||
|
Negation: a.Negation,
|
||||||
|
Network: copyNet(a.Network),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// len returns size of the prefix in wire format.
|
||||||
|
func (a *APLPrefix) len() int {
|
||||||
|
// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
|
||||||
|
prefix, _ := a.Network.Mask.Size()
|
||||||
|
return 4 + (prefix+7)/8
|
||||||
|
}
|
||||||
|
|
||||||
// TimeToString translates the RRSIG's incep. and expir. times to the
|
// TimeToString translates the RRSIG's incep. and expir. times to the
|
||||||
// string representation used when printing the record.
|
// string representation used when printing the record.
|
||||||
// It takes serial arithmetic (RFC 1982) into account.
|
// It takes serial arithmetic (RFC 1982) into account.
|
||||||
@ -1384,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)
|
||||||
@ -1411,6 +1525,17 @@ func copyIP(ip net.IP) net.IP {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copyNet returns a copy of a subnet.
|
||||||
|
func copyNet(n net.IPNet) net.IPNet {
|
||||||
|
m := make(net.IPMask, len(n.Mask))
|
||||||
|
copy(m, n.Mask)
|
||||||
|
|
||||||
|
return net.IPNet{
|
||||||
|
IP: copyIP(n.IP),
|
||||||
|
Mask: m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SplitN splits a string into N sized string chunks.
|
// SplitN splits a string into N sized string chunks.
|
||||||
// This might become an exported function once.
|
// This might become an exported function once.
|
||||||
func splitN(s string, n int) []string {
|
func splitN(s string, n int) []string {
|
||||||
|
8
vendor/github.com/miekg/dns/version.go
generated
vendored
8
vendor/github.com/miekg/dns/version.go
generated
vendored
@ -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, 3}
|
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)
|
||||||
}
|
}
|
||||||
|
18
vendor/github.com/miekg/dns/xfr.go
generated
vendored
18
vendor/github.com/miekg/dns/xfr.go
generated
vendored
@ -182,14 +182,17 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
|
|||||||
//
|
//
|
||||||
// ch := make(chan *dns.Envelope)
|
// ch := make(chan *dns.Envelope)
|
||||||
// tr := new(dns.Transfer)
|
// tr := new(dns.Transfer)
|
||||||
// go tr.Out(w, r, ch)
|
// var wg sync.WaitGroup
|
||||||
|
// go func() {
|
||||||
|
// tr.Out(w, r, ch)
|
||||||
|
// wg.Done()
|
||||||
|
// }()
|
||||||
// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
|
// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
|
||||||
// close(ch)
|
// close(ch)
|
||||||
// w.Hijack()
|
// wg.Wait() // wait until everything is written out
|
||||||
// // w.Close() // Client closes connection
|
// w.Close() // close connection
|
||||||
//
|
//
|
||||||
// The server is responsible for sending the correct sequence of RRs through the
|
// The server is responsible for sending the correct sequence of RRs through the channel ch.
|
||||||
// channel ch.
|
|
||||||
func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
|
func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
|
||||||
for x := range ch {
|
for x := range ch {
|
||||||
r := new(Msg)
|
r := new(Msg)
|
||||||
@ -198,11 +201,14 @@ func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
|
|||||||
r.Authoritative = true
|
r.Authoritative = true
|
||||||
// assume it fits TODO(miek): fix
|
// assume it fits TODO(miek): fix
|
||||||
r.Answer = append(r.Answer, x.RR...)
|
r.Answer = append(r.Answer, x.RR...)
|
||||||
|
if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
|
||||||
|
r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
|
||||||
|
}
|
||||||
if err := w.WriteMsg(r); err != nil {
|
if err := w.WriteMsg(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
w.TsigTimersOnly(true)
|
||||||
}
|
}
|
||||||
w.TsigTimersOnly(true)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
264
vendor/github.com/miekg/dns/zduplicate.go
generated
vendored
264
vendor/github.com/miekg/dns/zduplicate.go
generated
vendored
@ -37,7 +37,7 @@ func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Subtype != r2.Subtype {
|
if r1.Subtype != r2.Subtype {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Hostname, r2.Hostname) {
|
if !isDuplicateName(r1.Hostname, r2.Hostname) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -52,6 +52,23 @@ func (r1 *ANY) isDuplicate(_r2 RR) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r1 *APL) isDuplicate(_r2 RR) bool {
|
||||||
|
r2, ok := _r2.(*APL)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_ = r2
|
||||||
|
if len(r1.Prefixes) != len(r2.Prefixes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.Prefixes); i++ {
|
||||||
|
if !r1.Prefixes[i].equals(&r2.Prefixes[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (r1 *AVC) isDuplicate(_r2 RR) bool {
|
func (r1 *AVC) isDuplicate(_r2 RR) bool {
|
||||||
r2, ok := _r2.(*AVC)
|
r2, ok := _r2.(*AVC)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -87,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 {
|
||||||
@ -114,7 +173,7 @@ func (r1 *CNAME) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Target, r2.Target) {
|
if !isDuplicateName(r1.Target, r2.Target) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -155,13 +214,34 @@ 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 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Target, r2.Target) {
|
if !isDuplicateName(r1.Target, r2.Target) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -315,13 +395,55 @@ func (r1 *HIP) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i := 0; i < len(r1.RendezvousServers); i++ {
|
for i := 0; i < len(r1.RendezvousServers); i++ {
|
||||||
if !isDulicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
|
if !isDuplicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
||||||
@ -331,7 +453,7 @@ func (r1 *KX) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Preference != r2.Preference {
|
if r1.Preference != r2.Preference {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Exchanger, r2.Exchanger) {
|
if !isDuplicateName(r1.Exchanger, r2.Exchanger) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -406,7 +528,7 @@ func (r1 *LP) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Preference != r2.Preference {
|
if r1.Preference != r2.Preference {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Fqdn, r2.Fqdn) {
|
if !isDuplicateName(r1.Fqdn, r2.Fqdn) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -418,7 +540,7 @@ func (r1 *MB) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Mb, r2.Mb) {
|
if !isDuplicateName(r1.Mb, r2.Mb) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -430,7 +552,7 @@ func (r1 *MD) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Md, r2.Md) {
|
if !isDuplicateName(r1.Md, r2.Md) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -442,7 +564,7 @@ func (r1 *MF) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Mf, r2.Mf) {
|
if !isDuplicateName(r1.Mf, r2.Mf) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -454,7 +576,7 @@ func (r1 *MG) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Mg, r2.Mg) {
|
if !isDuplicateName(r1.Mg, r2.Mg) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -466,10 +588,10 @@ func (r1 *MINFO) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Rmail, r2.Rmail) {
|
if !isDuplicateName(r1.Rmail, r2.Rmail) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Email, r2.Email) {
|
if !isDuplicateName(r1.Email, r2.Email) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -481,7 +603,7 @@ func (r1 *MR) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Mr, r2.Mr) {
|
if !isDuplicateName(r1.Mr, r2.Mr) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -496,7 +618,7 @@ func (r1 *MX) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Preference != r2.Preference {
|
if r1.Preference != r2.Preference {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Mx, r2.Mx) {
|
if !isDuplicateName(r1.Mx, r2.Mx) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -523,7 +645,7 @@ func (r1 *NAPTR) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Regexp != r2.Regexp {
|
if r1.Regexp != r2.Regexp {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Replacement, r2.Replacement) {
|
if !isDuplicateName(r1.Replacement, r2.Replacement) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -579,7 +701,7 @@ func (r1 *NS) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Ns, r2.Ns) {
|
if !isDuplicateName(r1.Ns, r2.Ns) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -591,7 +713,7 @@ func (r1 *NSAPPTR) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Ptr, r2.Ptr) {
|
if !isDuplicateName(r1.Ptr, r2.Ptr) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -603,7 +725,7 @@ func (r1 *NSEC) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.NextDomain, r2.NextDomain) {
|
if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
|
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
|
||||||
@ -709,7 +831,7 @@ func (r1 *PTR) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Ptr, r2.Ptr) {
|
if !isDuplicateName(r1.Ptr, r2.Ptr) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -724,10 +846,10 @@ func (r1 *PX) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Preference != r2.Preference {
|
if r1.Preference != r2.Preference {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Map822, r2.Map822) {
|
if !isDuplicateName(r1.Map822, r2.Map822) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Mapx400, r2.Mapx400) {
|
if !isDuplicateName(r1.Mapx400, r2.Mapx400) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -772,10 +894,10 @@ func (r1 *RP) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Mbox, r2.Mbox) {
|
if !isDuplicateName(r1.Mbox, r2.Mbox) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Txt, r2.Txt) {
|
if !isDuplicateName(r1.Txt, r2.Txt) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -808,7 +930,7 @@ func (r1 *RRSIG) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.KeyTag != r2.KeyTag {
|
if r1.KeyTag != r2.KeyTag {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.SignerName, r2.SignerName) {
|
if !isDuplicateName(r1.SignerName, r2.SignerName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if r1.Signature != r2.Signature {
|
if r1.Signature != r2.Signature {
|
||||||
@ -826,7 +948,43 @@ func (r1 *RT) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Preference != r2.Preference {
|
if r1.Preference != r2.Preference {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Host, r2.Host) {
|
if !isDuplicateName(r1.Host, r2.Host) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
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 false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -859,10 +1017,10 @@ func (r1 *SOA) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Ns, r2.Ns) {
|
if !isDuplicateName(r1.Ns, r2.Ns) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Mbox, r2.Mbox) {
|
if !isDuplicateName(r1.Mbox, r2.Mbox) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if r1.Serial != r2.Serial {
|
if r1.Serial != r2.Serial {
|
||||||
@ -915,7 +1073,7 @@ func (r1 *SRV) isDuplicate(_r2 RR) bool {
|
|||||||
if r1.Port != r2.Port {
|
if r1.Port != r2.Port {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.Target, r2.Target) {
|
if !isDuplicateName(r1.Target, r2.Target) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -939,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 {
|
||||||
@ -966,10 +1145,10 @@ func (r1 *TALINK) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.PreviousName, r2.PreviousName) {
|
if !isDuplicateName(r1.PreviousName, r2.PreviousName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isDulicateName(r1.NextName, r2.NextName) {
|
if !isDuplicateName(r1.NextName, r2.NextName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -981,7 +1160,7 @@ func (r1 *TKEY) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Algorithm, r2.Algorithm) {
|
if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if r1.Inception != r2.Inception {
|
if r1.Inception != r2.Inception {
|
||||||
@ -1038,7 +1217,7 @@ func (r1 *TSIG) isDuplicate(_r2 RR) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ = r2
|
_ = r2
|
||||||
if !isDulicateName(r1.Algorithm, r2.Algorithm) {
|
if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if r1.TimeSigned != r2.TimeSigned {
|
if r1.TimeSigned != r2.TimeSigned {
|
||||||
@ -1138,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
|
||||||
|
}
|
||||||
|
153
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
153
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
@ -36,6 +36,14 @@ func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bo
|
|||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *APL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
||||||
|
off, err = packDataApl(rr.Prefixes, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
||||||
off, err = packStringTxt(rr.Txt, msg, off)
|
off, err = packStringTxt(rr.Txt, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -308,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 {
|
||||||
@ -898,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 {
|
||||||
@ -1078,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) {
|
||||||
@ -1127,6 +1187,17 @@ func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
|
|||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *APL) unpack(msg []byte, off int) (off1 int, err error) {
|
||||||
|
rdStart := off
|
||||||
|
_ = rdStart
|
||||||
|
|
||||||
|
rr.Prefixes, off, err = unpackDataApl(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
|
func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
|
||||||
rdStart := off
|
rdStart := off
|
||||||
_ = rdStart
|
_ = rdStart
|
||||||
@ -1540,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
|
||||||
@ -2442,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
|
||||||
@ -2720,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
|
||||||
|
}
|
||||||
|
105
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
105
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
@ -13,6 +13,7 @@ var TypeToRR = map[uint16]func() RR{
|
|||||||
TypeAAAA: func() RR { return new(AAAA) },
|
TypeAAAA: func() RR { return new(AAAA) },
|
||||||
TypeAFSDB: func() RR { return new(AFSDB) },
|
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||||
TypeANY: func() RR { return new(ANY) },
|
TypeANY: func() RR { return new(ANY) },
|
||||||
|
TypeAPL: func() RR { return new(APL) },
|
||||||
TypeAVC: func() RR { return new(AVC) },
|
TypeAVC: func() RR { return new(AVC) },
|
||||||
TypeCAA: func() RR { return new(CAA) },
|
TypeCAA: func() RR { return new(CAA) },
|
||||||
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
||||||
@ -32,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) },
|
||||||
@ -69,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) },
|
||||||
@ -79,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.
|
||||||
@ -87,6 +91,7 @@ var TypeToString = map[uint16]string{
|
|||||||
TypeAAAA: "AAAA",
|
TypeAAAA: "AAAA",
|
||||||
TypeAFSDB: "AFSDB",
|
TypeAFSDB: "AFSDB",
|
||||||
TypeANY: "ANY",
|
TypeANY: "ANY",
|
||||||
|
TypeAPL: "APL",
|
||||||
TypeATMA: "ATMA",
|
TypeATMA: "ATMA",
|
||||||
TypeAVC: "AVC",
|
TypeAVC: "AVC",
|
||||||
TypeAXFR: "AXFR",
|
TypeAXFR: "AXFR",
|
||||||
@ -108,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",
|
||||||
@ -151,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",
|
||||||
@ -162,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",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +177,7 @@ func (rr *A) Header() *RR_Header { return &rr.Hdr }
|
|||||||
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *APL) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
|
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
@ -188,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 }
|
||||||
@ -226,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 }
|
||||||
@ -236,16 +247,21 @@ 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 {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += net.IPv4len // A
|
if len(rr.A) != 0 {
|
||||||
|
l += net.IPv4len
|
||||||
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *AAAA) len(off int, compression map[string]struct{}) int {
|
func (rr *AAAA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += net.IPv6len // AAAA
|
if len(rr.AAAA) != 0 {
|
||||||
|
l += net.IPv6len
|
||||||
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
|
func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
|
||||||
@ -258,6 +274,13 @@ func (rr *ANY) len(off int, compression map[string]struct{}) int {
|
|||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
func (rr *APL) len(off int, compression map[string]struct{}) int {
|
||||||
|
l := rr.Hdr.len(off, compression)
|
||||||
|
for _, x := range rr.Prefixes {
|
||||||
|
l += x.len()
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
func (rr *AVC) len(off int, compression map[string]struct{}) int {
|
func (rr *AVC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
for _, x := range rr.Txt {
|
for _, x := range rr.Txt {
|
||||||
@ -308,12 +331,12 @@ func (rr *DS) len(off int, compression map[string]struct{}) int {
|
|||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *EID) len(off int, compression map[string]struct{}) int {
|
func (rr *EID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Endpoint)/2 + 1
|
l += len(rr.Endpoint) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *EUI48) len(off int, compression map[string]struct{}) int {
|
func (rr *EUI48) len(off int, compression map[string]struct{}) int {
|
||||||
@ -364,8 +387,10 @@ func (rr *KX) len(off int, compression map[string]struct{}) int {
|
|||||||
}
|
}
|
||||||
func (rr *L32) len(off int, compression map[string]struct{}) int {
|
func (rr *L32) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += net.IPv4len // Locator32
|
if len(rr.Locator32) != 0 {
|
||||||
|
l += net.IPv4len
|
||||||
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *L64) len(off int, compression map[string]struct{}) int {
|
func (rr *L64) len(off int, compression map[string]struct{}) int {
|
||||||
@ -446,7 +471,7 @@ func (rr *NID) len(off int, compression map[string]struct{}) int {
|
|||||||
}
|
}
|
||||||
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
|
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Locator)/2 + 1
|
l += len(rr.Locator) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NINFO) len(off int, compression map[string]struct{}) int {
|
func (rr *NINFO) len(off int, compression map[string]struct{}) int {
|
||||||
@ -499,7 +524,7 @@ func (rr *PX) len(off int, compression map[string]struct{}) int {
|
|||||||
}
|
}
|
||||||
func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
|
func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Rdata)/2 + 1
|
l += len(rr.Rdata) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RKEY) len(off int, compression map[string]struct{}) int {
|
func (rr *RKEY) len(off int, compression map[string]struct{}) int {
|
||||||
@ -540,7 +565,7 @@ func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
|
|||||||
l++ // Usage
|
l++ // Usage
|
||||||
l++ // Selector
|
l++ // Selector
|
||||||
l++ // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SOA) len(off int, compression map[string]struct{}) int {
|
func (rr *SOA) len(off int, compression map[string]struct{}) int {
|
||||||
@ -573,7 +598,16 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
|
|||||||
l := rr.Hdr.len(off, compression)
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // Type
|
l++ // Type
|
||||||
l += len(rr.FingerPrint)/2 + 1
|
l += len(rr.FingerPrint) / 2
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
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
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TA) len(off int, compression map[string]struct{}) int {
|
func (rr *TA) len(off int, compression map[string]struct{}) int {
|
||||||
@ -581,7 +615,7 @@ func (rr *TA) len(off int, compression map[string]struct{}) int {
|
|||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TALINK) len(off int, compression map[string]struct{}) int {
|
func (rr *TALINK) len(off int, compression map[string]struct{}) int {
|
||||||
@ -608,7 +642,7 @@ func (rr *TLSA) len(off int, compression map[string]struct{}) int {
|
|||||||
l++ // Usage
|
l++ // Usage
|
||||||
l++ // Selector
|
l++ // Selector
|
||||||
l++ // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TSIG) len(off int, compression map[string]struct{}) int {
|
func (rr *TSIG) len(off int, compression map[string]struct{}) int {
|
||||||
@ -653,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 {
|
||||||
@ -667,6 +709,13 @@ func (rr *AFSDB) copy() RR {
|
|||||||
func (rr *ANY) copy() RR {
|
func (rr *ANY) copy() RR {
|
||||||
return &ANY{rr.Hdr}
|
return &ANY{rr.Hdr}
|
||||||
}
|
}
|
||||||
|
func (rr *APL) copy() RR {
|
||||||
|
Prefixes := make([]APLPrefix, len(rr.Prefixes))
|
||||||
|
for i, e := range rr.Prefixes {
|
||||||
|
Prefixes[i] = e.copy()
|
||||||
|
}
|
||||||
|
return &APL{rr.Hdr, Prefixes}
|
||||||
|
}
|
||||||
func (rr *AVC) copy() RR {
|
func (rr *AVC) copy() RR {
|
||||||
Txt := make([]string, len(rr.Txt))
|
Txt := make([]string, len(rr.Txt))
|
||||||
copy(Txt, rr.Txt)
|
copy(Txt, rr.Txt)
|
||||||
@ -675,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}
|
||||||
}
|
}
|
||||||
@ -689,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}
|
||||||
}
|
}
|
||||||
@ -721,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}
|
||||||
}
|
}
|
||||||
@ -798,7 +862,9 @@ func (rr *OPENPGPKEY) copy() RR {
|
|||||||
}
|
}
|
||||||
func (rr *OPT) copy() RR {
|
func (rr *OPT) copy() RR {
|
||||||
Option := make([]EDNS0, len(rr.Option))
|
Option := make([]EDNS0, len(rr.Option))
|
||||||
copy(Option, rr.Option)
|
for i, e := range rr.Option {
|
||||||
|
Option[i] = e.copy()
|
||||||
|
}
|
||||||
return &OPT{rr.Hdr, Option}
|
return &OPT{rr.Hdr, Option}
|
||||||
}
|
}
|
||||||
func (rr *PTR) copy() RR {
|
func (rr *PTR) copy() RR {
|
||||||
@ -822,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}
|
||||||
}
|
}
|
||||||
@ -839,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}
|
||||||
}
|
}
|
||||||
@ -871,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}
|
||||||
|
}
|
||||||
|
9
vendor/github.com/nathan-osman/go-aptproxy/LICENSE.txt
generated
vendored
9
vendor/github.com/nathan-osman/go-aptproxy/LICENSE.txt
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Nathan Osman
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
125
vendor/github.com/nathan-osman/go-aptproxy/cache/cache.go
generated
vendored
125
vendor/github.com/nathan-osman/go-aptproxy/cache/cache.go
generated
vendored
@ -1,125 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"mime"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reader is a generic interface for reading cache entries either from disk or
|
|
||||||
// directly attached to a downloader.
|
|
||||||
type Reader interface {
|
|
||||||
io.ReadCloser
|
|
||||||
GetEntry() (*Entry, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache provides access to entries in the cache.
|
|
||||||
type Cache struct {
|
|
||||||
mutex sync.Mutex
|
|
||||||
directory string
|
|
||||||
downloaders map[string]*downloader
|
|
||||||
waitGroup sync.WaitGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCache creates a new cache in the specified directory.
|
|
||||||
func NewCache(directory string) (*Cache, error) {
|
|
||||||
if err := os.MkdirAll(directory, 0775); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Cache{
|
|
||||||
directory: directory,
|
|
||||||
downloaders: make(map[string]*downloader),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getFilenames returns the filenames for the JSON and data files from a URL.
|
|
||||||
func (c *Cache) getFilenames(rawurl string) (hash, jsonFilename, dataFilename string) {
|
|
||||||
b := md5.Sum([]byte(rawurl))
|
|
||||||
hash = hex.EncodeToString(b[:])
|
|
||||||
jsonFilename = path.Join(c.directory, fmt.Sprintf("%s.json", hash))
|
|
||||||
dataFilename = path.Join(c.directory, fmt.Sprintf("%s.data", hash))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetReader obtains a Reader for the specified rawurl. If a downloader
|
|
||||||
// currently exists for the URL, a live reader is created and connected to it.
|
|
||||||
// If the URL exists in the cache, it is read using the standard file API. If
|
|
||||||
// not, a downloader and live reader are created.
|
|
||||||
func (c *Cache) GetReader(rawurl string, maxAge time.Duration) (Reader, error) {
|
|
||||||
hash, jsonFilename, dataFilename := c.getFilenames(rawurl)
|
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
d, ok := c.downloaders[hash]
|
|
||||||
if !ok {
|
|
||||||
_, err := os.Stat(jsonFilename)
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r, err := newDiskReader(jsonFilename, dataFilename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
e, _ := r.GetEntry()
|
|
||||||
lastModified, _ := time.Parse(http.TimeFormat, e.LastModified)
|
|
||||||
if e.Complete &&
|
|
||||||
(maxAge == -1 ||
|
|
||||||
lastModified.Before(time.Now().Add(maxAge))) {
|
|
||||||
log.Println("[HIT]", rawurl)
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d = newDownloader(rawurl, jsonFilename, dataFilename)
|
|
||||||
go func() {
|
|
||||||
d.WaitForDone()
|
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
delete(c.downloaders, hash)
|
|
||||||
c.waitGroup.Done()
|
|
||||||
}()
|
|
||||||
c.downloaders[hash] = d
|
|
||||||
c.waitGroup.Add(1)
|
|
||||||
}
|
|
||||||
log.Println("[MISS]", rawurl)
|
|
||||||
return newLiveReader(d, dataFilename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert adds an item into the cache.
|
|
||||||
func (c *Cache) Insert(rawurl string, r io.Reader) error {
|
|
||||||
_, jsonFilename, dataFilename := c.getFilenames(rawurl)
|
|
||||||
f, err := os.Open(dataFilename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
n, err := io.Copy(f, r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
e := &Entry{
|
|
||||||
URL: rawurl,
|
|
||||||
Complete: true,
|
|
||||||
ContentLength: strconv.FormatInt(n, 10),
|
|
||||||
ContentType: mime.TypeByExtension(rawurl),
|
|
||||||
LastModified: time.Now().Format(http.TimeFormat),
|
|
||||||
}
|
|
||||||
return e.Save(jsonFilename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement some form of "safe abort" for downloads so that the entire
|
|
||||||
// application doesn't end up spinning its tires waiting for downloads to end.
|
|
||||||
|
|
||||||
// Close waits for all downloaders to complete before shutting down.
|
|
||||||
func (c *Cache) Close() {
|
|
||||||
c.waitGroup.Wait()
|
|
||||||
}
|
|
43
vendor/github.com/nathan-osman/go-aptproxy/cache/diskreader.go
generated
vendored
43
vendor/github.com/nathan-osman/go-aptproxy/cache/diskreader.go
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// diskReader reads a file from the cache on disk.
|
|
||||||
type diskReader struct {
|
|
||||||
entry *Entry
|
|
||||||
file *os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
// newDiskReader creates a reader from the provided JSON and data filenames.
|
|
||||||
// Failure to open either of these results in an immediate error.
|
|
||||||
func newDiskReader(jsonFilename, dataFilename string) (*diskReader, error) {
|
|
||||||
e := &Entry{}
|
|
||||||
if err := e.Load(jsonFilename); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
f, err := os.Open(dataFilename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &diskReader{
|
|
||||||
entry: e,
|
|
||||||
file: f,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read attempts to read as much data as possible into the provided buffer.
|
|
||||||
func (d *diskReader) Read(p []byte) (int, error) {
|
|
||||||
return d.file.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close attempts to close the data file.
|
|
||||||
func (d *diskReader) Close() error {
|
|
||||||
return d.file.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntry returns the Entry associated with the file.
|
|
||||||
func (d *diskReader) GetEntry() (*Entry, error) {
|
|
||||||
return d.entry, nil
|
|
||||||
}
|
|
105
vendor/github.com/nathan-osman/go-aptproxy/cache/downloader.go
generated
vendored
105
vendor/github.com/nathan-osman/go-aptproxy/cache/downloader.go
generated
vendored
@ -1,105 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DownloadError conveys information about a download request that failed.
|
|
||||||
type DownloadError struct {
|
|
||||||
Status string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns a description of the error.
|
|
||||||
func (d *DownloadError) Error() string {
|
|
||||||
return d.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
// downloader attempts to download a file from a remote URL.
|
|
||||||
type downloader struct {
|
|
||||||
doneMutex sync.Mutex
|
|
||||||
err error
|
|
||||||
entry *Entry
|
|
||||||
entryMutex sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// newDownloader creates a new downloader.
|
|
||||||
func newDownloader(rawurl, jsonFilename, dataFilename string) *downloader {
|
|
||||||
d := &downloader{}
|
|
||||||
d.doneMutex.Lock()
|
|
||||||
d.entryMutex.Lock()
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
d.doneMutex.Unlock()
|
|
||||||
}()
|
|
||||||
once := &sync.Once{}
|
|
||||||
trigger := func() {
|
|
||||||
once.Do(func() {
|
|
||||||
d.entryMutex.Unlock()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
defer trigger()
|
|
||||||
resp, err := http.Get(rawurl)
|
|
||||||
if err != nil {
|
|
||||||
d.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
d.err = &DownloadError{
|
|
||||||
Status: resp.Status,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f, err := os.Create(dataFilename)
|
|
||||||
if err != nil {
|
|
||||||
d.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
d.entry = &Entry{
|
|
||||||
URL: rawurl,
|
|
||||||
ContentLength: strconv.FormatInt(resp.ContentLength, 10),
|
|
||||||
ContentType: resp.Header.Get("Content-Type"),
|
|
||||||
LastModified: resp.Header.Get("Last-Modified"),
|
|
||||||
}
|
|
||||||
if d.entry.ContentType == "" {
|
|
||||||
d.entry.ContentType = "application/octet-stream"
|
|
||||||
}
|
|
||||||
if d.entry.LastModified == "" {
|
|
||||||
d.entry.LastModified = time.Now().Format(http.TimeFormat)
|
|
||||||
}
|
|
||||||
if err = d.entry.Save(jsonFilename); err != nil {
|
|
||||||
d.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
trigger()
|
|
||||||
n, err := io.Copy(f, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
d.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.entry.ContentLength = strconv.FormatInt(n, 10)
|
|
||||||
d.entry.Complete = true
|
|
||||||
d.entry.Save(jsonFilename)
|
|
||||||
}()
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntry retrieves the entry associated with the download.
|
|
||||||
func (d *downloader) GetEntry() (*Entry, error) {
|
|
||||||
d.entryMutex.Lock()
|
|
||||||
defer d.entryMutex.Unlock()
|
|
||||||
return d.entry, d.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitForDone will block until the download completes.
|
|
||||||
func (d *downloader) WaitForDone() error {
|
|
||||||
d.doneMutex.Lock()
|
|
||||||
defer d.doneMutex.Unlock()
|
|
||||||
return d.err
|
|
||||||
}
|
|
35
vendor/github.com/nathan-osman/go-aptproxy/cache/entry.go
generated
vendored
35
vendor/github.com/nathan-osman/go-aptproxy/cache/entry.go
generated
vendored
@ -1,35 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Entry represents an individual item in the cache.
|
|
||||||
type Entry struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
Complete bool `json:"complete"`
|
|
||||||
ContentLength string `json:"content_length"`
|
|
||||||
ContentType string `json:"content_type"`
|
|
||||||
LastModified string `json:"last_modified"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load reads the entry from disk.
|
|
||||||
func (e *Entry) Load(filename string) error {
|
|
||||||
f, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
return json.NewDecoder(f).Decode(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save writes the entry to disk.
|
|
||||||
func (e *Entry) Save(filename string) error {
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
return json.NewEncoder(f).Encode(e)
|
|
||||||
}
|
|
102
vendor/github.com/nathan-osman/go-aptproxy/cache/livereader.go
generated
vendored
102
vendor/github.com/nathan-osman/go-aptproxy/cache/livereader.go
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// liveReader reads a file from disk, synchronizing reads with a downloader.
|
|
||||||
type liveReader struct {
|
|
||||||
downloader *downloader
|
|
||||||
dataFilename string
|
|
||||||
file *os.File
|
|
||||||
entry *Entry
|
|
||||||
done chan error
|
|
||||||
err error
|
|
||||||
eof bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// newLiveReader creates a reader from the provided downloader and data
|
|
||||||
// file. fsnotify is used to watch for writes to the file to avoid using a
|
|
||||||
// spinloop. Invoking this function assumes the existence of the data file.
|
|
||||||
func newLiveReader(d *downloader, dataFilename string) (*liveReader, error) {
|
|
||||||
l := &liveReader{
|
|
||||||
downloader: d,
|
|
||||||
dataFilename: dataFilename,
|
|
||||||
done: make(chan error),
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
defer close(l.done)
|
|
||||||
l.done <- d.WaitForDone()
|
|
||||||
}()
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read attempts to read as much data as possible into the provided buffer.
|
|
||||||
// Since data is being downloaded as data is being read, fsnotify is used to
|
|
||||||
// monitor writes to the file. This function blocks until the requested amount
|
|
||||||
// of data is read, an error occurs, or EOF is encountered.
|
|
||||||
func (l *liveReader) Read(p []byte) (int, error) {
|
|
||||||
if l.err != nil {
|
|
||||||
return 0, l.err
|
|
||||||
}
|
|
||||||
if l.file == nil {
|
|
||||||
f, err := os.Open(l.dataFilename)
|
|
||||||
if err != nil {
|
|
||||||
l.err = err
|
|
||||||
return 0, l.err
|
|
||||||
}
|
|
||||||
l.file = f
|
|
||||||
}
|
|
||||||
bytesRead := 0
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
|
||||||
if err != nil {
|
|
||||||
l.err = err
|
|
||||||
return 0, l.err
|
|
||||||
}
|
|
||||||
defer watcher.Close()
|
|
||||||
if err := watcher.Add(l.dataFilename); err != nil {
|
|
||||||
l.err = err
|
|
||||||
return 0, l.err
|
|
||||||
}
|
|
||||||
loop:
|
|
||||||
for bytesRead < len(p) {
|
|
||||||
n, err := l.file.Read(p[bytesRead:])
|
|
||||||
bytesRead += n
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF || l.eof {
|
|
||||||
l.err = err
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case e := <-watcher.Events:
|
|
||||||
if e.Op&fsnotify.Write != fsnotify.Write {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case err = <-l.done:
|
|
||||||
l.err = err
|
|
||||||
l.eof = true
|
|
||||||
}
|
|
||||||
continue loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytesRead, l.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close attempts to close the data file (if opened).
|
|
||||||
func (l *liveReader) Close() error {
|
|
||||||
if l.file != nil {
|
|
||||||
return l.file.Close()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntry returns the Entry associated with the file, blocking until either
|
|
||||||
// the data is available or an error occurs.
|
|
||||||
func (l *liveReader) GetEntry() (*Entry, error) {
|
|
||||||
return l.downloader.GetEntry()
|
|
||||||
}
|
|
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
@ -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.
|
|
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
@ -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
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
@ -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
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
@ -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.
|
|
217
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
217
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
@ -1,217 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package 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[:])
|
|
||||||
}
|
|
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
File diff suppressed because it is too large
Load Diff
3
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
3
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
@ -129,7 +129,8 @@ func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
|
|||||||
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
||||||
offset := int(ins.Off)
|
offset := int(ins.Off)
|
||||||
|
|
||||||
if !inBounds(len(in), offset, 0) {
|
// Size of LoadMemShift is always 1 byte
|
||||||
|
if !inBounds(len(in), offset, 1) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
@ -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 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
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
@ -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 darwin dragonfly freebsd netbsd openbsd
|
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
|
||||||
|
// +build aix darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
@ -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
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
@ -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 arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
4
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
4
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
@ -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
|
||||||
|
|
||||||
|
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
@ -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 !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 }
|
||||||
|
22
vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
Normal file
22
vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
Normal 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)
|
||||||
|
}
|
25
vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
generated
vendored
Normal file
25
vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
generated
vendored
Normal 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)
|
||||||
|
}
|
26
vendor/golang.org/x/net/internal/socket/complete_dontwait.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/internal/socket/complete_dontwait.go
generated
vendored
Normal 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
|
||||||
|
}
|
22
vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
generated
vendored
Normal file
22
vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
generated
vendored
Normal 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
|
||||||
|
}
|
1
vendor/golang.org/x/net/internal/socket/empty.s
generated
vendored
1
vendor/golang.org/x/net/internal/socket/empty.s
generated
vendored
@ -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 darwin && go1.12
|
||||||
// +build darwin,go1.12
|
// +build darwin,go1.12
|
||||||
|
|
||||||
// This exists solely so we can linkname in symbols from syscall.
|
// This exists solely so we can linkname in symbols from syscall.
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
@ -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 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
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
@ -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
|
||||||
|
5
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
5
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
@ -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.
|
||||||
|
|
||||||
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos)
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd zos
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
|
||||||
|
4
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
4
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
@ -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
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
@ -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 !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
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
@ -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 !linux,!netbsd
|
//go:build !aix && !linux && !netbsd
|
||||||
|
// +build !aix,!linux,!netbsd
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
|
||||||
|
106
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
106
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
@ -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.
|
||||||
|
|
||||||
// +build linux netbsd
|
//go: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)
|
||||||
|
}
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
@ -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 darwin dragonfly freebsd netbsd openbsd
|
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
|
||||||
|
// +build aix darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
@ -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 darwin dragonfly freebsd netbsd
|
//go:build aix || darwin || dragonfly || freebsd || netbsd
|
||||||
|
// +build aix darwin dragonfly freebsd netbsd
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
@ -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
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
@ -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 arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package socket
|
package socket
|
||||||
|
4
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
4
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
@ -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
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
3
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
@ -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 !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
|
||||||
|
|
||||||
|
36
vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
generated
vendored
Normal file
36
vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
generated
vendored
Normal 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)
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user