Fix panic when parsing resolv.conf
This commit is contained in:
parent
f149b56063
commit
9ae808aac4
316 changed files with 37454 additions and 13195 deletions
16
Gopkg.lock
generated
16
Gopkg.lock
generated
|
@ -810,9 +810,10 @@
|
||||||
source = "https://github.com/containous/mesos-dns.git"
|
source = "https://github.com/containous/mesos-dns.git"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
name = "github.com/miekg/dns"
|
name = "github.com/miekg/dns"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "8060d9f51305bbe024b99679454e62f552cd0b0b"
|
revision = "906238edc6eb0ddface4a1923f6d41ef2a5ca59b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -1106,28 +1107,35 @@
|
||||||
packages = [
|
packages = [
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"blowfish",
|
"blowfish",
|
||||||
|
"ed25519",
|
||||||
|
"ed25519/internal/edwards25519",
|
||||||
"ocsp",
|
"ocsp",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"scrypt"
|
"scrypt"
|
||||||
]
|
]
|
||||||
revision = "4ed45ec682102c643324fae5dff8dab085b6c300"
|
revision = "b080dc9a8c480b08e698fb1219160d598526310f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
|
"bpf",
|
||||||
"context",
|
"context",
|
||||||
"context/ctxhttp",
|
"context/ctxhttp",
|
||||||
"http2",
|
"http2",
|
||||||
"http2/hpack",
|
"http2/hpack",
|
||||||
"idna",
|
"idna",
|
||||||
|
"internal/iana",
|
||||||
|
"internal/socket",
|
||||||
"internal/timeseries",
|
"internal/timeseries",
|
||||||
|
"ipv4",
|
||||||
|
"ipv6",
|
||||||
"lex/httplex",
|
"lex/httplex",
|
||||||
"proxy",
|
"proxy",
|
||||||
"publicsuffix",
|
"publicsuffix",
|
||||||
"trace",
|
"trace",
|
||||||
"websocket"
|
"websocket"
|
||||||
]
|
]
|
||||||
revision = "c8c74377599bd978aee1cf3b9b63a8634051cec2"
|
revision = "894f8ed5849b15b810ae41e9590a0d05395bba27"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
|
@ -1390,6 +1398,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "7122deb7b2056ecfa444c5fb64437c1b0723afae528a331c4b032b841039383b"
|
inputs-digest = "e39b26480b9d74df5e7c14ac916b991027976286a605a99e3c512d1fde87b21e"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
12
Gopkg.toml
12
Gopkg.toml
|
@ -191,6 +191,18 @@ ignored = ["github.com/sirupsen/logrus"]
|
||||||
name = "github.com/coreos/bbolt"
|
name = "github.com/coreos/bbolt"
|
||||||
revision = "32c383e75ce054674c53b5a07e55de85332aee14"
|
revision = "32c383e75ce054674c53b5a07e55de85332aee14"
|
||||||
|
|
||||||
|
[[override]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/miekg/dns"
|
||||||
|
|
||||||
|
[[override]]
|
||||||
|
name = "golang.org/x/crypto"
|
||||||
|
revision = "b080dc9a8c480b08e698fb1219160d598526310f"
|
||||||
|
|
||||||
|
[[override]]
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
revision = "894f8ed5849b15b810ae41e9590a0d05395bba27"
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
non-go = true
|
non-go = true
|
||||||
go-tests = true
|
go-tests = true
|
||||||
|
|
307
vendor/github.com/miekg/dns/client.go
generated
vendored
307
vendor/github.com/miekg/dns/client.go
generated
vendored
|
@ -4,10 +4,12 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,7 +20,7 @@ const tcpIdleTimeout time.Duration = 8 * time.Second
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
net.Conn // a net.Conn holding the connection
|
net.Conn // a net.Conn holding the connection
|
||||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||||
rtt time.Duration
|
rtt time.Duration
|
||||||
t time.Time
|
t time.Time
|
||||||
tsigRequestMAC string
|
tsigRequestMAC string
|
||||||
|
@ -26,14 +28,18 @@ type Conn struct {
|
||||||
|
|
||||||
// A Client defines parameters for a DNS client.
|
// A Client defines parameters for a DNS client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
||||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||||
TLSConfig *tls.Config // TLS connection configuration
|
TLSConfig *tls.Config // TLS connection configuration
|
||||||
Timeout time.Duration // a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout and WriteTimeout when non-zero
|
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
|
||||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
|
||||||
|
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
|
||||||
|
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
|
||||||
|
Timeout time.Duration
|
||||||
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
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 fully qualified
|
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||||
group singleflight
|
group singleflight
|
||||||
}
|
}
|
||||||
|
@ -43,93 +49,11 @@ type Client struct {
|
||||||
// will it fall back to TCP in case of truncation.
|
// will it fall back to TCP in case of truncation.
|
||||||
// See client.Exchange for more information on setting larger buffer sizes.
|
// See client.Exchange for more information on setting larger buffer sizes.
|
||||||
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||||
var co *Conn
|
client := Client{Net: "udp"}
|
||||||
co, err = DialTimeout("udp", a, dnsTimeout)
|
r, _, err = client.Exchange(m, a)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer co.Close()
|
|
||||||
|
|
||||||
opt := m.IsEdns0()
|
|
||||||
// If EDNS0 is used use that for size.
|
|
||||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
|
||||||
co.UDPSize = opt.UDPSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
|
||||||
if err = co.WriteMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
|
||||||
r, err = co.ReadMsg()
|
|
||||||
if err == nil && r.Id != m.Id {
|
|
||||||
err = ErrId
|
|
||||||
}
|
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
|
||||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
|
||||||
// This function is going away, but can easily be mimicked:
|
|
||||||
//
|
|
||||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
|
||||||
// co.WriteMsg(m)
|
|
||||||
// in, _ := co.ReadMsg()
|
|
||||||
// co.Close()
|
|
||||||
//
|
|
||||||
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
|
||||||
println("dns: this function is deprecated")
|
|
||||||
co := new(Conn)
|
|
||||||
co.Conn = c
|
|
||||||
if err = co.WriteMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r, err = co.ReadMsg()
|
|
||||||
if err == nil && r.Id != m.Id {
|
|
||||||
err = ErrId
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exchange performs a synchronous query. It sends the message m to the address
|
|
||||||
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
|
|
||||||
//
|
|
||||||
// c := new(dns.Client)
|
|
||||||
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
|
||||||
//
|
|
||||||
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
|
||||||
// case of truncation.
|
|
||||||
// It is up to the caller to create a message that allows for larger responses to be
|
|
||||||
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
|
||||||
// buffer, see SetEdns0. Messsages without an OPT RR will fallback to the historic limit
|
|
||||||
// of 512 bytes.
|
|
||||||
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
|
||||||
if !c.SingleInflight {
|
|
||||||
return c.exchange(m, a)
|
|
||||||
}
|
|
||||||
// This adds a bunch of garbage, TODO(miek).
|
|
||||||
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, a)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return r, rtt, err
|
|
||||||
}
|
|
||||||
if shared {
|
|
||||||
return r.Copy(), rtt, nil
|
|
||||||
}
|
|
||||||
return r, rtt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) dialTimeout() time.Duration {
|
func (c *Client) dialTimeout() time.Duration {
|
||||||
if c.Timeout != 0 {
|
if c.Timeout != 0 {
|
||||||
return c.Timeout
|
return c.Timeout
|
||||||
|
@ -154,37 +78,88 @@ func (c *Client) writeTimeout() time.Duration {
|
||||||
return dnsTimeout
|
return dnsTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
// Dial connects to the address on the named network.
|
||||||
var co *Conn
|
func (c *Client) Dial(address string) (conn *Conn, err error) {
|
||||||
|
// create a new dialer with the appropriate timeout
|
||||||
|
var d net.Dialer
|
||||||
|
if c.Dialer == nil {
|
||||||
|
d = net.Dialer{}
|
||||||
|
} else {
|
||||||
|
d = net.Dialer(*c.Dialer)
|
||||||
|
}
|
||||||
|
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
|
||||||
|
|
||||||
network := "udp"
|
network := "udp"
|
||||||
tls := false
|
useTLS := false
|
||||||
|
|
||||||
switch c.Net {
|
switch c.Net {
|
||||||
case "tcp-tls":
|
case "tcp-tls":
|
||||||
network = "tcp"
|
network = "tcp"
|
||||||
tls = true
|
useTLS = true
|
||||||
case "tcp4-tls":
|
case "tcp4-tls":
|
||||||
network = "tcp4"
|
network = "tcp4"
|
||||||
tls = true
|
useTLS = true
|
||||||
case "tcp6-tls":
|
case "tcp6-tls":
|
||||||
network = "tcp6"
|
network = "tcp6"
|
||||||
tls = true
|
useTLS = true
|
||||||
default:
|
default:
|
||||||
if c.Net != "" {
|
if c.Net != "" {
|
||||||
network = c.Net
|
network = c.Net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var deadline time.Time
|
conn = new(Conn)
|
||||||
if c.Timeout != 0 {
|
if useTLS {
|
||||||
deadline = time.Now().Add(c.Timeout)
|
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
|
||||||
|
} else {
|
||||||
|
conn.Conn, err = d.Dial(network, address)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exchange performs a synchronous query. It sends the message m to the address
|
||||||
|
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
|
||||||
|
//
|
||||||
|
// c := new(dns.Client)
|
||||||
|
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
||||||
|
//
|
||||||
|
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
||||||
|
// case of truncation.
|
||||||
|
// It is up to the caller to create a message that allows for larger responses to be
|
||||||
|
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
||||||
|
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
|
||||||
|
// of 512 bytes
|
||||||
|
// To specify a local address or a timeout, the caller has to set the `Client.Dialer`
|
||||||
|
// attribute appropriately
|
||||||
|
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
if !c.SingleInflight {
|
||||||
|
return c.exchange(m, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tls {
|
t := "nop"
|
||||||
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, c.dialTimeout())
|
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
||||||
} else {
|
t = t1
|
||||||
co, err = DialTimeout(network, a, c.dialTimeout())
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
@ -202,12 +177,13 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
co.TsigSecret = c.TsigSecret
|
co.TsigSecret = c.TsigSecret
|
||||||
co.SetWriteDeadline(deadlineOrTimeout(deadline, c.writeTimeout()))
|
// write with the appropriate write timeout
|
||||||
|
co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
|
||||||
if err = co.WriteMsg(m); err != nil {
|
if err = co.WriteMsg(m); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
co.SetReadDeadline(deadlineOrTimeout(deadline, c.readTimeout()))
|
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
|
||||||
r, err = co.ReadMsg()
|
r, err = co.ReadMsg()
|
||||||
if err == nil && r.Id != m.Id {
|
if err == nil && r.Id != m.Id {
|
||||||
err = ErrId
|
err = ErrId
|
||||||
|
@ -216,8 +192,10 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMsg reads a message from the connection co.
|
// ReadMsg reads a message from the connection co.
|
||||||
// If the received message contains a TSIG record the transaction
|
// If the received message contains a TSIG record the transaction signature
|
||||||
// signature is verified.
|
// is verified. This method always tries to return the message, however if an
|
||||||
|
// error is returned there are no guarantees that the returned message is a
|
||||||
|
// valid representation of the packet read.
|
||||||
func (co *Conn) ReadMsg() (*Msg, error) {
|
func (co *Conn) ReadMsg() (*Msg, error) {
|
||||||
p, err := co.ReadMsgHeader(nil)
|
p, err := co.ReadMsgHeader(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -226,13 +204,10 @@ func (co *Conn) ReadMsg() (*Msg, error) {
|
||||||
|
|
||||||
m := new(Msg)
|
m := new(Msg)
|
||||||
if err := m.Unpack(p); err != nil {
|
if err := m.Unpack(p); err != nil {
|
||||||
// If ErrTruncated was returned, we still want to allow the user to use
|
// If an error was returned, we still want to allow the user to use
|
||||||
// the message, but naively they can just check err if they don't want
|
// the message, but naively they can just check err if they don't want
|
||||||
// to use a truncated message
|
// to use an erroneous message
|
||||||
if err == ErrTruncated {
|
return m, err
|
||||||
return m, err
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if t := m.IsTsig(); t != nil {
|
if t := m.IsTsig(); t != nil {
|
||||||
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
||||||
|
@ -300,6 +275,18 @@ func tcpMsgLen(t io.Reader) (int, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
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 {
|
if n != 2 {
|
||||||
return 0, ErrShortRead
|
return 0, ErrShortRead
|
||||||
}
|
}
|
||||||
|
@ -400,10 +387,28 @@ func (co *Conn) Write(p []byte) (n int, err error) {
|
||||||
n, err := io.Copy(w, bytes.NewReader(p))
|
n, err := io.Copy(w, bytes.NewReader(p))
|
||||||
return int(n), err
|
return int(n), err
|
||||||
}
|
}
|
||||||
n, err = co.Conn.(*net.UDPConn).Write(p)
|
n, err = co.Conn.Write(p)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the appropriate timeout for a specific request
|
||||||
|
func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration {
|
||||||
|
var requestTimeout time.Duration
|
||||||
|
if c.Timeout != 0 {
|
||||||
|
requestTimeout = c.Timeout
|
||||||
|
} else {
|
||||||
|
requestTimeout = timeout
|
||||||
|
}
|
||||||
|
// net.Dialer.Timeout has priority if smaller than the timeouts computed so
|
||||||
|
// far
|
||||||
|
if c.Dialer != nil && c.Dialer.Timeout != 0 {
|
||||||
|
if c.Dialer.Timeout < requestTimeout {
|
||||||
|
requestTimeout = c.Dialer.Timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestTimeout
|
||||||
|
}
|
||||||
|
|
||||||
// Dial connects to the address on the named network.
|
// Dial connects to the address on the named network.
|
||||||
func Dial(network, address string) (conn *Conn, err error) {
|
func Dial(network, address string) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
conn = new(Conn)
|
||||||
|
@ -414,10 +419,43 @@ func Dial(network, address string) (conn *Conn, err error) {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExchangeContext performs a synchronous UDP query, like Exchange. It
|
||||||
|
// additionally obeys deadlines from the passed Context.
|
||||||
|
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
|
||||||
|
client := Client{Net: "udp"}
|
||||||
|
r, _, err = client.ExchangeContext(ctx, m, a)
|
||||||
|
// ignorint rtt to leave the original ExchangeContext API unchanged, but
|
||||||
|
// this function will go away
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||||
|
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||||
|
// This function is going away, but can easily be mimicked:
|
||||||
|
//
|
||||||
|
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||||
|
// co.WriteMsg(m)
|
||||||
|
// in, _ := co.ReadMsg()
|
||||||
|
// co.Close()
|
||||||
|
//
|
||||||
|
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||||
|
println("dns: ExchangeConn: this function is deprecated")
|
||||||
|
co := new(Conn)
|
||||||
|
co.Conn = c
|
||||||
|
if err = co.WriteMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r, err = co.ReadMsg()
|
||||||
|
if err == nil && r.Id != m.Id {
|
||||||
|
err = ErrId
|
||||||
|
}
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
// DialTimeout acts like Dial but takes a timeout.
|
// DialTimeout acts like Dial but takes a timeout.
|
||||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
|
||||||
conn.Conn, err = net.DialTimeout(network, address, timeout)
|
conn, err = client.Dial(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -426,8 +464,12 @@ func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, er
|
||||||
|
|
||||||
// DialWithTLS connects to the address on the named network with TLS.
|
// DialWithTLS connects to the address on the named network with TLS.
|
||||||
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
if !strings.HasSuffix(network, "-tls") {
|
||||||
conn.Conn, err = tls.Dial(network, address, tlsConfig)
|
network += "-tls"
|
||||||
|
}
|
||||||
|
client := Client{Net: network, TLSConfig: tlsConfig}
|
||||||
|
conn, err = client.Dial(address)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -436,20 +478,29 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
|
||||||
|
|
||||||
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||||
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
||||||
var dialer net.Dialer
|
if !strings.HasSuffix(network, "-tls") {
|
||||||
dialer.Timeout = timeout
|
network += "-tls"
|
||||||
|
}
|
||||||
conn = new(Conn)
|
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
|
||||||
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
|
conn, err = client.Dial(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
|
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
||||||
if deadline.IsZero() {
|
// context, if present. If there is both a context deadline and a configured
|
||||||
return time.Now().Add(timeout)
|
// timeout on the client, the earliest of the two takes effect.
|
||||||
|
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
var timeout time.Duration
|
||||||
|
if deadline, ok := ctx.Deadline(); !ok {
|
||||||
|
timeout = 0
|
||||||
|
} else {
|
||||||
|
timeout = deadline.Sub(time.Now())
|
||||||
}
|
}
|
||||||
return deadline
|
// not passing the context to the underlying calls, as the API does not support
|
||||||
|
// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
|
||||||
|
c.Dialer = &net.Dialer{Timeout: timeout}
|
||||||
|
return c.Exchange(m, a)
|
||||||
}
|
}
|
||||||
|
|
48
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
48
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
|
@ -2,6 +2,7 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -25,8 +26,13 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
return ClientConfigFromReader(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument
|
||||||
|
func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
|
||||||
c := new(ClientConfig)
|
c := new(ClientConfig)
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(resolvconf)
|
||||||
c.Servers = make([]string, 0)
|
c.Servers = make([]string, 0)
|
||||||
c.Search = make([]string, 0)
|
c.Search = make([]string, 0)
|
||||||
c.Port = "53"
|
c.Port = "53"
|
||||||
|
@ -73,8 +79,10 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
||||||
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:])
|
||||||
if n < 1 {
|
if n < 0 {
|
||||||
n = 1
|
n = 0
|
||||||
|
} else if n > 15 {
|
||||||
|
n = 15
|
||||||
}
|
}
|
||||||
c.Ndots = n
|
c.Ndots = n
|
||||||
case len(s) >= 8 && s[:8] == "timeout:":
|
case len(s) >= 8 && s[:8] == "timeout:":
|
||||||
|
@ -83,7 +91,7 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
||||||
n = 1
|
n = 1
|
||||||
}
|
}
|
||||||
c.Timeout = n
|
c.Timeout = n
|
||||||
case len(s) >= 8 && s[:9] == "attempts:":
|
case len(s) >= 9 && s[:9] == "attempts:":
|
||||||
n, _ := strconv.Atoi(s[9:])
|
n, _ := strconv.Atoi(s[9:])
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
n = 1
|
n = 1
|
||||||
|
@ -97,3 +105,35 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameList returns all of the names that should be queried based on the
|
||||||
|
// config. It is based off of go's net/dns name building, but it does not
|
||||||
|
// check the length of the resulting names.
|
||||||
|
func (c *ClientConfig) NameList(name string) []string {
|
||||||
|
// if this domain is already fully qualified, no append needed.
|
||||||
|
if IsFqdn(name) {
|
||||||
|
return []string{name}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the name has more labels than Ndots. Do this before making
|
||||||
|
// the domain fully qualified.
|
||||||
|
hasNdots := CountLabel(name) > c.Ndots
|
||||||
|
// Make the domain fully qualified.
|
||||||
|
name = Fqdn(name)
|
||||||
|
|
||||||
|
// Make a list of names based off search.
|
||||||
|
names := []string{}
|
||||||
|
|
||||||
|
// If name has enough dots, try that first.
|
||||||
|
if hasNdots {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
for _, s := range c.Search {
|
||||||
|
names = append(names, Fqdn(name+s))
|
||||||
|
}
|
||||||
|
// If we didn't have enough dots, try after suffixes.
|
||||||
|
if !hasNdots {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
188
vendor/github.com/miekg/dns/compress_generate.go
generated
vendored
Normal file
188
vendor/github.com/miekg/dns/compress_generate.go
generated
vendored
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
//+build ignore
|
||||||
|
|
||||||
|
// compression_generate.go is meant to run with go generate. It will use
|
||||||
|
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||||
|
// it will look to see if there are (compressible) names, if so it will add that
|
||||||
|
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
|
||||||
|
// compression so that Len() is fast.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"go/importer"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packageHdr = `
|
||||||
|
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
// getTypeStruct will take a type and the package scope, and return the
|
||||||
|
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||||
|
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||||
|
// the RR interface). The bool return value indicates if embedded structs were
|
||||||
|
// resolved.
|
||||||
|
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||||
|
st, ok := t.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||||
|
return st, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Anonymous() {
|
||||||
|
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||||
|
return st, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Import and type-check the package
|
||||||
|
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||||
|
fatalIfErr(err)
|
||||||
|
scope := pkg.Scope()
|
||||||
|
|
||||||
|
var domainTypes []string // Types that have a domain name in them (either compressible or not).
|
||||||
|
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
|
||||||
|
Names:
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
if o == nil || !o.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
if st == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if name == "PrivateRR" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||||
|
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
if st.Tag(i) == `dns:"domain-name"` {
|
||||||
|
domainTypes = append(domainTypes, o.Name())
|
||||||
|
continue Names
|
||||||
|
}
|
||||||
|
if st.Tag(i) == `dns:"cdomain-name"` {
|
||||||
|
cdomainTypes = append(cdomainTypes, o.Name())
|
||||||
|
domainTypes = append(domainTypes, o.Name())
|
||||||
|
continue Names
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case st.Tag(i) == `dns:"domain-name"`:
|
||||||
|
domainTypes = append(domainTypes, o.Name())
|
||||||
|
continue Names
|
||||||
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
|
cdomainTypes = append(cdomainTypes, o.Name())
|
||||||
|
domainTypes = append(domainTypes, o.Name())
|
||||||
|
continue Names
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
b.WriteString(packageHdr)
|
||||||
|
|
||||||
|
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
|
||||||
|
|
||||||
|
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
|
||||||
|
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||||
|
for _, name := range domainTypes {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
|
fmt.Fprintf(b, "case *%s:\n", name)
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
|
||||||
|
|
||||||
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
switch st.Tag(i) {
|
||||||
|
case `dns:"domain-name"`:
|
||||||
|
fallthrough
|
||||||
|
case `dns:"cdomain-name"`:
|
||||||
|
// For HIP we need to slice over the elements in this slice.
|
||||||
|
fmt.Fprintf(b, `for i := range x.%s {
|
||||||
|
compressionLenHelper(c, x.%s[i])
|
||||||
|
}
|
||||||
|
`, st.Field(i).Name(), st.Field(i).Name())
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
|
fallthrough
|
||||||
|
case st.Tag(i) == `dns:"domain-name"`:
|
||||||
|
out(st.Field(i).Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintln(b, "}\n}\n\n")
|
||||||
|
|
||||||
|
// compressionLenSearchType - search cdomain-tags types for compressible names.
|
||||||
|
|
||||||
|
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
|
||||||
|
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||||
|
for _, name := range cdomainTypes {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
|
fmt.Fprintf(b, "case *%s:\n", name)
|
||||||
|
j := 1
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
out := func(s string, j int) {
|
||||||
|
fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are no slice types with names that can be compressed.
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
|
out(st.Field(i).Name(), j)
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k := "k1"
|
||||||
|
ok := "ok1"
|
||||||
|
for i := 2; i < j; i++ {
|
||||||
|
k += fmt.Sprintf(" + k%d", i)
|
||||||
|
ok += fmt.Sprintf(" && ok%d", i)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "return %s, %s\n", k, ok)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
|
||||||
|
|
||||||
|
// gofmt
|
||||||
|
res, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b.WriteTo(os.Stderr)
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("zcompress.go")
|
||||||
|
fatalIfErr(err)
|
||||||
|
defer f.Close()
|
||||||
|
f.Write(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatalIfErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
14
vendor/github.com/miekg/dns/defaults.go
generated
vendored
14
vendor/github.com/miekg/dns/defaults.go
generated
vendored
|
@ -13,9 +13,12 @@ const hexDigit = "0123456789abcdef"
|
||||||
// SetReply creates a reply message from a request message.
|
// SetReply creates a reply message from a request message.
|
||||||
func (dns *Msg) SetReply(request *Msg) *Msg {
|
func (dns *Msg) SetReply(request *Msg) *Msg {
|
||||||
dns.Id = request.Id
|
dns.Id = request.Id
|
||||||
dns.RecursionDesired = request.RecursionDesired // Copy rd bit
|
|
||||||
dns.Response = true
|
dns.Response = true
|
||||||
dns.Opcode = OpcodeQuery
|
dns.Opcode = request.Opcode
|
||||||
|
if dns.Opcode == OpcodeQuery {
|
||||||
|
dns.RecursionDesired = request.RecursionDesired // Copy rd bit
|
||||||
|
dns.CheckingDisabled = request.CheckingDisabled // Copy cd bit
|
||||||
|
}
|
||||||
dns.Rcode = RcodeSuccess
|
dns.Rcode = RcodeSuccess
|
||||||
if len(request.Question) > 0 {
|
if len(request.Question) > 0 {
|
||||||
dns.Question = make([]Question, 1)
|
dns.Question = make([]Question, 1)
|
||||||
|
@ -270,8 +273,11 @@ 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 c1, ok := ClassToString[uint16(c)]; ok {
|
if s, ok := ClassToString[uint16(c)]; ok {
|
||||||
return c1
|
// Only emit mnemonics when they are unambiguous, specically ANY is in both.
|
||||||
|
if _, ok := StringToType[s]; !ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "CLASS" + strconv.Itoa(int(c))
|
return "CLASS" + strconv.Itoa(int(c))
|
||||||
}
|
}
|
||||||
|
|
9
vendor/github.com/miekg/dns/dns.go
generated
vendored
9
vendor/github.com/miekg/dns/dns.go
generated
vendored
|
@ -6,9 +6,12 @@ const (
|
||||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||||
defaultTtl = 3600 // Default internal TTL.
|
defaultTtl = 3600 // Default internal TTL.
|
||||||
|
|
||||||
DefaultMsgSize = 4096 // DefaultMsgSize is the standard default for messages larger than 512 bytes.
|
// DefaultMsgSize is the standard default for messages larger than 512 bytes.
|
||||||
MinMsgSize = 512 // MinMsgSize is the minimal size of a DNS packet.
|
DefaultMsgSize = 4096
|
||||||
MaxMsgSize = 65535 // MaxMsgSize is the largest possible DNS packet.
|
// MinMsgSize is the minimal size of a DNS packet.
|
||||||
|
MinMsgSize = 512
|
||||||
|
// MaxMsgSize is the largest possible DNS packet.
|
||||||
|
MaxMsgSize = 65535
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error represents a DNS error.
|
// Error represents a DNS error.
|
||||||
|
|
92
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
92
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
|
@ -19,6 +19,8 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSSEC encryption algorithm codes.
|
// DNSSEC encryption algorithm codes.
|
||||||
|
@ -38,12 +40,14 @@ const (
|
||||||
ECCGOST
|
ECCGOST
|
||||||
ECDSAP256SHA256
|
ECDSAP256SHA256
|
||||||
ECDSAP384SHA384
|
ECDSAP384SHA384
|
||||||
|
ED25519
|
||||||
|
ED448
|
||||||
INDIRECT uint8 = 252
|
INDIRECT uint8 = 252
|
||||||
PRIVATEDNS uint8 = 253 // Private (experimental keys)
|
PRIVATEDNS uint8 = 253 // Private (experimental keys)
|
||||||
PRIVATEOID uint8 = 254
|
PRIVATEOID uint8 = 254
|
||||||
)
|
)
|
||||||
|
|
||||||
// Map for algorithm names.
|
// AlgorithmToString is a map of algorithm IDs to algorithm names.
|
||||||
var AlgorithmToString = map[uint8]string{
|
var AlgorithmToString = map[uint8]string{
|
||||||
RSAMD5: "RSAMD5",
|
RSAMD5: "RSAMD5",
|
||||||
DH: "DH",
|
DH: "DH",
|
||||||
|
@ -56,15 +60,17 @@ var AlgorithmToString = map[uint8]string{
|
||||||
ECCGOST: "ECC-GOST",
|
ECCGOST: "ECC-GOST",
|
||||||
ECDSAP256SHA256: "ECDSAP256SHA256",
|
ECDSAP256SHA256: "ECDSAP256SHA256",
|
||||||
ECDSAP384SHA384: "ECDSAP384SHA384",
|
ECDSAP384SHA384: "ECDSAP384SHA384",
|
||||||
|
ED25519: "ED25519",
|
||||||
|
ED448: "ED448",
|
||||||
INDIRECT: "INDIRECT",
|
INDIRECT: "INDIRECT",
|
||||||
PRIVATEDNS: "PRIVATEDNS",
|
PRIVATEDNS: "PRIVATEDNS",
|
||||||
PRIVATEOID: "PRIVATEOID",
|
PRIVATEOID: "PRIVATEOID",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map of algorithm strings.
|
// StringToAlgorithm is the reverse of AlgorithmToString.
|
||||||
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
||||||
|
|
||||||
// Map of algorithm crypto hashes.
|
// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
|
||||||
var AlgorithmToHash = map[uint8]crypto.Hash{
|
var AlgorithmToHash = map[uint8]crypto.Hash{
|
||||||
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
||||||
RSASHA1: crypto.SHA1,
|
RSASHA1: crypto.SHA1,
|
||||||
|
@ -73,6 +79,7 @@ var AlgorithmToHash = map[uint8]crypto.Hash{
|
||||||
ECDSAP256SHA256: crypto.SHA256,
|
ECDSAP256SHA256: crypto.SHA256,
|
||||||
ECDSAP384SHA384: crypto.SHA384,
|
ECDSAP384SHA384: crypto.SHA384,
|
||||||
RSASHA512: crypto.SHA512,
|
RSASHA512: crypto.SHA512,
|
||||||
|
ED25519: crypto.Hash(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSSEC hashing algorithm codes.
|
// DNSSEC hashing algorithm codes.
|
||||||
|
@ -85,7 +92,7 @@ const (
|
||||||
SHA512 // Experimental
|
SHA512 // Experimental
|
||||||
)
|
)
|
||||||
|
|
||||||
// Map for hash names.
|
// HashToString is a map of hash IDs to names.
|
||||||
var HashToString = map[uint8]string{
|
var HashToString = map[uint8]string{
|
||||||
SHA1: "SHA1",
|
SHA1: "SHA1",
|
||||||
SHA256: "SHA256",
|
SHA256: "SHA256",
|
||||||
|
@ -94,7 +101,7 @@ var HashToString = map[uint8]string{
|
||||||
SHA512: "SHA512",
|
SHA512: "SHA512",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map of hash strings.
|
// StringToHash is a map of names to hash IDs.
|
||||||
var StringToHash = reverseInt8(HashToString)
|
var StringToHash = reverseInt8(HashToString)
|
||||||
|
|
||||||
// DNSKEY flag values.
|
// DNSKEY flag values.
|
||||||
|
@ -301,17 +308,33 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
||||||
return ErrAlg
|
return ErrAlg
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hash.New()
|
switch rr.Algorithm {
|
||||||
h.Write(signdata)
|
case ED25519:
|
||||||
h.Write(wire)
|
// ed25519 signs the raw message and performs hashing internally.
|
||||||
|
// All other supported signature schemes operate over the pre-hashed
|
||||||
|
// message, and thus ed25519 must be handled separately here.
|
||||||
|
//
|
||||||
|
// The raw message is passed directly into sign and crypto.Hash(0) is
|
||||||
|
// used to signal to the crypto.Signer that the data has not been hashed.
|
||||||
|
signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
rr.Signature = toBase64(signature)
|
||||||
if err != nil {
|
default:
|
||||||
return err
|
h := hash.New()
|
||||||
|
h.Write(signdata)
|
||||||
|
h.Write(wire)
|
||||||
|
|
||||||
|
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rr.Signature = toBase64(signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr.Signature = toBase64(signature)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +375,9 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
|
||||||
// signature = append(signature, intToBytes(r1, 20)...)
|
// signature = append(signature, intToBytes(r1, 20)...)
|
||||||
// signature = append(signature, intToBytes(s1, 20)...)
|
// signature = append(signature, intToBytes(s1, 20)...)
|
||||||
// rr.Signature = signature
|
// rr.Signature = signature
|
||||||
|
|
||||||
|
case ED25519:
|
||||||
|
return signature, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrAlg
|
return nil, ErrAlg
|
||||||
|
@ -456,6 +482,17 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||||
}
|
}
|
||||||
return ErrSig
|
return ErrSig
|
||||||
|
|
||||||
|
case ED25519:
|
||||||
|
pubkey := k.publicKeyED25519()
|
||||||
|
if pubkey == nil {
|
||||||
|
return ErrKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return ErrSig
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ErrAlg
|
return ErrAlg
|
||||||
}
|
}
|
||||||
|
@ -515,7 +552,7 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||||
}
|
}
|
||||||
// Remainder
|
// Remainder
|
||||||
expo += uint64(keybuf[keyoff])
|
expo += uint64(keybuf[keyoff])
|
||||||
if expo > 2<<31 {
|
if expo > (2<<31)+1 {
|
||||||
// Larger expo than supported.
|
// Larger expo than supported.
|
||||||
// println("dns: F5 primes (or larger) are not supported")
|
// println("dns: F5 primes (or larger) are not supported")
|
||||||
return nil
|
return nil
|
||||||
|
@ -578,6 +615,17 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
|
||||||
|
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(keybuf) != ed25519.PublicKeySize {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return keybuf
|
||||||
|
}
|
||||||
|
|
||||||
type wireSlice [][]byte
|
type wireSlice [][]byte
|
||||||
|
|
||||||
func (p wireSlice) Len() int { return len(p) }
|
func (p wireSlice) Len() int { return len(p) }
|
||||||
|
@ -615,6 +663,10 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
||||||
switch x := r1.(type) {
|
switch x := r1.(type) {
|
||||||
case *NS:
|
case *NS:
|
||||||
x.Ns = strings.ToLower(x.Ns)
|
x.Ns = strings.ToLower(x.Ns)
|
||||||
|
case *MD:
|
||||||
|
x.Md = strings.ToLower(x.Md)
|
||||||
|
case *MF:
|
||||||
|
x.Mf = strings.ToLower(x.Mf)
|
||||||
case *CNAME:
|
case *CNAME:
|
||||||
x.Target = strings.ToLower(x.Target)
|
x.Target = strings.ToLower(x.Target)
|
||||||
case *SOA:
|
case *SOA:
|
||||||
|
@ -633,6 +685,18 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
||||||
x.Email = strings.ToLower(x.Email)
|
x.Email = strings.ToLower(x.Email)
|
||||||
case *MX:
|
case *MX:
|
||||||
x.Mx = strings.ToLower(x.Mx)
|
x.Mx = strings.ToLower(x.Mx)
|
||||||
|
case *RP:
|
||||||
|
x.Mbox = strings.ToLower(x.Mbox)
|
||||||
|
x.Txt = strings.ToLower(x.Txt)
|
||||||
|
case *AFSDB:
|
||||||
|
x.Hostname = strings.ToLower(x.Hostname)
|
||||||
|
case *RT:
|
||||||
|
x.Host = strings.ToLower(x.Host)
|
||||||
|
case *SIG:
|
||||||
|
x.SignerName = strings.ToLower(x.SignerName)
|
||||||
|
case *PX:
|
||||||
|
x.Map822 = strings.ToLower(x.Map822)
|
||||||
|
x.Mapx400 = strings.ToLower(x.Mapx400)
|
||||||
case *NAPTR:
|
case *NAPTR:
|
||||||
x.Replacement = strings.ToLower(x.Replacement)
|
x.Replacement = strings.ToLower(x.Replacement)
|
||||||
case *KX:
|
case *KX:
|
||||||
|
|
22
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
22
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
|
@ -8,6 +8,8 @@ import (
|
||||||
"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.
|
||||||
|
@ -38,6 +40,10 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
||||||
if bits != 384 {
|
if bits != 384 {
|
||||||
return nil, ErrKeySize
|
return nil, ErrKeySize
|
||||||
}
|
}
|
||||||
|
case ED25519:
|
||||||
|
if bits != 256 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch k.Algorithm {
|
switch k.Algorithm {
|
||||||
|
@ -75,6 +81,13 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
||||||
}
|
}
|
||||||
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
|
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
|
||||||
return priv, nil
|
return priv, nil
|
||||||
|
case ED25519:
|
||||||
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
k.setPublicKeyED25519(pub)
|
||||||
|
return priv, nil
|
||||||
default:
|
default:
|
||||||
return nil, ErrAlg
|
return nil, ErrAlg
|
||||||
}
|
}
|
||||||
|
@ -117,6 +130,15 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the public key for Ed25519
|
||||||
|
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
|
||||||
|
if _K == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
k.PublicKey = toBase64(_K)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Set the public key (the values E and N) for RSA
|
// Set the public key (the values E and N) for RSA
|
||||||
// RFC 3110: Section 2. RSA Public KEY Resource Records
|
// RFC 3110: Section 2. RSA Public KEY Resource Records
|
||||||
func exponentToBuf(_E int) []byte {
|
func exponentToBuf(_E int) []byte {
|
||||||
|
|
52
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
52
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
@ -9,6 +10,8 @@ import (
|
||||||
"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.
|
||||||
|
@ -36,7 +39,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
// TODO(mg): check if the pubkey matches the private key
|
// TODO(mg): check if the pubkey matches the private key
|
||||||
algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
|
algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
|
@ -86,6 +89,8 @@ 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 ED25519:
|
||||||
|
return readPrivateKeyED25519(m)
|
||||||
default:
|
default:
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
|
@ -166,13 +171,56 @@ func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
|
||||||
|
var p ed25519.PrivateKey
|
||||||
|
// TODO: validate that the required flags are present
|
||||||
|
for k, v := range m {
|
||||||
|
switch k {
|
||||||
|
case "privatekey":
|
||||||
|
p1, err := fromBase64([]byte(v))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(p1) != 32 {
|
||||||
|
return nil, ErrPrivKey
|
||||||
|
}
|
||||||
|
// RFC 8080 and Golang's x/crypto/ed25519 differ as to how the
|
||||||
|
// private keys are represented. RFC 8080 specifies that private
|
||||||
|
// keys be stored solely as the seed value (p1 above) while the
|
||||||
|
// ed25519 package represents them as the seed value concatenated
|
||||||
|
// to the public key, which is derived from the seed value.
|
||||||
|
//
|
||||||
|
// ed25519.GenerateKey reads exactly 32 bytes from the passed in
|
||||||
|
// io.Reader and uses them as the seed. It also derives the
|
||||||
|
// public key and produces a compatible private key.
|
||||||
|
_, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case "created", "publish", "activate":
|
||||||
|
/* not used in Go (yet) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
// parseKey reads a private key from r. It returns a map[string]string,
|
// parseKey reads a private key from r. It returns a map[string]string,
|
||||||
// with the key-value pairs, or an error when the file is not correct.
|
// with the key-value pairs, or an error when the file is not correct.
|
||||||
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||||
s := scanInit(r)
|
s, cancel := scanInit(r)
|
||||||
m := make(map[string]string)
|
m := make(map[string]string)
|
||||||
c := make(chan lex)
|
c := make(chan lex)
|
||||||
k := ""
|
k := ""
|
||||||
|
defer func() {
|
||||||
|
cancel()
|
||||||
|
// zlexer can send up to two tokens, the next one and possibly 1 remainders.
|
||||||
|
// Do a non-blocking read.
|
||||||
|
_, ok := <-c
|
||||||
|
_, ok = <-c
|
||||||
|
if !ok {
|
||||||
|
// too bad
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Start the lexer
|
// Start the lexer
|
||||||
go klexer(s, c)
|
go klexer(s, c)
|
||||||
for l := range c {
|
for l := range c {
|
||||||
|
|
8
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
8
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
|
@ -7,6 +7,8 @@ import (
|
||||||
"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"
|
||||||
|
@ -79,6 +81,12 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
||||||
"Private_value(x): " + priv + "\n" +
|
"Private_value(x): " + priv + "\n" +
|
||||||
"Public_value(y): " + pub + "\n"
|
"Public_value(y): " + pub + "\n"
|
||||||
|
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
private := toBase64(p[:32])
|
||||||
|
return format +
|
||||||
|
"Algorithm: " + algorithm + "\n" +
|
||||||
|
"PrivateKey: " + private + "\n"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
35
vendor/github.com/miekg/dns/doc.go
generated
vendored
35
vendor/github.com/miekg/dns/doc.go
generated
vendored
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Package dns implements a full featured interface to the Domain Name System.
|
Package dns implements a full featured interface to the Domain Name System.
|
||||||
Server- and client-side programming is supported.
|
Server- and client-side programming is supported.
|
||||||
The package allows complete control over what is send out to the DNS. The package
|
The package allows complete control over what is sent out to the DNS. The package
|
||||||
API follows the less-is-more principle, by presenting a small, clean interface.
|
API follows the less-is-more principle, by presenting a small, clean interface.
|
||||||
|
|
||||||
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
||||||
|
@ -14,7 +14,7 @@ Basic usage pattern for creating a new resource record:
|
||||||
|
|
||||||
r := new(dns.MX)
|
r := new(dns.MX)
|
||||||
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
||||||
Class: dns.ClassINET, Ttl: 3600}
|
Class: dns.ClassINET, Ttl: 3600}
|
||||||
r.Preference = 10
|
r.Preference = 10
|
||||||
r.Mx = "mx.miek.nl."
|
r.Mx = "mx.miek.nl."
|
||||||
|
|
||||||
|
@ -22,16 +22,16 @@ Or directly from a string:
|
||||||
|
|
||||||
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
||||||
|
|
||||||
Or when the default TTL (3600) and class (IN) suit you:
|
Or when the default origin (.) and TTL (3600) and class (IN) suit you:
|
||||||
|
|
||||||
mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
|
mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
|
||||||
|
|
||||||
Or even:
|
Or even:
|
||||||
|
|
||||||
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
||||||
|
|
||||||
In the DNS messages are exchanged, these messages contain resource
|
In the DNS messages are exchanged, these messages contain resource
|
||||||
records (sets). Use pattern for creating a message:
|
records (sets). Use pattern for creating a message:
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion("miek.nl.", dns.TypeMX)
|
m.SetQuestion("miek.nl.", dns.TypeMX)
|
||||||
|
@ -51,7 +51,7 @@ The following is slightly more verbose, but more flexible:
|
||||||
m1.Question = make([]dns.Question, 1)
|
m1.Question = make([]dns.Question, 1)
|
||||||
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
||||||
|
|
||||||
After creating a message it can be send.
|
After creating a message it can be sent.
|
||||||
Basic use pattern for synchronous querying the DNS at a
|
Basic use pattern for synchronous querying the DNS at a
|
||||||
server configured on 127.0.0.1 and port 53:
|
server configured on 127.0.0.1 and port 53:
|
||||||
|
|
||||||
|
@ -63,7 +63,23 @@ class) is as easy as setting:
|
||||||
|
|
||||||
c.SingleInflight = true
|
c.SingleInflight = true
|
||||||
|
|
||||||
If these "advanced" features are not needed, a simple UDP query can be send,
|
More advanced options are available using a net.Dialer and the corresponding API.
|
||||||
|
For example it is possible to set a timeout, or to specify a source IP address
|
||||||
|
and port to use for the connection:
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
laddr := net.UDPAddr{
|
||||||
|
IP: net.ParseIP("[::1]"),
|
||||||
|
Port: 12345,
|
||||||
|
Zone: "",
|
||||||
|
}
|
||||||
|
d := net.Dialer{
|
||||||
|
Timeout: 200 * time.Millisecond,
|
||||||
|
LocalAddr: &laddr,
|
||||||
|
}
|
||||||
|
in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")
|
||||||
|
|
||||||
|
If these "advanced" features are not needed, a simple UDP query can be sent,
|
||||||
with:
|
with:
|
||||||
|
|
||||||
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
||||||
|
@ -152,6 +168,11 @@ Basic use pattern when querying with a TSIG name "axfr." (note that these key na
|
||||||
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
|
||||||
"so6ZGir4GPAqINNh9U5c3A==":
|
"so6ZGir4GPAqINNh9U5c3A==":
|
||||||
|
|
||||||
|
If an incoming message contains a TSIG record it MUST be the last record in
|
||||||
|
the additional section (RFC2845 3.2). This means that you should make the
|
||||||
|
call to SetTsig last, right before executing the query. If you make any
|
||||||
|
changes to the RRset after calling SetTsig() the signature will be incorrect.
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
|
98
vendor/github.com/miekg/dns/edns.go
generated
vendored
98
vendor/github.com/miekg/dns/edns.go
generated
vendored
|
@ -13,18 +13,18 @@ import (
|
||||||
const (
|
const (
|
||||||
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
||||||
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
||||||
EDNS0NSID = 0x3 // nsid (RFC5001)
|
EDNS0NSID = 0x3 // nsid (See RFC 5001)
|
||||||
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
|
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
|
||||||
EDNS0DHU = 0x6 // DS Hash Understood
|
EDNS0DHU = 0x6 // DS Hash Understood
|
||||||
EDNS0N3U = 0x7 // NSEC3 Hash Understood
|
EDNS0N3U = 0x7 // NSEC3 Hash Understood
|
||||||
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
|
EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
|
||||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||||
EDNS0COOKIE = 0xa // EDNS0 Cookie
|
EDNS0COOKIE = 0xa // EDNS0 Cookie
|
||||||
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
|
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
|
||||||
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
|
||||||
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
|
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
|
||||||
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
|
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
|
||||||
_DO = 1 << 15 // dnssec ok
|
_DO = 1 << 15 // DNSSEC OK
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -57,9 +57,6 @@ func (rr *OPT) String() string {
|
||||||
}
|
}
|
||||||
case *EDNS0_SUBNET:
|
case *EDNS0_SUBNET:
|
||||||
s += "\n; SUBNET: " + o.String()
|
s += "\n; SUBNET: " + o.String()
|
||||||
if o.(*EDNS0_SUBNET).DraftOption {
|
|
||||||
s += " (draft)"
|
|
||||||
}
|
|
||||||
case *EDNS0_COOKIE:
|
case *EDNS0_COOKIE:
|
||||||
s += "\n; COOKIE: " + o.String()
|
s += "\n; COOKIE: " + o.String()
|
||||||
case *EDNS0_UL:
|
case *EDNS0_UL:
|
||||||
|
@ -74,6 +71,8 @@ func (rr *OPT) String() string {
|
||||||
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
||||||
case *EDNS0_LOCAL:
|
case *EDNS0_LOCAL:
|
||||||
s += "\n; LOCAL OPT: " + o.String()
|
s += "\n; LOCAL OPT: " + o.String()
|
||||||
|
case *EDNS0_PADDING:
|
||||||
|
s += "\n; PADDING: " + o.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
@ -103,15 +102,12 @@ func (rr *OPT) SetVersion(v uint8) {
|
||||||
|
|
||||||
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
||||||
func (rr *OPT) ExtendedRcode() int {
|
func (rr *OPT) ExtendedRcode() int {
|
||||||
return int((rr.Hdr.Ttl&0xFF000000)>>24) + 15
|
return int((rr.Hdr.Ttl & 0xFF000000) >> 24)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetExtendedRcode sets the EDNS extended RCODE field.
|
// SetExtendedRcode sets the EDNS extended RCODE field.
|
||||||
func (rr *OPT) SetExtendedRcode(v uint8) {
|
func (rr *OPT) SetExtendedRcode(v uint8) {
|
||||||
if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
|
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24)
|
||||||
return
|
|
||||||
}
|
|
||||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v-15) << 24)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDPSize returns the UDP buffer size.
|
// UDPSize returns the UDP buffer size.
|
||||||
|
@ -157,7 +153,7 @@ type EDNS0 interface {
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// The nsid EDNS0 option is used to retrieve a nameserver
|
// EDNS0_NSID option is used to retrieve a nameserver
|
||||||
// identifier. When sending a request Nsid must be set to the empty string
|
// identifier. When sending a request Nsid must be set to the empty string
|
||||||
// The identifier is an opaque string encoded as hex.
|
// The identifier is an opaque string encoded as hex.
|
||||||
// Basic use pattern for creating an nsid option:
|
// Basic use pattern for creating an nsid option:
|
||||||
|
@ -182,12 +178,13 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID }
|
// Option implements the EDNS0 interface.
|
||||||
|
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
|
||||||
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
||||||
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
func (e *EDNS0_NSID) String() string { return string(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. It can then give back a different
|
// an idea of where the client lives. See RFC 7871. It can then give back a different
|
||||||
// answer depending on the location or network topology.
|
// answer depending on the location or network topology.
|
||||||
// Basic use pattern for creating an subnet option:
|
// Basic use pattern for creating an subnet option:
|
||||||
//
|
//
|
||||||
|
@ -197,31 +194,25 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
||||||
// e := new(dns.EDNS0_SUBNET)
|
// e := new(dns.EDNS0_SUBNET)
|
||||||
// e.Code = dns.EDNS0SUBNET
|
// e.Code = dns.EDNS0SUBNET
|
||||||
// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
|
// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
|
||||||
// e.SourceNetMask = 32 // 32 for IPV4, 128 for IPv6
|
// e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
|
||||||
// e.SourceScope = 0
|
// e.SourceScope = 0
|
||||||
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
|
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
|
||||||
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
|
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
|
||||||
// o.Option = append(o.Option, e)
|
// o.Option = append(o.Option, e)
|
||||||
//
|
//
|
||||||
// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
|
// This code will parse all the available bits when unpacking (up to optlen).
|
||||||
// for which netmask applies to the address. This code will parse all the
|
// When packing it will apply SourceNetmask. If you need more advanced logic,
|
||||||
// available bits when unpacking (up to optlen). When packing it will apply
|
// patches welcome and good luck.
|
||||||
// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
|
|
||||||
type EDNS0_SUBNET struct {
|
type EDNS0_SUBNET struct {
|
||||||
Code uint16 // Always EDNS0SUBNET
|
Code uint16 // Always EDNS0SUBNET
|
||||||
Family uint16 // 1 for IP, 2 for IP6
|
Family uint16 // 1 for IP, 2 for IP6
|
||||||
SourceNetmask uint8
|
SourceNetmask uint8
|
||||||
SourceScope uint8
|
SourceScope uint8
|
||||||
Address net.IP
|
Address net.IP
|
||||||
DraftOption bool // Set to true if using the old (0x50fa) option code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_SUBNET) Option() uint16 {
|
// Option implements the EDNS0 interface.
|
||||||
if e.DraftOption {
|
func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
|
||||||
return EDNS0SUBNETDRAFT
|
|
||||||
}
|
|
||||||
return EDNS0SUBNET
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
|
@ -229,6 +220,12 @@ func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
||||||
b[2] = e.SourceNetmask
|
b[2] = e.SourceNetmask
|
||||||
b[3] = e.SourceScope
|
b[3] = e.SourceScope
|
||||||
switch e.Family {
|
switch e.Family {
|
||||||
|
case 0:
|
||||||
|
// "dig" sets AddressFamily to 0 if SourceNetmask is also 0
|
||||||
|
// We might don't need to complain either
|
||||||
|
if e.SourceNetmask != 0 {
|
||||||
|
return nil, errors.New("dns: bad address family")
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
if e.SourceNetmask > net.IPv4len*8 {
|
if e.SourceNetmask > net.IPv4len*8 {
|
||||||
return nil, errors.New("dns: bad netmask")
|
return nil, errors.New("dns: bad netmask")
|
||||||
|
@ -263,6 +260,13 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
||||||
e.SourceNetmask = b[2]
|
e.SourceNetmask = b[2]
|
||||||
e.SourceScope = b[3]
|
e.SourceScope = b[3]
|
||||||
switch e.Family {
|
switch e.Family {
|
||||||
|
case 0:
|
||||||
|
// "dig" sets AddressFamily to 0 if SourceNetmask is also 0
|
||||||
|
// It's okay to accept such a packet
|
||||||
|
if e.SourceNetmask != 0 {
|
||||||
|
return errors.New("dns: bad address family")
|
||||||
|
}
|
||||||
|
e.Address = net.IPv4(0, 0, 0, 0)
|
||||||
case 1:
|
case 1:
|
||||||
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||||
return errors.New("dns: bad netmask")
|
return errors.New("dns: bad netmask")
|
||||||
|
@ -301,7 +305,7 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Cookie EDNS0 option
|
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
|
||||||
//
|
//
|
||||||
// o := new(dns.OPT)
|
// o := new(dns.OPT)
|
||||||
// o.Hdr.Name = "."
|
// o.Hdr.Name = "."
|
||||||
|
@ -332,6 +336,7 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
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 }
|
||||||
|
@ -353,6 +358,7 @@ type EDNS0_UL struct {
|
||||||
Lease uint32
|
Lease uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
||||||
func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
|
func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
|
||||||
|
|
||||||
|
@ -382,6 +388,7 @@ type EDNS0_LLQ struct {
|
||||||
LeaseLife uint32
|
LeaseLife uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
|
func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
|
||||||
|
|
||||||
func (e *EDNS0_LLQ) pack() ([]byte, error) {
|
func (e *EDNS0_LLQ) pack() ([]byte, error) {
|
||||||
|
@ -413,11 +420,13 @@ func (e *EDNS0_LLQ) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
|
||||||
type EDNS0_DAU struct {
|
type EDNS0_DAU struct {
|
||||||
Code uint16 // Always EDNS0DAU
|
Code uint16 // Always EDNS0DAU
|
||||||
AlgCode []uint8
|
AlgCode []uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
|
func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
|
||||||
func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
|
func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||||
func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||||
|
@ -434,11 +443,13 @@ func (e *EDNS0_DAU) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_DHU struct {
|
type EDNS0_DHU struct {
|
||||||
Code uint16 // Always EDNS0DHU
|
Code uint16 // Always EDNS0DHU
|
||||||
AlgCode []uint8
|
AlgCode []uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
|
func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
|
||||||
func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
|
func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||||
func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||||
|
@ -455,11 +466,13 @@ func (e *EDNS0_DHU) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_N3U struct {
|
type EDNS0_N3U struct {
|
||||||
Code uint16 // Always EDNS0N3U
|
Code uint16 // Always EDNS0N3U
|
||||||
AlgCode []uint8
|
AlgCode []uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
|
func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
|
||||||
func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
|
func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||||
func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
|
func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||||
|
@ -477,11 +490,13 @@ func (e *EDNS0_N3U) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
|
||||||
type EDNS0_EXPIRE struct {
|
type EDNS0_EXPIRE struct {
|
||||||
Code uint16 // Always EDNS0EXPIRE
|
Code uint16 // Always EDNS0EXPIRE
|
||||||
Expire uint32
|
Expire uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) }
|
||||||
|
|
||||||
|
@ -520,6 +535,7 @@ type EDNS0_LOCAL struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
|
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)
|
||||||
|
@ -543,15 +559,16 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
|
||||||
|
// the TCP connection alive. See RFC 7828.
|
||||||
type EDNS0_TCP_KEEPALIVE struct {
|
type EDNS0_TCP_KEEPALIVE struct {
|
||||||
Code uint16 // Always EDNSTCPKEEPALIVE
|
Code uint16 // Always EDNSTCPKEEPALIVE
|
||||||
Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
|
Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
|
||||||
Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
|
Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 {
|
// Option implements the EDNS0 interface.
|
||||||
return EDNS0TCPKEEPALIVE
|
func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
|
func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
|
||||||
if e.Timeout != 0 && e.Length != 2 {
|
if e.Timeout != 0 && e.Length != 2 {
|
||||||
|
@ -595,3 +612,16 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
||||||
|
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
||||||
|
// compression is applied before encryption which may break signatures.
|
||||||
|
type EDNS0_PADDING struct {
|
||||||
|
Padding []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option implements the EDNS0 interface.
|
||||||
|
func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
|
||||||
|
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) String() string { return fmt.Sprintf("%0X", e.Padding) }
|
||||||
|
|
23
vendor/github.com/miekg/dns/fuzz.go
generated
vendored
Normal file
23
vendor/github.com/miekg/dns/fuzz.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// +build fuzz
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
func Fuzz(data []byte) int {
|
||||||
|
msg := new(Msg)
|
||||||
|
|
||||||
|
if err := msg.Unpack(data); err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if _, err := msg.Pack(); err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzNewRR(data []byte) int {
|
||||||
|
if _, err := NewRR(string(data)); err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
43
vendor/github.com/miekg/dns/labels.go
generated
vendored
43
vendor/github.com/miekg/dns/labels.go
generated
vendored
|
@ -42,7 +42,7 @@ func SplitDomainName(s string) (labels []string) {
|
||||||
|
|
||||||
// CompareDomainName compares the names s1 and s2 and
|
// CompareDomainName compares the names s1 and s2 and
|
||||||
// returns how many labels they have in common starting from the *right*.
|
// returns how many labels they have in common starting from the *right*.
|
||||||
// The comparison stops at the first inequality. The names are not downcased
|
// The comparison stops at the first inequality. The names are downcased
|
||||||
// before the comparison.
|
// before the comparison.
|
||||||
//
|
//
|
||||||
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
||||||
|
@ -50,23 +50,21 @@ func SplitDomainName(s string) (labels []string) {
|
||||||
//
|
//
|
||||||
// s1 and s2 must be syntactically valid domain names.
|
// s1 and s2 must be syntactically valid domain names.
|
||||||
func CompareDomainName(s1, s2 string) (n int) {
|
func CompareDomainName(s1, s2 string) (n int) {
|
||||||
s1 = Fqdn(s1)
|
// the first check: root label
|
||||||
s2 = Fqdn(s2)
|
if s1 == "." || s2 == "." {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
l1 := Split(s1)
|
l1 := Split(s1)
|
||||||
l2 := Split(s2)
|
l2 := Split(s2)
|
||||||
|
|
||||||
// the first check: root label
|
|
||||||
if l1 == nil || l2 == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
j1 := len(l1) - 1 // end
|
j1 := len(l1) - 1 // end
|
||||||
i1 := len(l1) - 2 // start
|
i1 := len(l1) - 2 // start
|
||||||
j2 := len(l2) - 1
|
j2 := len(l2) - 1
|
||||||
i2 := len(l2) - 2
|
i2 := len(l2) - 2
|
||||||
// the second check can be done here: last/only label
|
// the second check can be done here: last/only label
|
||||||
// before we fall through into the for-loop below
|
// before we fall through into the for-loop below
|
||||||
if s1[l1[j1]:] == s2[l2[j2]:] {
|
if equal(s1[l1[j1]:], s2[l2[j2]:]) {
|
||||||
n++
|
n++
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
|
@ -75,7 +73,7 @@ func CompareDomainName(s1, s2 string) (n int) {
|
||||||
if i1 < 0 || i2 < 0 {
|
if i1 < 0 || i2 < 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
|
if equal(s1[l1[i1]:l1[j1]], s2[l2[i2]:l2[j2]]) {
|
||||||
n++
|
n++
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
@ -166,3 +164,28 @@ func PrevLabel(s string, n int) (i int, start bool) {
|
||||||
}
|
}
|
||||||
return lab[len(lab)-n], false
|
return lab[len(lab)-n], false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// equal compares a and b while ignoring case. It returns true when equal otherwise false.
|
||||||
|
func equal(a, b string) bool {
|
||||||
|
// might be lifted into API function.
|
||||||
|
la := len(a)
|
||||||
|
lb := len(b)
|
||||||
|
if la != lb {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := la - 1; i >= 0; i-- {
|
||||||
|
ai := a[i]
|
||||||
|
bi := b[i]
|
||||||
|
if ai >= 'A' && ai <= 'Z' {
|
||||||
|
ai |= ('a' - 'A')
|
||||||
|
}
|
||||||
|
if bi >= 'A' && bi <= 'Z' {
|
||||||
|
bi |= ('a' - 'A')
|
||||||
|
}
|
||||||
|
if ai != bi {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
306
vendor/github.com/miekg/dns/msg.go
generated
vendored
306
vendor/github.com/miekg/dns/msg.go
generated
vendored
|
@ -9,42 +9,36 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
//go:generate go run msg_generate.go
|
//go:generate go run msg_generate.go
|
||||||
|
//go:generate go run compress_generate.go
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
const (
|
||||||
// Initialize default math/rand source using crypto/rand to provide better
|
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||||
// security without the performance trade-off.
|
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
|
||||||
buf := make([]byte, 8)
|
)
|
||||||
_, err := crand.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
// Failed to read from cryptographic source, fallback to default initial
|
|
||||||
// seed (1) by returning early
|
|
||||||
return
|
|
||||||
}
|
|
||||||
seed := binary.BigEndian.Uint64(buf)
|
|
||||||
rand.Seed(int64(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
|
||||||
|
|
||||||
|
// Errors defined in this package.
|
||||||
var (
|
var (
|
||||||
ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm.
|
ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm.
|
||||||
ErrAuth error = &Error{err: "bad authentication"} // ErrAuth indicates an error in the TSIG authentication.
|
ErrAuth error = &Error{err: "bad authentication"} // ErrAuth indicates an error in the TSIG authentication.
|
||||||
ErrBuf error = &Error{err: "buffer size too small"} // ErrBuf indicates that the buffer used it too small for the message.
|
ErrBuf error = &Error{err: "buffer size too small"} // ErrBuf indicates that the buffer used is too small for the message.
|
||||||
ErrConnEmpty error = &Error{err: "conn has no connection"} // ErrConnEmpty indicates a connection is being uses before it is initialized.
|
ErrConnEmpty error = &Error{err: "conn has no connection"} // ErrConnEmpty indicates a connection is being used before it is initialized.
|
||||||
ErrExtendedRcode error = &Error{err: "bad extended rcode"} // ErrExtendedRcode ...
|
ErrExtendedRcode error = &Error{err: "bad extended rcode"} // ErrExtendedRcode ...
|
||||||
ErrFqdn error = &Error{err: "domain must be fully qualified"} // ErrFqdn indicates that a domain name does not have a closing dot.
|
ErrFqdn error = &Error{err: "domain must be fully qualified"} // ErrFqdn indicates that a domain name does not have a closing dot.
|
||||||
ErrId error = &Error{err: "id mismatch"} // ErrId indicates there is a mismatch with the message's ID.
|
ErrId error = &Error{err: "id mismatch"} // ErrId indicates there is a mismatch with the message's ID.
|
||||||
ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
|
ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
|
||||||
ErrKey error = &Error{err: "bad key"}
|
ErrKey error = &Error{err: "bad key"}
|
||||||
ErrKeySize error = &Error{err: "bad key size"}
|
ErrKeySize error = &Error{err: "bad key size"}
|
||||||
|
ErrLongDomain error = &Error{err: fmt.Sprintf("domain name exceeded %d wire-format octets", maxDomainNameWireOctets)}
|
||||||
ErrNoSig error = &Error{err: "no signature found"}
|
ErrNoSig error = &Error{err: "no signature found"}
|
||||||
ErrPrivKey error = &Error{err: "bad private key"}
|
ErrPrivKey error = &Error{err: "bad private key"}
|
||||||
ErrRcode error = &Error{err: "bad rcode"}
|
ErrRcode error = &Error{err: "bad rcode"}
|
||||||
|
@ -64,13 +58,47 @@ var (
|
||||||
// For instance, to make it return a static value:
|
// For instance, to make it return a static value:
|
||||||
//
|
//
|
||||||
// dns.Id = func() uint16 { return 3 }
|
// dns.Id = func() uint16 { return 3 }
|
||||||
var Id func() uint16 = 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 {
|
||||||
id32 := rand.Uint32()
|
idLock.Lock()
|
||||||
return uint16(id32)
|
|
||||||
|
if idRand == nil {
|
||||||
|
// This (partially) works around
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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).
|
||||||
|
@ -241,7 +269,9 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
||||||
bsFresh = true
|
bsFresh = true
|
||||||
}
|
}
|
||||||
// Don't try to compress '.'
|
// Don't try to compress '.'
|
||||||
if compress && roBs[begin:] != "." {
|
// We should only compress when compress it true, but we should also still pick
|
||||||
|
// up names that can be used for *future* compression(s).
|
||||||
|
if compression != nil && roBs[begin:] != "." {
|
||||||
if p, ok := compression[roBs[begin:]]; !ok {
|
if p, ok := compression[roBs[begin:]]; !ok {
|
||||||
// Only offsets smaller than this can be used.
|
// Only offsets smaller than this can be used.
|
||||||
if offset < maxCompressionOffset {
|
if offset < maxCompressionOffset {
|
||||||
|
@ -305,6 +335,7 @@ func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
||||||
s := make([]byte, 0, 64)
|
s := make([]byte, 0, 64)
|
||||||
off1 := 0
|
off1 := 0
|
||||||
lenmsg := len(msg)
|
lenmsg := len(msg)
|
||||||
|
maxLen := maxDomainNameWireOctets
|
||||||
ptr := 0 // number of pointers followed
|
ptr := 0 // number of pointers followed
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
|
@ -329,8 +360,10 @@ Loop:
|
||||||
fallthrough
|
fallthrough
|
||||||
case '"', '\\':
|
case '"', '\\':
|
||||||
s = append(s, '\\', b)
|
s = append(s, '\\', b)
|
||||||
|
// presentation-format \X escapes add an extra byte
|
||||||
|
maxLen++
|
||||||
default:
|
default:
|
||||||
if b < 32 || b >= 127 { // unprintable use \DDD
|
if b < 32 || b >= 127 { // unprintable, use \DDD
|
||||||
var buf [3]byte
|
var buf [3]byte
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
||||||
s = append(s, '\\')
|
s = append(s, '\\')
|
||||||
|
@ -340,6 +373,8 @@ Loop:
|
||||||
for _, r := range bufs {
|
for _, r := range bufs {
|
||||||
s = append(s, r)
|
s = append(s, r)
|
||||||
}
|
}
|
||||||
|
// presentation-format \DDD escapes add 3 extra bytes
|
||||||
|
maxLen += 3
|
||||||
} else {
|
} else {
|
||||||
s = append(s, b)
|
s = append(s, b)
|
||||||
}
|
}
|
||||||
|
@ -364,6 +399,9 @@ Loop:
|
||||||
if ptr++; ptr > 10 {
|
if ptr++; ptr > 10 {
|
||||||
return "", lenmsg, &Error{err: "too many compression pointers"}
|
return "", lenmsg, &Error{err: "too many compression pointers"}
|
||||||
}
|
}
|
||||||
|
// pointer should guarantee that it advances and points forwards at least
|
||||||
|
// but the condition on previous three lines guarantees that it's
|
||||||
|
// at least loop-free
|
||||||
off = (c^0xC0)<<8 | int(c1)
|
off = (c^0xC0)<<8 | int(c1)
|
||||||
default:
|
default:
|
||||||
// 0x80 and 0x40 are reserved
|
// 0x80 and 0x40 are reserved
|
||||||
|
@ -375,6 +413,9 @@ Loop:
|
||||||
}
|
}
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
s = []byte(".")
|
s = []byte(".")
|
||||||
|
} else if len(s) >= maxLen {
|
||||||
|
// error if the name is too long, but don't throw it away
|
||||||
|
return string(s), lenmsg, ErrLongDomain
|
||||||
}
|
}
|
||||||
return string(s), off1, nil
|
return string(s), off1, nil
|
||||||
}
|
}
|
||||||
|
@ -571,8 +612,8 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
||||||
// If we cannot unpack the whole array, then it will return nil
|
// If we cannot unpack the whole array, then it will return nil
|
||||||
func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
|
func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
|
||||||
var r RR
|
var r RR
|
||||||
// Optimistically make dst be the length that was sent
|
// Don't pre-allocate, l may be under attacker control
|
||||||
dst := make([]RR, 0, l)
|
var dst []RR
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
off1 := off
|
off1 := off
|
||||||
r, off, err = UnpackRR(msg, off)
|
r, off, err = UnpackRR(msg, off)
|
||||||
|
@ -710,12 +751,10 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
||||||
|
|
||||||
// We need the uncompressed length here, because we first pack it and then compress it.
|
// We need the uncompressed length here, because we first pack it and then compress it.
|
||||||
msg = buf
|
msg = buf
|
||||||
compress := dns.Compress
|
uncompressedLen := compressedLen(dns, false)
|
||||||
dns.Compress = false
|
if packLen := uncompressedLen + 1; len(msg) < packLen {
|
||||||
if packLen := dns.Len() + 1; len(msg) < packLen {
|
|
||||||
msg = make([]byte, packLen)
|
msg = make([]byte, packLen)
|
||||||
}
|
}
|
||||||
dns.Compress = compress
|
|
||||||
|
|
||||||
// Pack it in: header and then the pieces.
|
// Pack it in: header and then the pieces.
|
||||||
off := 0
|
off := 0
|
||||||
|
@ -772,13 +811,19 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
||||||
dns.CheckingDisabled = (dh.Bits & _CD) != 0
|
dns.CheckingDisabled = (dh.Bits & _CD) != 0
|
||||||
dns.Rcode = int(dh.Bits & 0xF)
|
dns.Rcode = int(dh.Bits & 0xF)
|
||||||
|
|
||||||
|
// If we are at the end of the message we should return *just* the
|
||||||
|
// header. This can still be useful to the caller. 9.9.9.9 sends these
|
||||||
|
// when responding with REFUSED for instance.
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return ErrTruncated
|
// reset sections before returning
|
||||||
|
dns.Question, dns.Answer, dns.Ns, dns.Extra = nil, nil, nil, nil
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimistically use the count given to us in the header
|
// Qdcount, Ancount, Nscount, Arcount can't be trusted, as they are
|
||||||
dns.Question = make([]Question, 0, int(dh.Qdcount))
|
// attacker controlled. This means we can't use them to pre-allocate
|
||||||
|
// slices.
|
||||||
|
dns.Question = nil
|
||||||
for i := 0; i < int(dh.Qdcount); i++ {
|
for i := 0; i < int(dh.Qdcount); i++ {
|
||||||
off1 := off
|
off1 := off
|
||||||
var q Question
|
var q Question
|
||||||
|
@ -868,72 +913,62 @@ func (dns *Msg) String() string {
|
||||||
// If dns.Compress is true compression it is taken into account. Len()
|
// If dns.Compress is true compression it is taken into account. Len()
|
||||||
// is provided to be a faster way to get the size of the resulting packet,
|
// is provided to be a faster way to get the size of the resulting packet,
|
||||||
// than packing it, measuring the size and discarding the buffer.
|
// than packing it, measuring the size and discarding the buffer.
|
||||||
func (dns *Msg) Len() int {
|
func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
|
||||||
|
|
||||||
|
// compressedLen returns the message length when in compressed wire format
|
||||||
|
// when compress is true, otherwise the uncompressed length is returned.
|
||||||
|
func compressedLen(dns *Msg, compress bool) int {
|
||||||
// We always return one more than needed.
|
// We always return one more than needed.
|
||||||
l := 12 // Message header is always 12 bytes
|
l := 12 // Message header is always 12 bytes
|
||||||
var compression map[string]int
|
if compress {
|
||||||
if dns.Compress {
|
compression := map[string]int{}
|
||||||
compression = make(map[string]int)
|
for _, r := range dns.Question {
|
||||||
}
|
l += r.len()
|
||||||
for i := 0; i < len(dns.Question); i++ {
|
compressionLenHelper(compression, r.Name)
|
||||||
l += dns.Question[i].len()
|
}
|
||||||
if dns.Compress {
|
l += compressionLenSlice(compression, dns.Answer)
|
||||||
compressionLenHelper(compression, dns.Question[i].Name)
|
l += compressionLenSlice(compression, dns.Ns)
|
||||||
|
l += compressionLenSlice(compression, dns.Extra)
|
||||||
|
} else {
|
||||||
|
for _, r := range dns.Question {
|
||||||
|
l += r.len()
|
||||||
|
}
|
||||||
|
for _, r := range dns.Answer {
|
||||||
|
if r != nil {
|
||||||
|
l += r.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, r := range dns.Ns {
|
||||||
|
if r != nil {
|
||||||
|
l += r.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, r := range dns.Extra {
|
||||||
|
if r != nil {
|
||||||
|
l += r.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(dns.Answer); i++ {
|
return l
|
||||||
if dns.Answer[i] == nil {
|
}
|
||||||
|
|
||||||
|
func compressionLenSlice(c map[string]int, rs []RR) int {
|
||||||
|
var l int
|
||||||
|
for _, r := range rs {
|
||||||
|
if r == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
l += dns.Answer[i].len()
|
l += r.len()
|
||||||
if dns.Compress {
|
k, ok := compressionLenSearch(c, r.Header().Name)
|
||||||
k, ok := compressionLenSearch(compression, dns.Answer[i].Header().Name)
|
if ok {
|
||||||
if ok {
|
l += 1 - k
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelper(compression, dns.Answer[i].Header().Name)
|
|
||||||
k, ok = compressionLenSearchType(compression, dns.Answer[i])
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelperType(compression, dns.Answer[i])
|
|
||||||
}
|
}
|
||||||
}
|
compressionLenHelper(c, r.Header().Name)
|
||||||
for i := 0; i < len(dns.Ns); i++ {
|
k, ok = compressionLenSearchType(c, r)
|
||||||
if dns.Ns[i] == nil {
|
if ok {
|
||||||
continue
|
l += 1 - k
|
||||||
}
|
|
||||||
l += dns.Ns[i].len()
|
|
||||||
if dns.Compress {
|
|
||||||
k, ok := compressionLenSearch(compression, dns.Ns[i].Header().Name)
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelper(compression, dns.Ns[i].Header().Name)
|
|
||||||
k, ok = compressionLenSearchType(compression, dns.Ns[i])
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelperType(compression, dns.Ns[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(dns.Extra); i++ {
|
|
||||||
if dns.Extra[i] == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
l += dns.Extra[i].len()
|
|
||||||
if dns.Compress {
|
|
||||||
k, ok := compressionLenSearch(compression, dns.Extra[i].Header().Name)
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelper(compression, dns.Extra[i].Header().Name)
|
|
||||||
k, ok = compressionLenSearchType(compression, dns.Extra[i])
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelperType(compression, dns.Extra[i])
|
|
||||||
}
|
}
|
||||||
|
compressionLenHelperType(c, r)
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -970,97 +1005,6 @@ func compressionLenSearch(c map[string]int, s string) (int, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(miek): should add all types, because the all can be *used* for compression. Autogenerate from msg_generate and put in zmsg.go
|
|
||||||
func compressionLenHelperType(c map[string]int, r RR) {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case *NS:
|
|
||||||
compressionLenHelper(c, x.Ns)
|
|
||||||
case *MX:
|
|
||||||
compressionLenHelper(c, x.Mx)
|
|
||||||
case *CNAME:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *PTR:
|
|
||||||
compressionLenHelper(c, x.Ptr)
|
|
||||||
case *SOA:
|
|
||||||
compressionLenHelper(c, x.Ns)
|
|
||||||
compressionLenHelper(c, x.Mbox)
|
|
||||||
case *MB:
|
|
||||||
compressionLenHelper(c, x.Mb)
|
|
||||||
case *MG:
|
|
||||||
compressionLenHelper(c, x.Mg)
|
|
||||||
case *MR:
|
|
||||||
compressionLenHelper(c, x.Mr)
|
|
||||||
case *MF:
|
|
||||||
compressionLenHelper(c, x.Mf)
|
|
||||||
case *MD:
|
|
||||||
compressionLenHelper(c, x.Md)
|
|
||||||
case *RT:
|
|
||||||
compressionLenHelper(c, x.Host)
|
|
||||||
case *RP:
|
|
||||||
compressionLenHelper(c, x.Mbox)
|
|
||||||
compressionLenHelper(c, x.Txt)
|
|
||||||
case *MINFO:
|
|
||||||
compressionLenHelper(c, x.Rmail)
|
|
||||||
compressionLenHelper(c, x.Email)
|
|
||||||
case *AFSDB:
|
|
||||||
compressionLenHelper(c, x.Hostname)
|
|
||||||
case *SRV:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *NAPTR:
|
|
||||||
compressionLenHelper(c, x.Replacement)
|
|
||||||
case *RRSIG:
|
|
||||||
compressionLenHelper(c, x.SignerName)
|
|
||||||
case *NSEC:
|
|
||||||
compressionLenHelper(c, x.NextDomain)
|
|
||||||
// HIP?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only search on compressing these types.
|
|
||||||
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case *NS:
|
|
||||||
return compressionLenSearch(c, x.Ns)
|
|
||||||
case *MX:
|
|
||||||
return compressionLenSearch(c, x.Mx)
|
|
||||||
case *CNAME:
|
|
||||||
return compressionLenSearch(c, x.Target)
|
|
||||||
case *DNAME:
|
|
||||||
return compressionLenSearch(c, x.Target)
|
|
||||||
case *PTR:
|
|
||||||
return compressionLenSearch(c, x.Ptr)
|
|
||||||
case *SOA:
|
|
||||||
k, ok := compressionLenSearch(c, x.Ns)
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mbox)
|
|
||||||
if !ok && !ok1 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return k + k1, true
|
|
||||||
case *MB:
|
|
||||||
return compressionLenSearch(c, x.Mb)
|
|
||||||
case *MG:
|
|
||||||
return compressionLenSearch(c, x.Mg)
|
|
||||||
case *MR:
|
|
||||||
return compressionLenSearch(c, x.Mr)
|
|
||||||
case *MF:
|
|
||||||
return compressionLenSearch(c, x.Mf)
|
|
||||||
case *MD:
|
|
||||||
return compressionLenSearch(c, x.Md)
|
|
||||||
case *RT:
|
|
||||||
return compressionLenSearch(c, x.Host)
|
|
||||||
case *MINFO:
|
|
||||||
k, ok := compressionLenSearch(c, x.Rmail)
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Email)
|
|
||||||
if !ok && !ok1 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return k + k1, true
|
|
||||||
case *AFSDB:
|
|
||||||
return compressionLenSearch(c, x.Hostname)
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy returns a new RR which is a deep-copy of r.
|
// Copy returns a new RR which is a deep-copy of r.
|
||||||
func Copy(r RR) RR { r1 := r.copy(); return r1 }
|
func Copy(r RR) RR { r1 := r.copy(); return r1 }
|
||||||
|
|
||||||
|
|
16
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
16
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
|
@ -18,8 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var packageHdr = `
|
var packageHdr = `
|
||||||
// *** DO NOT MODIFY ***
|
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
|
||||||
// AUTOGENERATED BY go generate from msg_generate.go
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -139,8 +138,17 @@ return off, err
|
||||||
case st.Tag(i) == `dns:"base64"`:
|
case st.Tag(i) == `dns:"base64"`:
|
||||||
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
||||||
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`): // Hack to fix empty salt length for NSEC3
|
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
|
||||||
o("if rr.%s == \"-\" { /* do nothing, empty salt */ }\n")
|
// directly write instead of using o() so we get the error check in the correct place
|
||||||
|
field := st.Field(i).Name()
|
||||||
|
fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
|
||||||
|
if rr.%s != "-" {
|
||||||
|
off, err = packStringHex(rr.%s, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, field, field)
|
||||||
continue
|
continue
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
19
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
19
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
|
@ -96,7 +96,7 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
|
||||||
return hdr, len(msg), msg, err
|
return hdr, len(msg), msg, err
|
||||||
}
|
}
|
||||||
msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
|
msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
|
||||||
return hdr, off, msg, nil
|
return hdr, off, msg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// pack packs an RR header, returning the offset to the end of the header.
|
// pack packs an RR header, returning the offset to the end of the header.
|
||||||
|
@ -142,6 +142,11 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromBase32(s []byte) (buf []byte, err error) {
|
func fromBase32(s []byte) (buf []byte, err error) {
|
||||||
|
for i, b := range s {
|
||||||
|
if b >= 'a' && b <= 'z' {
|
||||||
|
s[i] = b - 32
|
||||||
|
}
|
||||||
|
}
|
||||||
buflen := base32.HexEncoding.DecodedLen(len(s))
|
buflen := base32.HexEncoding.DecodedLen(len(s))
|
||||||
buf = make([]byte, buflen)
|
buf = make([]byte, buflen)
|
||||||
n, err := base32.HexEncoding.Decode(buf, s)
|
n, err := base32.HexEncoding.Decode(buf, s)
|
||||||
|
@ -401,16 +406,13 @@ Option:
|
||||||
}
|
}
|
||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off += int(optlen)
|
off += int(optlen)
|
||||||
case EDNS0SUBNET, EDNS0SUBNETDRAFT:
|
case EDNS0SUBNET:
|
||||||
e := new(EDNS0_SUBNET)
|
e := new(EDNS0_SUBNET)
|
||||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||||
return nil, len(msg), err
|
return nil, len(msg), err
|
||||||
}
|
}
|
||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off += int(optlen)
|
off += int(optlen)
|
||||||
if code == EDNS0SUBNETDRAFT {
|
|
||||||
e.DraftOption = true
|
|
||||||
}
|
|
||||||
case EDNS0COOKIE:
|
case EDNS0COOKIE:
|
||||||
e := new(EDNS0_COOKIE)
|
e := new(EDNS0_COOKIE)
|
||||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||||
|
@ -453,6 +455,13 @@ Option:
|
||||||
}
|
}
|
||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off += int(optlen)
|
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:
|
default:
|
||||||
e := new(EDNS0_LOCAL)
|
e := new(EDNS0_LOCAL)
|
||||||
e.Code = code
|
e.Code = code
|
||||||
|
|
76
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
76
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
|
@ -48,62 +48,50 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
|
||||||
return toBase32(nsec3)
|
return toBase32(nsec3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Denialer is an interface that should be implemented by types that are used to denial
|
// Cover returns true if a name is covered by the NSEC3 record
|
||||||
// answers in DNSSEC.
|
|
||||||
type Denialer interface {
|
|
||||||
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
|
||||||
Cover(name string) bool
|
|
||||||
// Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
|
|
||||||
Match(name string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cover implements the Denialer interface.
|
|
||||||
func (rr *NSEC) Cover(name string) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match implements the Denialer interface.
|
|
||||||
func (rr *NSEC) Match(name string) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cover implements the Denialer interface.
|
|
||||||
func (rr *NSEC3) Cover(name string) bool {
|
func (rr *NSEC3) Cover(name string) bool {
|
||||||
// FIXME(miek): check if the zones match
|
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||||
// FIXME(miek): check if we're not dealing with parent nsec3
|
owner := strings.ToUpper(rr.Hdr.Name)
|
||||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
labelIndices := Split(owner)
|
||||||
labels := Split(rr.Hdr.Name)
|
if len(labelIndices) < 2 {
|
||||||
if len(labels) < 2 {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
|
ownerHash := owner[:labelIndices[1]-1]
|
||||||
if hash == rr.NextDomain {
|
ownerZone := owner[labelIndices[1]:]
|
||||||
return false // empty interval
|
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||||
}
|
|
||||||
if hash > rr.NextDomain { // last name, points to apex
|
|
||||||
// hname > hash
|
|
||||||
// hname > rr.NextDomain
|
|
||||||
// TODO(miek)
|
|
||||||
}
|
|
||||||
if hname <= hash {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if hname >= rr.NextDomain {
|
|
||||||
|
nextHash := rr.NextDomain
|
||||||
|
if ownerHash == nextHash { // empty interval
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
if ownerHash > nextHash { // end of zone
|
||||||
|
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return nameHash < nextHash // if nameHash is before beginning of zone it is covered
|
||||||
|
}
|
||||||
|
if nameHash < ownerHash { // nameHash is before ownerHash, not covered
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match implements the Denialer interface.
|
// Match returns true if a name matches the NSEC3 record
|
||||||
func (rr *NSEC3) Match(name string) bool {
|
func (rr *NSEC3) Match(name string) bool {
|
||||||
// FIXME(miek): Check if we are in the same zone
|
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
owner := strings.ToUpper(rr.Hdr.Name)
|
||||||
labels := Split(rr.Hdr.Name)
|
labelIndices := Split(owner)
|
||||||
if len(labels) < 2 {
|
if len(labelIndices) < 2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
|
ownerHash := owner[:labelIndices[1]-1]
|
||||||
if hash == hname {
|
ownerZone := owner[labelIndices[1]:]
|
||||||
|
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ownerHash == nameHash {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
4
vendor/github.com/miekg/dns/reverse.go
generated
vendored
4
vendor/github.com/miekg/dns/reverse.go
generated
vendored
|
@ -6,10 +6,10 @@ var StringToType = reverseInt16(TypeToString)
|
||||||
// StringToClass is the reverse of ClassToString, needed for string parsing.
|
// StringToClass is the reverse of ClassToString, needed for string parsing.
|
||||||
var StringToClass = reverseInt16(ClassToString)
|
var StringToClass = reverseInt16(ClassToString)
|
||||||
|
|
||||||
// Map of opcodes strings.
|
// StringToOpcode is a map of opcodes to strings.
|
||||||
var StringToOpcode = reverseInt(OpcodeToString)
|
var StringToOpcode = reverseInt(OpcodeToString)
|
||||||
|
|
||||||
// Map of rcodes strings.
|
// StringToRcode is a map of rcodes to strings.
|
||||||
var StringToRcode = reverseInt(RcodeToString)
|
var StringToRcode = reverseInt(RcodeToString)
|
||||||
|
|
||||||
// Reverse a map
|
// Reverse a map
|
||||||
|
|
2
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
2
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
|
@ -3,7 +3,7 @@ package dns
|
||||||
// Dedup removes identical RRs from rrs. It preserves the original ordering.
|
// Dedup removes identical RRs from rrs. It preserves the original ordering.
|
||||||
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
|
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
|
||||||
// rrs.
|
// rrs.
|
||||||
// m is used to store the RRs temporay. If it is nil a new map will be allocated.
|
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
||||||
func Dedup(rrs []RR, m map[string]RR) []RR {
|
func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
m = make(map[string]RR)
|
m = make(map[string]RR)
|
||||||
|
|
244
vendor/github.com/miekg/dns/scan.go
generated
vendored
244
vendor/github.com/miekg/dns/scan.go
generated
vendored
|
@ -1,23 +1,14 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type debugging bool
|
|
||||||
|
|
||||||
const debug debugging = false
|
|
||||||
|
|
||||||
func (d debugging) Printf(format string, args ...interface{}) {
|
|
||||||
if d {
|
|
||||||
log.Printf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxTok = 2048 // Largest token we can return.
|
const maxTok = 2048 // Largest token we can return.
|
||||||
const maxUint16 = 1<<16 - 1
|
const maxUint16 = 1<<16 - 1
|
||||||
|
|
||||||
|
@ -38,7 +29,7 @@ const (
|
||||||
zOwner
|
zOwner
|
||||||
zClass
|
zClass
|
||||||
zDirOrigin // $ORIGIN
|
zDirOrigin // $ORIGIN
|
||||||
zDirTtl // $TTL
|
zDirTTL // $TTL
|
||||||
zDirInclude // $INCLUDE
|
zDirInclude // $INCLUDE
|
||||||
zDirGenerate // $GENERATE
|
zDirGenerate // $GENERATE
|
||||||
|
|
||||||
|
@ -51,13 +42,13 @@ const (
|
||||||
zExpectAny // Expect rrtype, ttl or class
|
zExpectAny // Expect rrtype, ttl or class
|
||||||
zExpectAnyNoClass // Expect rrtype or ttl
|
zExpectAnyNoClass // Expect rrtype or ttl
|
||||||
zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
|
zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
|
||||||
zExpectAnyNoTtl // Expect rrtype or class
|
zExpectAnyNoTTL // Expect rrtype or class
|
||||||
zExpectAnyNoTtlBl // Whitespace after _EXPECT_ANY_NOTTL
|
zExpectAnyNoTTLBl // Whitespace after _EXPECT_ANY_NOTTL
|
||||||
zExpectRrtype // Expect rrtype
|
zExpectRrtype // Expect rrtype
|
||||||
zExpectRrtypeBl // Whitespace BEFORE rrtype
|
zExpectRrtypeBl // Whitespace BEFORE rrtype
|
||||||
zExpectRdata // The first element of the rdata
|
zExpectRdata // The first element of the rdata
|
||||||
zExpectDirTtlBl // Space after directive $TTL
|
zExpectDirTTLBl // Space after directive $TTL
|
||||||
zExpectDirTtl // Directive $TTL
|
zExpectDirTTL // Directive $TTL
|
||||||
zExpectDirOriginBl // Space after directive $ORIGIN
|
zExpectDirOriginBl // Space after directive $ORIGIN
|
||||||
zExpectDirOrigin // Directive $ORIGIN
|
zExpectDirOrigin // Directive $ORIGIN
|
||||||
zExpectDirIncludeBl // Space after directive $INCLUDE
|
zExpectDirIncludeBl // Space after directive $INCLUDE
|
||||||
|
@ -105,6 +96,12 @@ type Token struct {
|
||||||
Comment string
|
Comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ttlState describes the state necessary to fill in an omitted RR TTL
|
||||||
|
type ttlState struct {
|
||||||
|
ttl uint32 // ttl is the current default TTL
|
||||||
|
isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
|
||||||
|
}
|
||||||
|
|
||||||
// NewRR reads the RR contained in the string s. Only the first RR is
|
// NewRR reads the RR contained in the string s. Only the first RR is
|
||||||
// returned. If s contains no RR, return nil with no error. The class
|
// returned. If s contains no RR, return nil with no error. The class
|
||||||
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
||||||
|
@ -120,7 +117,8 @@ func NewRR(s string) (RR, error) {
|
||||||
// ReadRR reads the RR contained in q.
|
// ReadRR reads the RR contained in q.
|
||||||
// See NewRR for more documentation.
|
// See NewRR for more documentation.
|
||||||
func ReadRR(q io.Reader, filename string) (RR, error) {
|
func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||||
r := <-parseZoneHelper(q, ".", filename, 1)
|
defttl := &ttlState{defaultTtl, false}
|
||||||
|
r := <-parseZoneHelper(q, ".", filename, defttl, 1)
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -132,10 +130,10 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
||||||
// returned channel, which consist out the parsed RR, a potential comment or an error.
|
// returned channel, each consisting of either a parsed RR and optional comment
|
||||||
// If there is an error the RR is nil. The string file is only used
|
// or a nil RR and an error. The string file is only used
|
||||||
// in error reporting. The string origin is used as the initial origin, as
|
// in error reporting. The string origin is used as the initial origin, as
|
||||||
// if the file would start with: $ORIGIN origin .
|
// if the file would start with an $ORIGIN directive.
|
||||||
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
||||||
// The channel t is closed by ParseZone when the end of r is reached.
|
// The channel t is closed by ParseZone when the end of r is reached.
|
||||||
//
|
//
|
||||||
|
@ -157,25 +155,37 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||||
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
||||||
// RR are discarded. Comments on a line by themselves are discarded too.
|
// RR are discarded. Comments on a line by themselves are discarded too.
|
||||||
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
||||||
return parseZoneHelper(r, origin, file, 10000)
|
return parseZoneHelper(r, origin, file, nil, 10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
|
func parseZoneHelper(r io.Reader, origin, file string, defttl *ttlState, chansize int) chan *Token {
|
||||||
t := make(chan *Token, chansize)
|
t := make(chan *Token, chansize)
|
||||||
go parseZone(r, origin, file, t, 0)
|
go parseZone(r, origin, file, defttl, t, 0)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, include int) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if include == 0 {
|
if include == 0 {
|
||||||
close(t)
|
close(t)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
s := scanInit(r)
|
s, cancel := scanInit(r)
|
||||||
c := make(chan lex)
|
c := make(chan lex)
|
||||||
// Start the lexer
|
// Start the lexer
|
||||||
go zlexer(s, c)
|
go zlexer(s, c)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
cancel()
|
||||||
|
// zlexer can send up to three tokens, the next one and possibly 2 remainders.
|
||||||
|
// Do a non-blocking read.
|
||||||
|
_, ok := <-c
|
||||||
|
_, ok = <-c
|
||||||
|
_, ok = <-c
|
||||||
|
if !ok {
|
||||||
|
// too bad
|
||||||
|
}
|
||||||
|
}()
|
||||||
// 6 possible beginnings of a line, _ is a space
|
// 6 possible beginnings of a line, _ is a space
|
||||||
// 0. zRRTYPE -> all omitted until the rrtype
|
// 0. zRRTYPE -> all omitted until the rrtype
|
||||||
// 1. zOwner _ zRrtype -> class/ttl omitted
|
// 1. zOwner _ zRrtype -> class/ttl omitted
|
||||||
|
@ -186,18 +196,16 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
// After detecting these, we know the zRrtype so we can jump to functions
|
// After detecting these, we know the zRrtype so we can jump to functions
|
||||||
// handling the rdata for each of these types.
|
// handling the rdata for each of these types.
|
||||||
|
|
||||||
if origin == "" {
|
if origin != "" {
|
||||||
origin = "."
|
origin = Fqdn(origin)
|
||||||
}
|
if _, ok := IsDomainName(origin); !ok {
|
||||||
origin = Fqdn(origin)
|
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
|
||||||
if _, ok := IsDomainName(origin); !ok {
|
return
|
||||||
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
st := zExpectOwnerDir // initial state
|
st := zExpectOwnerDir // initial state
|
||||||
var h RR_Header
|
var h RR_Header
|
||||||
var defttl uint32 = defaultTtl
|
|
||||||
var prevName string
|
var prevName string
|
||||||
for l := range c {
|
for l := range c {
|
||||||
// Lexer spotted an error already
|
// Lexer spotted an error already
|
||||||
|
@ -209,31 +217,25 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
switch st {
|
switch st {
|
||||||
case zExpectOwnerDir:
|
case zExpectOwnerDir:
|
||||||
// We can also expect a directive, like $TTL or $ORIGIN
|
// We can also expect a directive, like $TTL or $ORIGIN
|
||||||
h.Ttl = defttl
|
if defttl != nil {
|
||||||
|
h.Ttl = defttl.ttl
|
||||||
|
}
|
||||||
h.Class = ClassINET
|
h.Class = ClassINET
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zNewline:
|
case zNewline:
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zOwner:
|
case zOwner:
|
||||||
h.Name = l.token
|
h.Name = l.token
|
||||||
if l.token[0] == '@' {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
h.Name = origin
|
|
||||||
prevName = h.Name
|
|
||||||
st = zExpectOwnerBl
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if h.Name[l.length-1] != '.' {
|
|
||||||
h.Name = appendOrigin(h.Name, origin)
|
|
||||||
}
|
|
||||||
_, ok := IsDomainName(l.token)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
|
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
h.Name = name
|
||||||
prevName = h.Name
|
prevName = h.Name
|
||||||
st = zExpectOwnerBl
|
st = zExpectOwnerBl
|
||||||
case zDirTtl:
|
case zDirTTL:
|
||||||
st = zExpectDirTtlBl
|
st = zExpectDirTTLBl
|
||||||
case zDirOrigin:
|
case zDirOrigin:
|
||||||
st = zExpectDirOriginBl
|
st = zExpectDirOriginBl
|
||||||
case zDirInclude:
|
case zDirInclude:
|
||||||
|
@ -252,15 +254,16 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
// Discard, can happen when there is nothing on the
|
// Discard, can happen when there is nothing on the
|
||||||
// line except the RR type
|
// line except the RR type
|
||||||
case zString:
|
case zString:
|
||||||
ttl, ok := stringToTtl(l.token)
|
ttl, ok := stringToTTL(l.token)
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// Don't about the defttl, we should take the $TTL value
|
if defttl == nil || !defttl.isByDirective {
|
||||||
// defttl = ttl
|
defttl = &ttlState{ttl, false}
|
||||||
st = zExpectAnyNoTtlBl
|
}
|
||||||
|
st = zExpectAnyNoTTLBl
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
||||||
|
@ -278,25 +281,16 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
||||||
l := <-c
|
switch l := <-c; l.value {
|
||||||
switch l.value {
|
|
||||||
case zBlank:
|
case zBlank:
|
||||||
l := <-c
|
l := <-c
|
||||||
if l.value == zString {
|
if l.value == zString {
|
||||||
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// a new origin is specified.
|
neworigin = name
|
||||||
if l.token[l.length-1] != '.' {
|
|
||||||
if origin != "." { // Prevent .. endings
|
|
||||||
neworigin = l.token + "." + origin
|
|
||||||
} else {
|
|
||||||
neworigin = l.token + origin
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
neworigin = l.token
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case zNewline, zEOF:
|
case zNewline, zEOF:
|
||||||
// Ok
|
// Ok
|
||||||
|
@ -305,24 +299,32 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Start with the new file
|
// Start with the new file
|
||||||
r1, e1 := os.Open(l.token)
|
includePath := l.token
|
||||||
|
if !filepath.IsAbs(includePath) {
|
||||||
|
includePath = filepath.Join(filepath.Dir(f), includePath)
|
||||||
|
}
|
||||||
|
r1, e1 := os.Open(includePath)
|
||||||
if e1 != nil {
|
if e1 != nil {
|
||||||
t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
|
msg := fmt.Sprintf("failed to open `%s'", l.token)
|
||||||
|
if !filepath.IsAbs(l.token) {
|
||||||
|
msg += fmt.Sprintf(" as `%s'", includePath)
|
||||||
|
}
|
||||||
|
t <- &Token{Error: &ParseError{f, msg, l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if include+1 > 7 {
|
if include+1 > 7 {
|
||||||
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
|
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
parseZone(r1, l.token, neworigin, t, include+1)
|
parseZone(r1, neworigin, includePath, defttl, t, include+1)
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirTtlBl:
|
case zExpectDirTTLBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = zExpectDirTtl
|
st = zExpectDirTTL
|
||||||
case zExpectDirTtl:
|
case zExpectDirTTL:
|
||||||
if l.value != zString {
|
if l.value != zString {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||||
return
|
return
|
||||||
|
@ -331,12 +333,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
t <- &Token{Error: e}
|
t <- &Token{Error: e}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttl, ok := stringToTtl(l.token)
|
ttl, ok := stringToTTL(l.token)
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defttl = ttl
|
defttl = &ttlState{ttl, true}
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirOriginBl:
|
case zExpectDirOriginBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
|
@ -352,19 +354,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
if e, _ := slurpRemainder(c, f); e != nil {
|
if e, _ := slurpRemainder(c, f); e != nil {
|
||||||
t <- &Token{Error: e}
|
t <- &Token{Error: e}
|
||||||
}
|
}
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if l.token[l.length-1] != '.' {
|
origin = name
|
||||||
if origin != "." { // Prevent .. endings
|
|
||||||
origin = l.token + "." + origin
|
|
||||||
} else {
|
|
||||||
origin = l.token + origin
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
origin = l.token
|
|
||||||
}
|
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirGenerateBl:
|
case zExpectDirGenerateBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
|
@ -391,20 +386,26 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
case zExpectAny:
|
case zExpectAny:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zRrtpe:
|
case zRrtpe:
|
||||||
|
if defttl == nil {
|
||||||
|
t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}}
|
||||||
|
return
|
||||||
|
}
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = zExpectRdata
|
st = zExpectRdata
|
||||||
case zClass:
|
case zClass:
|
||||||
h.Class = l.torc
|
h.Class = l.torc
|
||||||
st = zExpectAnyNoClassBl
|
st = zExpectAnyNoClassBl
|
||||||
case zString:
|
case zString:
|
||||||
ttl, ok := stringToTtl(l.token)
|
ttl, ok := stringToTTL(l.token)
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// defttl = ttl // don't set the defttl here
|
if defttl == nil || !defttl.isByDirective {
|
||||||
st = zExpectAnyNoTtlBl
|
defttl = &ttlState{ttl, false}
|
||||||
|
}
|
||||||
|
st = zExpectAnyNoTTLBl
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
||||||
return
|
return
|
||||||
|
@ -415,13 +416,13 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = zExpectAnyNoClass
|
st = zExpectAnyNoClass
|
||||||
case zExpectAnyNoTtlBl:
|
case zExpectAnyNoTTLBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = zExpectAnyNoTtl
|
st = zExpectAnyNoTTL
|
||||||
case zExpectAnyNoTtl:
|
case zExpectAnyNoTTL:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zClass:
|
case zClass:
|
||||||
h.Class = l.torc
|
h.Class = l.torc
|
||||||
|
@ -436,13 +437,15 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||||
case zExpectAnyNoClass:
|
case zExpectAnyNoClass:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zString:
|
case zString:
|
||||||
ttl, ok := stringToTtl(l.token)
|
ttl, ok := stringToTTL(l.token)
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// defttl = ttl // don't set the def ttl anymore
|
if defttl == nil || !defttl.isByDirective {
|
||||||
|
defttl = &ttlState{ttl, false}
|
||||||
|
}
|
||||||
st = zExpectRrtypeBl
|
st = zExpectRrtypeBl
|
||||||
case zRrtpe:
|
case zRrtpe:
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
|
@ -505,14 +508,12 @@ func zlexer(s *scan, c chan lex) {
|
||||||
if stri >= maxTok {
|
if stri >= maxTok {
|
||||||
l.token = "token length insufficient for parsing"
|
l.token = "token length insufficient for parsing"
|
||||||
l.err = true
|
l.err = true
|
||||||
debug.Printf("[%+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if comi >= maxTok {
|
if comi >= maxTok {
|
||||||
l.token = "comment length insufficient for parsing"
|
l.token = "comment length insufficient for parsing"
|
||||||
l.err = true
|
l.err = true
|
||||||
debug.Printf("[%+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -547,7 +548,7 @@ func zlexer(s *scan, c chan lex) {
|
||||||
// escape $... start with a \ not a $, so this will work
|
// escape $... start with a \ not a $, so this will work
|
||||||
switch l.tokenUpper {
|
switch l.tokenUpper {
|
||||||
case "$TTL":
|
case "$TTL":
|
||||||
l.value = zDirTtl
|
l.value = zDirTTL
|
||||||
case "$ORIGIN":
|
case "$ORIGIN":
|
||||||
l.value = zDirOrigin
|
l.value = zDirOrigin
|
||||||
case "$INCLUDE":
|
case "$INCLUDE":
|
||||||
|
@ -555,7 +556,6 @@ func zlexer(s *scan, c chan lex) {
|
||||||
case "$GENERATE":
|
case "$GENERATE":
|
||||||
l.value = zDirGenerate
|
l.value = zDirGenerate
|
||||||
}
|
}
|
||||||
debug.Printf("[7 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
} else {
|
} else {
|
||||||
l.value = zString
|
l.value = zString
|
||||||
|
@ -577,6 +577,7 @@ func zlexer(s *scan, c chan lex) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l.value = zRrtpe
|
l.value = zRrtpe
|
||||||
|
rrtype = true
|
||||||
l.torc = t
|
l.torc = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,16 +598,14 @@ func zlexer(s *scan, c chan lex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug.Printf("[6 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
stri = 0
|
stri = 0
|
||||||
// I reverse space stuff here
|
|
||||||
if !space && !commt {
|
if !space && !commt {
|
||||||
l.value = zBlank
|
l.value = zBlank
|
||||||
l.token = " "
|
l.token = " "
|
||||||
l.length = 1
|
l.length = 1
|
||||||
debug.Printf("[5 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
owner = false
|
owner = false
|
||||||
|
@ -629,7 +628,6 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
l.length = stri
|
l.length = stri
|
||||||
debug.Printf("[4 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
stri = 0
|
stri = 0
|
||||||
}
|
}
|
||||||
|
@ -667,7 +665,6 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.tokenUpper = l.token
|
l.tokenUpper = l.token
|
||||||
l.length = 1
|
l.length = 1
|
||||||
l.comment = string(com[:comi])
|
l.comment = string(com[:comi])
|
||||||
debug.Printf("[3 %+v %+v]", l.token, l.comment)
|
|
||||||
c <- l
|
c <- l
|
||||||
l.comment = ""
|
l.comment = ""
|
||||||
comi = 0
|
comi = 0
|
||||||
|
@ -693,14 +690,12 @@ func zlexer(s *scan, c chan lex) {
|
||||||
rrtype = true
|
rrtype = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug.Printf("[2 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
l.value = zNewline
|
l.value = zNewline
|
||||||
l.token = "\n"
|
l.token = "\n"
|
||||||
l.tokenUpper = l.token
|
l.tokenUpper = l.token
|
||||||
l.length = 1
|
l.length = 1
|
||||||
debug.Printf("[1 %+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
stri = 0
|
stri = 0
|
||||||
commt = false
|
commt = false
|
||||||
|
@ -746,7 +741,6 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
l.length = stri
|
l.length = stri
|
||||||
|
|
||||||
debug.Printf("[%+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
stri = 0
|
stri = 0
|
||||||
}
|
}
|
||||||
|
@ -782,7 +776,6 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.token = "extra closing brace"
|
l.token = "extra closing brace"
|
||||||
l.tokenUpper = l.token
|
l.tokenUpper = l.token
|
||||||
l.err = true
|
l.err = true
|
||||||
debug.Printf("[%+v]", l.token)
|
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -808,7 +801,12 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
l.length = stri
|
l.length = stri
|
||||||
l.value = zString
|
l.value = zString
|
||||||
debug.Printf("[%+v]", l.token)
|
c <- l
|
||||||
|
}
|
||||||
|
if brace != 0 {
|
||||||
|
l.token = "unbalanced brace"
|
||||||
|
l.tokenUpper = l.token
|
||||||
|
l.err = true
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,8 +817,8 @@ func classToInt(token string) (uint16, bool) {
|
||||||
if len(token) < offset+1 {
|
if len(token) < offset+1 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
class, ok := strconv.Atoi(token[offset:])
|
class, err := strconv.ParseUint(token[offset:], 10, 16)
|
||||||
if ok != nil || class > maxUint16 {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return uint16(class), true
|
return uint16(class), true
|
||||||
|
@ -832,15 +830,15 @@ func typeToInt(token string) (uint16, bool) {
|
||||||
if len(token) < offset+1 {
|
if len(token) < offset+1 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
typ, ok := strconv.Atoi(token[offset:])
|
typ, err := strconv.ParseUint(token[offset:], 10, 16)
|
||||||
if ok != nil || typ > maxUint16 {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return uint16(typ), true
|
return uint16(typ), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse things like 2w, 2m, etc, Return the time in seconds.
|
// stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds.
|
||||||
func stringToTtl(token string) (uint32, bool) {
|
func stringToTTL(token string) (uint32, bool) {
|
||||||
s := uint32(0)
|
s := uint32(0)
|
||||||
i := uint32(0)
|
i := uint32(0)
|
||||||
for _, c := range token {
|
for _, c := range token {
|
||||||
|
@ -913,6 +911,34 @@ func stringToCm(token string) (e, m uint8, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toAbsoluteName(name, origin string) (absolute string, ok bool) {
|
||||||
|
// check for an explicit origin reference
|
||||||
|
if name == "@" {
|
||||||
|
// require a nonempty origin
|
||||||
|
if origin == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return origin, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// require a valid domain name
|
||||||
|
_, ok = IsDomainName(name)
|
||||||
|
if !ok || name == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if name is already absolute
|
||||||
|
if name[len(name)-1] == '.' {
|
||||||
|
return name, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// require a nonempty origin
|
||||||
|
if origin == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return appendOrigin(name, origin), true
|
||||||
|
}
|
||||||
|
|
||||||
func appendOrigin(name, origin string) string {
|
func appendOrigin(name, origin string) string {
|
||||||
if origin == "." {
|
if origin == "." {
|
||||||
return name + origin
|
return name + origin
|
||||||
|
|
824
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
824
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
File diff suppressed because it is too large
Load diff
17
vendor/github.com/miekg/dns/scanner.go
generated
vendored
17
vendor/github.com/miekg/dns/scanner.go
generated
vendored
|
@ -4,6 +4,7 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"text/scanner"
|
"text/scanner"
|
||||||
)
|
)
|
||||||
|
@ -12,13 +13,18 @@ type scan struct {
|
||||||
src *bufio.Reader
|
src *bufio.Reader
|
||||||
position scanner.Position
|
position scanner.Position
|
||||||
eof bool // Have we just seen a eof
|
eof bool // Have we just seen a eof
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanInit(r io.Reader) *scan {
|
func scanInit(r io.Reader) (*scan, context.CancelFunc) {
|
||||||
s := new(scan)
|
s := new(scan)
|
||||||
s.src = bufio.NewReader(r)
|
s.src = bufio.NewReader(r)
|
||||||
s.position.Line = 1
|
s.position.Line = 1
|
||||||
return s
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
s.ctx = ctx
|
||||||
|
|
||||||
|
return s, cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
// tokenText returns the next byte from the input
|
// tokenText returns the next byte from the input
|
||||||
|
@ -27,6 +33,13 @@ func (s *scan) tokenText() (byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
select {
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
return c, context.Canceled
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// delay the newline handling until the next token is delivered,
|
// delay the newline handling until the next token is delivered,
|
||||||
// fixes off-by-one errors when reporting a parse error.
|
// fixes off-by-one errors when reporting a parse error.
|
||||||
if s.eof == true {
|
if s.eof == true {
|
||||||
|
|
65
vendor/github.com/miekg/dns/server.go
generated
vendored
65
vendor/github.com/miekg/dns/server.go
generated
vendored
|
@ -285,7 +285,7 @@ type Server struct {
|
||||||
WriteTimeout time.Duration
|
WriteTimeout time.Duration
|
||||||
// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
|
// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
|
||||||
IdleTimeout func() time.Duration
|
IdleTimeout func() time.Duration
|
||||||
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
|
// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
|
||||||
TsigSecret map[string]string
|
TsigSecret map[string]string
|
||||||
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
|
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
|
||||||
// the handler. It will specifically not check if the query has the QR bit not set.
|
// the handler. It will specifically not check if the query has the QR bit not set.
|
||||||
|
@ -297,10 +297,7 @@ type Server struct {
|
||||||
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
||||||
DecorateWriter DecorateWriter
|
DecorateWriter DecorateWriter
|
||||||
|
|
||||||
// Graceful shutdown handling
|
// Shutdown handling
|
||||||
|
|
||||||
inFlight sync.WaitGroup
|
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
|
@ -412,10 +409,8 @@ func (srv *Server) ActivateAndServe() error {
|
||||||
return &Error{err: "bad listeners"}
|
return &Error{err: "bad listeners"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
|
// Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and
|
||||||
// ActivateAndServe will return. All in progress queries are completed before the server
|
// ActivateAndServe will return.
|
||||||
// is taken down. If the Shutdown is taking longer than the reading timeout an error
|
|
||||||
// is returned.
|
|
||||||
func (srv *Server) Shutdown() error {
|
func (srv *Server) Shutdown() error {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
if !srv.started {
|
if !srv.started {
|
||||||
|
@ -431,19 +426,7 @@ func (srv *Server) Shutdown() error {
|
||||||
if srv.Listener != nil {
|
if srv.Listener != nil {
|
||||||
srv.Listener.Close()
|
srv.Listener.Close()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
fin := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
srv.inFlight.Wait()
|
|
||||||
fin <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(srv.getReadTimeout()):
|
|
||||||
return &Error{err: "server shutdown is pending"}
|
|
||||||
case <-fin:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
|
// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
|
||||||
|
@ -477,13 +460,6 @@ func (srv *Server) serveTCP(l net.Listener) error {
|
||||||
// deadline is not used here
|
// deadline is not used here
|
||||||
for {
|
for {
|
||||||
rw, err := l.Accept()
|
rw, err := l.Accept()
|
||||||
if err != nil {
|
|
||||||
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m, err := reader.ReadTCP(rw, rtimeout)
|
|
||||||
srv.lock.RLock()
|
srv.lock.RLock()
|
||||||
if !srv.started {
|
if !srv.started {
|
||||||
srv.lock.RUnlock()
|
srv.lock.RUnlock()
|
||||||
|
@ -491,10 +467,19 @@ func (srv *Server) serveTCP(l net.Listener) error {
|
||||||
}
|
}
|
||||||
srv.lock.RUnlock()
|
srv.lock.RUnlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
srv.inFlight.Add(1)
|
go func() {
|
||||||
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
m, err := reader.ReadTCP(rw, rtimeout)
|
||||||
|
if err != nil {
|
||||||
|
rw.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,17 +512,20 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||||
}
|
}
|
||||||
srv.lock.RUnlock()
|
srv.lock.RUnlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(m) < headerSize {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
srv.inFlight.Add(1)
|
|
||||||
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve a new connection.
|
// Serve a new connection.
|
||||||
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
|
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
|
||||||
defer srv.inFlight.Done()
|
|
||||||
|
|
||||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
||||||
if srv.DecorateWriter != nil {
|
if srv.DecorateWriter != nil {
|
||||||
w.writer = srv.DecorateWriter(w)
|
w.writer = srv.DecorateWriter(w)
|
||||||
|
@ -647,11 +635,8 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
|
||||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||||
m := make([]byte, srv.UDPSize)
|
m := make([]byte, srv.UDPSize)
|
||||||
n, s, err := ReadFromSessionUDP(conn, m)
|
n, s, err := ReadFromSessionUDP(conn, m)
|
||||||
if err != nil || n == 0 {
|
if err != nil {
|
||||||
if err != nil {
|
return nil, nil, err
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return nil, nil, ErrShortRead
|
|
||||||
}
|
}
|
||||||
m = m[:n]
|
m = m[:n]
|
||||||
return m, s, nil
|
return m, s, nil
|
||||||
|
|
8
vendor/github.com/miekg/dns/smimea.go
generated
vendored
8
vendor/github.com/miekg/dns/smimea.go
generated
vendored
|
@ -33,15 +33,15 @@ func (r *SMIMEA) Verify(cert *x509.Certificate) error {
|
||||||
return ErrSig // ErrSig, really?
|
return ErrSig // ErrSig, really?
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIMEAName returns the ownername of a SMIMEA resource record as per the
|
// SMIMEAName returns the ownername of a SMIMEA resource record as per the
|
||||||
// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
|
// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
|
||||||
func SMIMEAName(email_address string, domain_name string) (string, error) {
|
func SMIMEAName(email, domain string) (string, error) {
|
||||||
hasher := sha256.New()
|
hasher := sha256.New()
|
||||||
hasher.Write([]byte(email_address))
|
hasher.Write([]byte(email))
|
||||||
|
|
||||||
// RFC Section 3: "The local-part is hashed using the SHA2-256
|
// RFC Section 3: "The local-part is hashed using the SHA2-256
|
||||||
// algorithm with the hash truncated to 28 octets and
|
// algorithm with the hash truncated to 28 octets and
|
||||||
// represented in its hexadecimal representation to become the
|
// represented in its hexadecimal representation to become the
|
||||||
// left-most label in the prepared domain name"
|
// left-most label in the prepared domain name"
|
||||||
return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain_name, nil
|
return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain, nil
|
||||||
}
|
}
|
||||||
|
|
3
vendor/github.com/miekg/dns/tsig.go
generated
vendored
3
vendor/github.com/miekg/dns/tsig.go
generated
vendored
|
@ -208,6 +208,9 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
|
||||||
rr.Fudge = 300 // Standard (RFC) default.
|
rr.Fudge = 300 // Standard (RFC) default.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace message ID in header with original ID from TSIG
|
||||||
|
binary.BigEndian.PutUint16(msgbuf[0:2], rr.OrigId)
|
||||||
|
|
||||||
if requestMAC != "" {
|
if requestMAC != "" {
|
||||||
m := new(macWireFmt)
|
m := new(macWireFmt)
|
||||||
m.MACSize = uint16(len(requestMAC) / 2)
|
m.MACSize = uint16(len(requestMAC) / 2)
|
||||||
|
|
184
vendor/github.com/miekg/dns/types.go
generated
vendored
184
vendor/github.com/miekg/dns/types.go
generated
vendored
|
@ -78,6 +78,7 @@ const (
|
||||||
TypeCDS uint16 = 59
|
TypeCDS uint16 = 59
|
||||||
TypeCDNSKEY uint16 = 60
|
TypeCDNSKEY uint16 = 60
|
||||||
TypeOPENPGPKEY uint16 = 61
|
TypeOPENPGPKEY uint16 = 61
|
||||||
|
TypeCSYNC uint16 = 62
|
||||||
TypeSPF uint16 = 99
|
TypeSPF uint16 = 99
|
||||||
TypeUINFO uint16 = 100
|
TypeUINFO uint16 = 100
|
||||||
TypeUID uint16 = 101
|
TypeUID uint16 = 101
|
||||||
|
@ -91,6 +92,7 @@ const (
|
||||||
TypeEUI64 uint16 = 109
|
TypeEUI64 uint16 = 109
|
||||||
TypeURI uint16 = 256
|
TypeURI uint16 = 256
|
||||||
TypeCAA uint16 = 257
|
TypeCAA uint16 = 257
|
||||||
|
TypeAVC uint16 = 258
|
||||||
|
|
||||||
TypeTKEY uint16 = 249
|
TypeTKEY uint16 = 249
|
||||||
TypeTSIG uint16 = 250
|
TypeTSIG uint16 = 250
|
||||||
|
@ -114,27 +116,27 @@ const (
|
||||||
ClassNONE = 254
|
ClassNONE = 254
|
||||||
ClassANY = 255
|
ClassANY = 255
|
||||||
|
|
||||||
// Message Response Codes.
|
// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
|
||||||
RcodeSuccess = 0
|
RcodeSuccess = 0 // NoError - No Error [DNS]
|
||||||
RcodeFormatError = 1
|
RcodeFormatError = 1 // FormErr - Format Error [DNS]
|
||||||
RcodeServerFailure = 2
|
RcodeServerFailure = 2 // ServFail - Server Failure [DNS]
|
||||||
RcodeNameError = 3
|
RcodeNameError = 3 // NXDomain - Non-Existent Domain [DNS]
|
||||||
RcodeNotImplemented = 4
|
RcodeNotImplemented = 4 // NotImp - Not Implemented [DNS]
|
||||||
RcodeRefused = 5
|
RcodeRefused = 5 // Refused - Query Refused [DNS]
|
||||||
RcodeYXDomain = 6
|
RcodeYXDomain = 6 // YXDomain - Name Exists when it should not [DNS Update]
|
||||||
RcodeYXRrset = 7
|
RcodeYXRrset = 7 // YXRRSet - RR Set Exists when it should not [DNS Update]
|
||||||
RcodeNXRrset = 8
|
RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update]
|
||||||
RcodeNotAuth = 9
|
RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update]
|
||||||
RcodeNotZone = 10
|
RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG]
|
||||||
RcodeBadSig = 16 // TSIG
|
RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG]
|
||||||
RcodeBadVers = 16 // EDNS0
|
RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0]
|
||||||
RcodeBadKey = 17
|
RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG]
|
||||||
RcodeBadTime = 18
|
RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG]
|
||||||
RcodeBadMode = 19 // TKEY
|
RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY]
|
||||||
RcodeBadName = 20
|
RcodeBadName = 20 // BADNAME - Duplicate key name [TKEY]
|
||||||
RcodeBadAlg = 21
|
RcodeBadAlg = 21 // BADALG - Algorithm not supported [TKEY]
|
||||||
RcodeBadTrunc = 22 // TSIG
|
RcodeBadTrunc = 22 // BADTRUNC - Bad Truncation [TSIG]
|
||||||
RcodeBadCookie = 23 // DNS Cookies
|
RcodeBadCookie = 23 // BADCOOKIE - Bad/missing Server Cookie [DNS Cookies]
|
||||||
|
|
||||||
// Message Opcodes. There is no 3.
|
// Message Opcodes. There is no 3.
|
||||||
OpcodeQuery = 0
|
OpcodeQuery = 0
|
||||||
|
@ -144,7 +146,7 @@ const (
|
||||||
OpcodeUpdate = 5
|
OpcodeUpdate = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// Headers 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
|
||||||
Bits uint16
|
Bits uint16
|
||||||
|
@ -163,14 +165,15 @@ const (
|
||||||
_Z = 1 << 6 // Z
|
_Z = 1 << 6 // Z
|
||||||
_AD = 1 << 5 // authticated data
|
_AD = 1 << 5 // authticated data
|
||||||
_CD = 1 << 4 // checking disabled
|
_CD = 1 << 4 // checking disabled
|
||||||
|
)
|
||||||
|
|
||||||
|
// Various constants used in the LOC RR, See RFC 1887.
|
||||||
|
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.
|
||||||
|
LOC_HOURS = 60 * 1000
|
||||||
LOC_HOURS = 60 * 1000
|
LOC_DEGREES = 60 * LOC_HOURS
|
||||||
LOC_DEGREES = 60 * LOC_HOURS
|
LOC_ALTITUDEBASE = 100000
|
||||||
|
|
||||||
LOC_ALTITUDEBASE = 100000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Different Certificate Types, see RFC 4398, Section 2.1
|
// Different Certificate Types, see RFC 4398, Section 2.1
|
||||||
|
@ -236,6 +239,7 @@ type ANY struct {
|
||||||
|
|
||||||
func (rr *ANY) String() string { return rr.Hdr.String() }
|
func (rr *ANY) String() string { return rr.Hdr.String() }
|
||||||
|
|
||||||
|
// CNAME RR. See RFC 1034.
|
||||||
type CNAME struct {
|
type CNAME struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Target string `dns:"cdomain-name"`
|
Target string `dns:"cdomain-name"`
|
||||||
|
@ -243,6 +247,7 @@ type CNAME struct {
|
||||||
|
|
||||||
func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
|
func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
|
||||||
|
|
||||||
|
// HINFO RR. See RFC 1034.
|
||||||
type HINFO struct {
|
type HINFO struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Cpu string
|
Cpu string
|
||||||
|
@ -253,6 +258,7 @@ func (rr *HINFO) String() string {
|
||||||
return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
|
return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MB RR. See RFC 1035.
|
||||||
type MB struct {
|
type MB struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Mb string `dns:"cdomain-name"`
|
Mb string `dns:"cdomain-name"`
|
||||||
|
@ -260,6 +266,7 @@ type MB struct {
|
||||||
|
|
||||||
func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
|
func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
|
||||||
|
|
||||||
|
// MG RR. See RFC 1035.
|
||||||
type MG struct {
|
type MG struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Mg string `dns:"cdomain-name"`
|
Mg string `dns:"cdomain-name"`
|
||||||
|
@ -267,6 +274,7 @@ type MG struct {
|
||||||
|
|
||||||
func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
|
func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
|
||||||
|
|
||||||
|
// MINFO RR. See RFC 1035.
|
||||||
type MINFO struct {
|
type MINFO struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Rmail string `dns:"cdomain-name"`
|
Rmail string `dns:"cdomain-name"`
|
||||||
|
@ -277,6 +285,7 @@ func (rr *MINFO) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
|
return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MR RR. See RFC 1035.
|
||||||
type MR struct {
|
type MR struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Mr string `dns:"cdomain-name"`
|
Mr string `dns:"cdomain-name"`
|
||||||
|
@ -286,6 +295,7 @@ func (rr *MR) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Mr)
|
return rr.Hdr.String() + sprintName(rr.Mr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MF RR. See RFC 1035.
|
||||||
type MF struct {
|
type MF struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Mf string `dns:"cdomain-name"`
|
Mf string `dns:"cdomain-name"`
|
||||||
|
@ -295,6 +305,7 @@ func (rr *MF) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Mf)
|
return rr.Hdr.String() + sprintName(rr.Mf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MD RR. See RFC 1035.
|
||||||
type MD struct {
|
type MD struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Md string `dns:"cdomain-name"`
|
Md string `dns:"cdomain-name"`
|
||||||
|
@ -304,6 +315,7 @@ func (rr *MD) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Md)
|
return rr.Hdr.String() + sprintName(rr.Md)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MX RR. See RFC 1035.
|
||||||
type MX struct {
|
type MX struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -314,6 +326,7 @@ func (rr *MX) String() string {
|
||||||
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AFSDB RR. See RFC 1183.
|
||||||
type AFSDB struct {
|
type AFSDB struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Subtype uint16
|
Subtype uint16
|
||||||
|
@ -324,6 +337,7 @@ func (rr *AFSDB) String() string {
|
||||||
return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// X25 RR. See RFC 1183, Section 3.1.
|
||||||
type X25 struct {
|
type X25 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
PSDNAddress string
|
PSDNAddress string
|
||||||
|
@ -333,6 +347,7 @@ func (rr *X25) String() string {
|
||||||
return rr.Hdr.String() + rr.PSDNAddress
|
return rr.Hdr.String() + rr.PSDNAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RT RR. See RFC 1183, Section 3.3.
|
||||||
type RT struct {
|
type RT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -343,6 +358,7 @@ func (rr *RT) String() string {
|
||||||
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NS RR. See RFC 1035.
|
||||||
type NS struct {
|
type NS struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Ns string `dns:"cdomain-name"`
|
Ns string `dns:"cdomain-name"`
|
||||||
|
@ -352,6 +368,7 @@ func (rr *NS) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Ns)
|
return rr.Hdr.String() + sprintName(rr.Ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PTR RR. See RFC 1035.
|
||||||
type PTR struct {
|
type PTR struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Ptr string `dns:"cdomain-name"`
|
Ptr string `dns:"cdomain-name"`
|
||||||
|
@ -361,6 +378,7 @@ func (rr *PTR) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Ptr)
|
return rr.Hdr.String() + sprintName(rr.Ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RP RR. See RFC 1138, Section 2.2.
|
||||||
type RP struct {
|
type RP struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Mbox string `dns:"domain-name"`
|
Mbox string `dns:"domain-name"`
|
||||||
|
@ -371,6 +389,7 @@ func (rr *RP) String() string {
|
||||||
return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
|
return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SOA RR. See RFC 1035.
|
||||||
type SOA struct {
|
type SOA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Ns string `dns:"cdomain-name"`
|
Ns string `dns:"cdomain-name"`
|
||||||
|
@ -391,6 +410,7 @@ func (rr *SOA) String() string {
|
||||||
" " + strconv.FormatInt(int64(rr.Minttl), 10)
|
" " + strconv.FormatInt(int64(rr.Minttl), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TXT RR. See RFC 1035.
|
||||||
type TXT struct {
|
type TXT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Txt []string `dns:"txt"`
|
Txt []string `dns:"txt"`
|
||||||
|
@ -523,6 +543,7 @@ func nextByte(b []byte, offset int) (byte, int) {
|
||||||
return b[offset+1], 2
|
return b[offset+1], 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPF RR. See RFC 4408, Section 3.1.1.
|
||||||
type SPF struct {
|
type SPF struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Txt []string `dns:"txt"`
|
Txt []string `dns:"txt"`
|
||||||
|
@ -530,6 +551,15 @@ type SPF struct {
|
||||||
|
|
||||||
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||||
|
|
||||||
|
// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
|
||||||
|
type AVC struct {
|
||||||
|
Hdr RR_Header
|
||||||
|
Txt []string `dns:"txt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||||
|
|
||||||
|
// SRV RR. See RFC 2782.
|
||||||
type SRV struct {
|
type SRV struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Priority uint16
|
Priority uint16
|
||||||
|
@ -545,6 +575,7 @@ func (rr *SRV) String() string {
|
||||||
strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
|
strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NAPTR RR. See RFC 2915.
|
||||||
type NAPTR struct {
|
type NAPTR struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Order uint16
|
Order uint16
|
||||||
|
@ -565,7 +596,7 @@ func (rr *NAPTR) String() string {
|
||||||
rr.Replacement
|
rr.Replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
// The CERT resource record, see RFC 4398.
|
// CERT RR. See RFC 4398.
|
||||||
type CERT struct {
|
type CERT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Type uint16
|
Type uint16
|
||||||
|
@ -591,7 +622,7 @@ func (rr *CERT) String() string {
|
||||||
" " + rr.Certificate
|
" " + rr.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
// The DNAME resource record, see RFC 2672.
|
// DNAME RR. See RFC 2672.
|
||||||
type DNAME struct {
|
type DNAME struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Target string `dns:"domain-name"`
|
Target string `dns:"domain-name"`
|
||||||
|
@ -601,6 +632,7 @@ func (rr *DNAME) String() string {
|
||||||
return rr.Hdr.String() + sprintName(rr.Target)
|
return rr.Hdr.String() + sprintName(rr.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A RR. See RFC 1035.
|
||||||
type A struct {
|
type A struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
A net.IP `dns:"a"`
|
A net.IP `dns:"a"`
|
||||||
|
@ -613,6 +645,7 @@ func (rr *A) String() string {
|
||||||
return rr.Hdr.String() + rr.A.String()
|
return rr.Hdr.String() + rr.A.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AAAA RR. See RFC 3596.
|
||||||
type AAAA struct {
|
type AAAA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
AAAA net.IP `dns:"aaaa"`
|
AAAA net.IP `dns:"aaaa"`
|
||||||
|
@ -625,6 +658,7 @@ func (rr *AAAA) String() string {
|
||||||
return rr.Hdr.String() + rr.AAAA.String()
|
return rr.Hdr.String() + rr.AAAA.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PX RR. See RFC 2163.
|
||||||
type PX struct {
|
type PX struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -636,6 +670,7 @@ func (rr *PX) String() string {
|
||||||
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GPOS RR. See RFC 1712.
|
||||||
type GPOS struct {
|
type GPOS struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Longitude string
|
Longitude string
|
||||||
|
@ -647,6 +682,7 @@ func (rr *GPOS) String() string {
|
||||||
return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
|
return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOC RR. See RFC RFC 1876.
|
||||||
type LOC struct {
|
type LOC struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Version uint8
|
Version uint8
|
||||||
|
@ -723,11 +759,12 @@ func (rr *LOC) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIG is identical to RRSIG and nowadays only used for SIG(0), RFC2931.
|
// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
|
||||||
type SIG struct {
|
type SIG struct {
|
||||||
RRSIG
|
RRSIG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RRSIG RR. See RFC 4034 and RFC 3755.
|
||||||
type RRSIG struct {
|
type RRSIG struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
TypeCovered uint16
|
TypeCovered uint16
|
||||||
|
@ -755,6 +792,7 @@ func (rr *RRSIG) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NSEC RR. See RFC 4034 and RFC 3755.
|
||||||
type NSEC struct {
|
type NSEC struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
NextDomain string `dns:"domain-name"`
|
NextDomain string `dns:"domain-name"`
|
||||||
|
@ -782,14 +820,13 @@ func (rr *NSEC) len() int {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
type DLV struct {
|
// DLV RR. See RFC 4431.
|
||||||
DS
|
type DLV struct{ DS }
|
||||||
}
|
|
||||||
|
|
||||||
type CDS struct {
|
// CDS RR. See RFC 7344.
|
||||||
DS
|
type CDS struct{ DS }
|
||||||
}
|
|
||||||
|
|
||||||
|
// DS RR. See RFC 4034 and RFC 3658.
|
||||||
type DS struct {
|
type DS struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
KeyTag uint16
|
KeyTag uint16
|
||||||
|
@ -805,6 +842,7 @@ func (rr *DS) String() string {
|
||||||
" " + strings.ToUpper(rr.Digest)
|
" " + strings.ToUpper(rr.Digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KX RR. See RFC 2230.
|
||||||
type KX struct {
|
type KX struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -816,6 +854,7 @@ func (rr *KX) String() string {
|
||||||
" " + sprintName(rr.Exchanger)
|
" " + sprintName(rr.Exchanger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
|
||||||
type TA struct {
|
type TA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
KeyTag uint16
|
KeyTag uint16
|
||||||
|
@ -831,6 +870,7 @@ func (rr *TA) String() string {
|
||||||
" " + strings.ToUpper(rr.Digest)
|
" " + strings.ToUpper(rr.Digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
|
||||||
type TALINK struct {
|
type TALINK struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
PreviousName string `dns:"domain-name"`
|
PreviousName string `dns:"domain-name"`
|
||||||
|
@ -842,6 +882,7 @@ func (rr *TALINK) String() string {
|
||||||
sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
|
sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSHFP RR. See RFC RFC 4255.
|
||||||
type SSHFP struct {
|
type SSHFP struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Algorithm uint8
|
Algorithm uint8
|
||||||
|
@ -855,14 +896,17 @@ func (rr *SSHFP) String() string {
|
||||||
" " + strings.ToUpper(rr.FingerPrint)
|
" " + strings.ToUpper(rr.FingerPrint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KEY RR. See RFC RFC 2535.
|
||||||
type KEY struct {
|
type KEY struct {
|
||||||
DNSKEY
|
DNSKEY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CDNSKEY RR. See RFC 7344.
|
||||||
type CDNSKEY struct {
|
type CDNSKEY struct {
|
||||||
DNSKEY
|
DNSKEY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DNSKEY RR. See RFC 4034 and RFC 3755.
|
||||||
type DNSKEY struct {
|
type DNSKEY struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Flags uint16
|
Flags uint16
|
||||||
|
@ -878,6 +922,7 @@ func (rr *DNSKEY) String() string {
|
||||||
" " + rr.PublicKey
|
" " + rr.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
|
||||||
type RKEY struct {
|
type RKEY struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Flags uint16
|
Flags uint16
|
||||||
|
@ -893,6 +938,7 @@ func (rr *RKEY) String() string {
|
||||||
" " + rr.PublicKey
|
" " + rr.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NSAPPTR RR. See RFC 1348.
|
||||||
type NSAPPTR struct {
|
type NSAPPTR struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Ptr string `dns:"domain-name"`
|
Ptr string `dns:"domain-name"`
|
||||||
|
@ -900,6 +946,7 @@ type NSAPPTR struct {
|
||||||
|
|
||||||
func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
|
func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
|
||||||
|
|
||||||
|
// NSEC3 RR. See RFC 5155.
|
||||||
type NSEC3 struct {
|
type NSEC3 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Hash uint8
|
Hash uint8
|
||||||
|
@ -938,6 +985,7 @@ func (rr *NSEC3) len() int {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NSEC3PARAM RR. See RFC 5155.
|
||||||
type NSEC3PARAM struct {
|
type NSEC3PARAM struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Hash uint8
|
Hash uint8
|
||||||
|
@ -956,6 +1004,7 @@ func (rr *NSEC3PARAM) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TKEY RR. See RFC 2930.
|
||||||
type TKEY struct {
|
type TKEY struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Algorithm string `dns:"domain-name"`
|
Algorithm string `dns:"domain-name"`
|
||||||
|
@ -964,17 +1013,21 @@ type TKEY struct {
|
||||||
Mode uint16
|
Mode uint16
|
||||||
Error uint16
|
Error uint16
|
||||||
KeySize uint16
|
KeySize uint16
|
||||||
Key string
|
Key string `dns:"size-hex:KeySize"`
|
||||||
OtherLen uint16
|
OtherLen uint16
|
||||||
OtherData string
|
OtherData string `dns:"size-hex:OtherLen"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TKEY has no official presentation format, but this will suffice.
|
||||||
func (rr *TKEY) String() string {
|
func (rr *TKEY) String() string {
|
||||||
// It has no presentation format
|
s := "\n;; TKEY PSEUDOSECTION:\n"
|
||||||
return ""
|
s += rr.Hdr.String() + " " + rr.Algorithm + " " +
|
||||||
|
strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
|
||||||
|
strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC3597 represents an unknown/generic RR.
|
// RFC3597 represents an unknown/generic RR. See RFC 3597.
|
||||||
type RFC3597 struct {
|
type RFC3597 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Rdata string `dns:"hex"`
|
Rdata string `dns:"hex"`
|
||||||
|
@ -998,6 +1051,7 @@ func rfc3597Header(h RR_Header) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URI RR. See RFC 7553.
|
||||||
type URI struct {
|
type URI struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Priority uint16
|
Priority uint16
|
||||||
|
@ -1010,6 +1064,7 @@ func (rr *URI) String() string {
|
||||||
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
|
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DHCID RR. See RFC 4701.
|
||||||
type DHCID struct {
|
type DHCID struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Digest string `dns:"base64"`
|
Digest string `dns:"base64"`
|
||||||
|
@ -1017,6 +1072,7 @@ type DHCID struct {
|
||||||
|
|
||||||
func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
|
func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
|
||||||
|
|
||||||
|
// TLSA RR. See RFC 6698.
|
||||||
type TLSA struct {
|
type TLSA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Usage uint8
|
Usage uint8
|
||||||
|
@ -1033,6 +1089,7 @@ func (rr *TLSA) String() string {
|
||||||
" " + rr.Certificate
|
" " + rr.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SMIMEA RR. See RFC 8162.
|
||||||
type SMIMEA struct {
|
type SMIMEA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Usage uint8
|
Usage uint8
|
||||||
|
@ -1055,6 +1112,7 @@ func (rr *SMIMEA) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HIP RR. See RFC 8005.
|
||||||
type HIP struct {
|
type HIP struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
HitLength uint8
|
HitLength uint8
|
||||||
|
@ -1076,6 +1134,7 @@ func (rr *HIP) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
|
||||||
type NINFO struct {
|
type NINFO struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
ZSData []string `dns:"txt"`
|
ZSData []string `dns:"txt"`
|
||||||
|
@ -1083,6 +1142,7 @@ type NINFO struct {
|
||||||
|
|
||||||
func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
|
func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
|
||||||
|
|
||||||
|
// NID RR. See RFC RFC 6742.
|
||||||
type NID struct {
|
type NID struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -1096,6 +1156,7 @@ func (rr *NID) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// L32 RR, See RFC 6742.
|
||||||
type L32 struct {
|
type L32 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -1110,6 +1171,7 @@ func (rr *L32) String() string {
|
||||||
" " + rr.Locator32.String()
|
" " + rr.Locator32.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// L64 RR, See RFC 6742.
|
||||||
type L64 struct {
|
type L64 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -1123,6 +1185,7 @@ func (rr *L64) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LP RR. See RFC 6742.
|
||||||
type LP struct {
|
type LP struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
Preference uint16
|
||||||
|
@ -1133,6 +1196,7 @@ func (rr *LP) String() string {
|
||||||
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
|
return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EUI48 RR. See RFC 7043.
|
||||||
type EUI48 struct {
|
type EUI48 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Address uint64 `dns:"uint48"`
|
Address uint64 `dns:"uint48"`
|
||||||
|
@ -1140,6 +1204,7 @@ type EUI48 struct {
|
||||||
|
|
||||||
func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
|
func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
|
||||||
|
|
||||||
|
// EUI64 RR. See RFC 7043.
|
||||||
type EUI64 struct {
|
type EUI64 struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Address uint64
|
Address uint64
|
||||||
|
@ -1147,6 +1212,7 @@ type EUI64 struct {
|
||||||
|
|
||||||
func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
|
func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
|
||||||
|
|
||||||
|
// CAA RR. See RFC 6844.
|
||||||
type CAA struct {
|
type CAA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Flag uint8
|
Flag uint8
|
||||||
|
@ -1158,6 +1224,7 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UID RR. Deprecated, IANA-Reserved.
|
||||||
type UID struct {
|
type UID struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Uid uint32
|
Uid uint32
|
||||||
|
@ -1165,6 +1232,7 @@ type UID struct {
|
||||||
|
|
||||||
func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
|
func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
|
||||||
|
|
||||||
|
// GID RR. Deprecated, IANA-Reserved.
|
||||||
type GID struct {
|
type GID struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Gid uint32
|
Gid uint32
|
||||||
|
@ -1172,6 +1240,7 @@ type GID struct {
|
||||||
|
|
||||||
func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
|
func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
|
||||||
|
|
||||||
|
// UINFO RR. Deprecated, IANA-Reserved.
|
||||||
type UINFO struct {
|
type UINFO struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Uinfo string
|
Uinfo string
|
||||||
|
@ -1179,6 +1248,7 @@ type UINFO struct {
|
||||||
|
|
||||||
func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
|
func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
|
||||||
|
|
||||||
|
// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
|
||||||
type EID struct {
|
type EID struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Endpoint string `dns:"hex"`
|
Endpoint string `dns:"hex"`
|
||||||
|
@ -1186,6 +1256,7 @@ type EID struct {
|
||||||
|
|
||||||
func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
|
func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
|
||||||
|
|
||||||
|
// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
|
||||||
type NIMLOC struct {
|
type NIMLOC struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Locator string `dns:"hex"`
|
Locator string `dns:"hex"`
|
||||||
|
@ -1193,6 +1264,7 @@ type NIMLOC struct {
|
||||||
|
|
||||||
func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
|
func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
|
||||||
|
|
||||||
|
// OPENPGPKEY RR. See RFC 7929.
|
||||||
type OPENPGPKEY struct {
|
type OPENPGPKEY struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
PublicKey string `dns:"base64"`
|
PublicKey string `dns:"base64"`
|
||||||
|
@ -1200,6 +1272,36 @@ type OPENPGPKEY struct {
|
||||||
|
|
||||||
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
|
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
|
||||||
|
|
||||||
|
// CSYNC RR. See RFC 7477.
|
||||||
|
type CSYNC struct {
|
||||||
|
Hdr RR_Header
|
||||||
|
Serial uint32
|
||||||
|
Flags uint16
|
||||||
|
TypeBitMap []uint16 `dns:"nsec"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *CSYNC) String() string {
|
||||||
|
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
|
||||||
|
|
||||||
|
for i := 0; i < len(rr.TypeBitMap); i++ {
|
||||||
|
s += " " + Type(rr.TypeBitMap[i]).String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *CSYNC) len() int {
|
||||||
|
l := rr.Hdr.len() + 4 + 2
|
||||||
|
lastwindow := uint32(2 ^ 32 + 1)
|
||||||
|
for _, t := range rr.TypeBitMap {
|
||||||
|
window := t / 256
|
||||||
|
if uint32(window) != lastwindow {
|
||||||
|
l += 1 + 32
|
||||||
|
}
|
||||||
|
lastwindow = uint32(window)
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
9
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
9
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
|
@ -23,11 +23,11 @@ var skipLen = map[string]struct{}{
|
||||||
"NSEC": {},
|
"NSEC": {},
|
||||||
"NSEC3": {},
|
"NSEC3": {},
|
||||||
"OPT": {},
|
"OPT": {},
|
||||||
|
"CSYNC": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
var packageHdr = `
|
var packageHdr = `
|
||||||
// *** DO NOT MODIFY ***
|
// Code generated by "go run types_generate.go"; DO NOT EDIT.
|
||||||
// AUTOGENERATED BY go generate from type_generate.go
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ var TypeToString = map[uint16]string{
|
||||||
`))
|
`))
|
||||||
|
|
||||||
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
||||||
// Header() functions
|
|
||||||
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
@ -182,6 +181,8 @@ func main() {
|
||||||
fallthrough
|
fallthrough
|
||||||
case st.Tag(i) == `dns:"base64"`:
|
case st.Tag(i) == `dns:"base64"`:
|
||||||
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
||||||
|
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
|
||||||
|
o("l += len(rr.%s)/2\n")
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
||||||
fallthrough
|
fallthrough
|
||||||
case st.Tag(i) == `dns:"hex"`:
|
case st.Tag(i) == `dns:"hex"`:
|
||||||
|
@ -197,7 +198,7 @@ func main() {
|
||||||
case st.Tag(i) == "":
|
case st.Tag(i) == "":
|
||||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||||
case types.Uint8:
|
case types.Uint8:
|
||||||
o("l += 1 // %s\n")
|
o("l++ // %s\n")
|
||||||
case types.Uint16:
|
case types.Uint16:
|
||||||
o("l += 2 // %s\n")
|
o("l += 2 // %s\n")
|
||||||
case types.Uint32:
|
case types.Uint32:
|
||||||
|
|
85
vendor/github.com/miekg/dns/udp.go
generated
vendored
85
vendor/github.com/miekg/dns/udp.go
generated
vendored
|
@ -1,10 +1,12 @@
|
||||||
// +build !windows,!plan9
|
// +build !windows
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SessionUDP holds the remote address and the associated
|
// SessionUDP holds the remote address and the associated
|
||||||
|
@ -17,29 +19,6 @@ type SessionUDP struct {
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
|
|
||||||
// setUDPSocketOptions sets the UDP socket options.
|
|
||||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
|
||||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
|
||||||
sa, err := getUDPSocketName(conn)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch sa.(type) {
|
|
||||||
case *syscall.SockaddrInet6:
|
|
||||||
v6only, err := getUDPSocketOptions6Only(conn)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
setUDPSocketOptions6(conn)
|
|
||||||
if !v6only {
|
|
||||||
setUDPSocketOptions4(conn)
|
|
||||||
}
|
|
||||||
case *syscall.SockaddrInet4:
|
|
||||||
setUDPSocketOptions4(conn)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
// net.UDPAddr.
|
// net.UDPAddr.
|
||||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
|
@ -51,8 +30,60 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
oob := correctSource(session.context)
|
||||||
|
n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||||
|
// Try setting the flags for both families and ignore the errors unless they
|
||||||
|
// both error.
|
||||||
|
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
|
||||||
|
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
|
||||||
|
if err6 != nil && err4 != nil {
|
||||||
|
return err4
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseDstFromOOB takes oob data and returns the destination IP.
|
||||||
|
func parseDstFromOOB(oob []byte) net.IP {
|
||||||
|
// Start with IPv6 and then fallback to IPv4
|
||||||
|
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
|
||||||
|
// the lvl of the header for a 0 or 41 isn't cross-platform.
|
||||||
|
var dst net.IP
|
||||||
|
cm6 := new(ipv6.ControlMessage)
|
||||||
|
if cm6.Parse(oob) == nil {
|
||||||
|
dst = cm6.Dst
|
||||||
|
}
|
||||||
|
if dst == nil {
|
||||||
|
cm4 := new(ipv4.ControlMessage)
|
||||||
|
if cm4.Parse(oob) == nil {
|
||||||
|
dst = cm4.Dst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
|
||||||
|
func correctSource(oob []byte) []byte {
|
||||||
|
dst := parseDstFromOOB(oob)
|
||||||
|
if dst == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// If the dst is definitely an IPv6, then use ipv6's ControlMessage to
|
||||||
|
// respond otherwise use ipv4's because ipv6's marshal ignores ipv4
|
||||||
|
// addresses.
|
||||||
|
if dst.To4() == nil {
|
||||||
|
cm := new(ipv6.ControlMessage)
|
||||||
|
cm.Src = dst
|
||||||
|
oob = cm.Marshal()
|
||||||
|
} else {
|
||||||
|
cm := new(ipv4.ControlMessage)
|
||||||
|
cm.Src = dst
|
||||||
|
oob = cm.Marshal()
|
||||||
|
}
|
||||||
|
return oob
|
||||||
|
}
|
||||||
|
|
82
vendor/github.com/miekg/dns/udp_linux.go
generated
vendored
82
vendor/github.com/miekg/dns/udp_linux.go
generated
vendored
|
@ -1,82 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
// See:
|
|
||||||
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
|
|
||||||
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
|
|
||||||
//
|
|
||||||
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
|
|
||||||
// interface, this might not always be the correct one. This code will make sure the egress
|
|
||||||
// packet's interface matched the ingress' one.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// setUDPSocketOptions4 prepares the v4 socket for sessions.
|
|
||||||
func setUDPSocketOptions4(conn *net.UDPConn) error {
|
|
||||||
file, err := conn.File()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
|
|
||||||
file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Calling File() above results in the connection becoming blocking, we must fix that.
|
|
||||||
// See https://github.com/miekg/dns/issues/279
|
|
||||||
err = syscall.SetNonblock(int(file.Fd()), true)
|
|
||||||
if err != nil {
|
|
||||||
file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setUDPSocketOptions6 prepares the v6 socket for sessions.
|
|
||||||
func setUDPSocketOptions6(conn *net.UDPConn) error {
|
|
||||||
file, err := conn.File()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
|
|
||||||
file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = syscall.SetNonblock(int(file.Fd()), true)
|
|
||||||
if err != nil {
|
|
||||||
file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
|
|
||||||
// (dualstack).
|
|
||||||
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
|
|
||||||
file, err := conn.File()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
|
|
||||||
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
|
|
||||||
if err != nil {
|
|
||||||
file.Close()
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
return v6only == 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
|
|
||||||
file, err := conn.File()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
return syscall.Getsockname(int(file.Fd()))
|
|
||||||
}
|
|
17
vendor/github.com/miekg/dns/udp_other.go
generated
vendored
17
vendor/github.com/miekg/dns/udp_other.go
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
// +build !linux,!plan9
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These do nothing. See udp_linux.go for an example of how to implement this.
|
|
||||||
|
|
||||||
// We tried to adhire to some kind of naming scheme.
|
|
||||||
|
|
||||||
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
|
|
||||||
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
|
|
||||||
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
|
|
||||||
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { return nil, nil }
|
|
34
vendor/github.com/miekg/dns/udp_plan9.go
generated
vendored
34
vendor/github.com/miekg/dns/udp_plan9.go
generated
vendored
|
@ -1,34 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
|
|
||||||
|
|
||||||
// SessionUDP holds the remote address and the associated
|
|
||||||
// out-of-band data.
|
|
||||||
type SessionUDP struct {
|
|
||||||
raddr *net.UDPAddr
|
|
||||||
context []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
|
||||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
|
||||||
|
|
||||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
|
||||||
// net.UDPAddr.
|
|
||||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
|
||||||
oob := make([]byte, 40)
|
|
||||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
|
||||||
if err != nil {
|
|
||||||
return n, nil, err
|
|
||||||
}
|
|
||||||
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
|
||||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
|
||||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
|
||||||
return n, err
|
|
||||||
}
|
|
19
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
19
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
|
@ -4,12 +4,17 @@ package dns
|
||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
|
// SessionUDP holds the remote address
|
||||||
type SessionUDP struct {
|
type SessionUDP struct {
|
||||||
raddr *net.UDPAddr
|
raddr *net.UDPAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoteAddr returns the remote network address.
|
||||||
|
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
|
|
||||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
// net.UDPAddr.
|
// net.UDPAddr.
|
||||||
|
// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
|
||||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
n, raddr, err := conn.ReadFrom(b)
|
n, raddr, err := conn.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -19,16 +24,14 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
return n, session, err
|
return n, session, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
|
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
|
||||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, err := conn.WriteTo(b, session.raddr)
|
n, err := conn.WriteTo(b, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
|
||||||
|
// use the standard method in udp.go for these.
|
||||||
// setUDPSocketOptions sets the UDP socket options.
|
func setUDPSocketOptions(*net.UDPConn) error { return nil }
|
||||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
func parseDstFromOOB([]byte, net.IP) net.IP { return nil }
|
||||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
15
vendor/github.com/miekg/dns/version.go
generated
vendored
Normal file
15
vendor/github.com/miekg/dns/version.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Version is current version of this library.
|
||||||
|
var Version = V{1, 0, 4}
|
||||||
|
|
||||||
|
// V holds the version of this library.
|
||||||
|
type V struct {
|
||||||
|
Major, Minor, Patch int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v V) String() string {
|
||||||
|
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||||
|
}
|
64
vendor/github.com/miekg/dns/xfr.go
generated
vendored
64
vendor/github.com/miekg/dns/xfr.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ type Transfer struct {
|
||||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
||||||
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
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)
|
||||||
tsigTimersOnly bool
|
tsigTimersOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,18 +51,18 @@ func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
||||||
env = make(chan *Envelope)
|
env = make(chan *Envelope)
|
||||||
go func() {
|
go func() {
|
||||||
if q.Question[0].Qtype == TypeAXFR {
|
if q.Question[0].Qtype == TypeAXFR {
|
||||||
go t.inAxfr(q.Id, env)
|
go t.inAxfr(q, env)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if q.Question[0].Qtype == TypeIXFR {
|
if q.Question[0].Qtype == TypeIXFR {
|
||||||
go t.inIxfr(q.Id, env)
|
go t.inIxfr(q, env)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
|
||||||
first := true
|
first := true
|
||||||
defer t.Close()
|
defer t.Close()
|
||||||
defer close(c)
|
defer close(c)
|
||||||
|
@ -76,11 +77,15 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
||||||
c <- &Envelope{nil, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != in.Id {
|
if q.Id != in.Id {
|
||||||
c <- &Envelope{in.Answer, ErrId}
|
c <- &Envelope{in.Answer, ErrId}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if first {
|
if first {
|
||||||
|
if in.Rcode != RcodeSuccess {
|
||||||
|
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||||
|
return
|
||||||
|
}
|
||||||
if !isSOAFirst(in) {
|
if !isSOAFirst(in) {
|
||||||
c <- &Envelope{in.Answer, ErrSoa}
|
c <- &Envelope{in.Answer, ErrSoa}
|
||||||
return
|
return
|
||||||
|
@ -105,9 +110,11 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
|
||||||
serial := uint32(0) // The first serial seen is the current server serial
|
serial := uint32(0) // The first serial seen is the current server serial
|
||||||
first := true
|
axfr := true
|
||||||
|
n := 0
|
||||||
|
qser := q.Ns[0].(*SOA).Serial
|
||||||
defer t.Close()
|
defer t.Close()
|
||||||
defer close(c)
|
defer close(c)
|
||||||
timeout := dnsTimeout
|
timeout := dnsTimeout
|
||||||
|
@ -121,17 +128,15 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||||
c <- &Envelope{nil, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != in.Id {
|
if q.Id != in.Id {
|
||||||
c <- &Envelope{in.Answer, ErrId}
|
c <- &Envelope{in.Answer, ErrId}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if first {
|
if in.Rcode != RcodeSuccess {
|
||||||
// A single SOA RR signals "no changes"
|
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||||
if len(in.Answer) == 1 && isSOAFirst(in) {
|
return
|
||||||
c <- &Envelope{in.Answer, nil}
|
}
|
||||||
return
|
if n == 0 {
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the returned answer is ok
|
// Check if the returned answer is ok
|
||||||
if !isSOAFirst(in) {
|
if !isSOAFirst(in) {
|
||||||
c <- &Envelope{in.Answer, ErrSoa}
|
c <- &Envelope{in.Answer, ErrSoa}
|
||||||
|
@ -139,21 +144,30 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||||
}
|
}
|
||||||
// This serial is important
|
// This serial is important
|
||||||
serial = in.Answer[0].(*SOA).Serial
|
serial = in.Answer[0].(*SOA).Serial
|
||||||
first = !first
|
// Check if there are no changes in zone
|
||||||
|
if qser >= serial {
|
||||||
|
c <- &Envelope{in.Answer, nil}
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we need to check each message for SOA records, to see what we need to do
|
// Now we need to check each message for SOA records, to see what we need to do
|
||||||
if !first {
|
t.tsigTimersOnly = true
|
||||||
t.tsigTimersOnly = true
|
for _, rr := range in.Answer {
|
||||||
// If the last record in the IXFR contains the servers' SOA, we should quit
|
if v, ok := rr.(*SOA); ok {
|
||||||
if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
|
|
||||||
if v.Serial == serial {
|
if v.Serial == serial {
|
||||||
c <- &Envelope{in.Answer, nil}
|
n++
|
||||||
return
|
// quit if it's a full axfr or the the servers' SOA is repeated the third time
|
||||||
|
if axfr && n == 2 || n == 3 {
|
||||||
|
c <- &Envelope{in.Answer, nil}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if axfr {
|
||||||
|
// it's an ixfr
|
||||||
|
axfr = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c <- &Envelope{in.Answer, nil}
|
|
||||||
}
|
}
|
||||||
|
c <- &Envelope{in.Answer, nil}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,3 +256,5 @@ func isSOALast(in *Msg) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errXFR = "bad xfr rcode: %d"
|
||||||
|
|
118
vendor/github.com/miekg/dns/zcompress.go
generated
vendored
Normal file
118
vendor/github.com/miekg/dns/zcompress.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
func compressionLenHelperType(c map[string]int, r RR) {
|
||||||
|
switch x := r.(type) {
|
||||||
|
case *AFSDB:
|
||||||
|
compressionLenHelper(c, x.Hostname)
|
||||||
|
case *CNAME:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
|
case *DNAME:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
|
case *HIP:
|
||||||
|
for i := range x.RendezvousServers {
|
||||||
|
compressionLenHelper(c, x.RendezvousServers[i])
|
||||||
|
}
|
||||||
|
case *KX:
|
||||||
|
compressionLenHelper(c, x.Exchanger)
|
||||||
|
case *LP:
|
||||||
|
compressionLenHelper(c, x.Fqdn)
|
||||||
|
case *MB:
|
||||||
|
compressionLenHelper(c, x.Mb)
|
||||||
|
case *MD:
|
||||||
|
compressionLenHelper(c, x.Md)
|
||||||
|
case *MF:
|
||||||
|
compressionLenHelper(c, x.Mf)
|
||||||
|
case *MG:
|
||||||
|
compressionLenHelper(c, x.Mg)
|
||||||
|
case *MINFO:
|
||||||
|
compressionLenHelper(c, x.Rmail)
|
||||||
|
compressionLenHelper(c, x.Email)
|
||||||
|
case *MR:
|
||||||
|
compressionLenHelper(c, x.Mr)
|
||||||
|
case *MX:
|
||||||
|
compressionLenHelper(c, x.Mx)
|
||||||
|
case *NAPTR:
|
||||||
|
compressionLenHelper(c, x.Replacement)
|
||||||
|
case *NS:
|
||||||
|
compressionLenHelper(c, x.Ns)
|
||||||
|
case *NSAPPTR:
|
||||||
|
compressionLenHelper(c, x.Ptr)
|
||||||
|
case *NSEC:
|
||||||
|
compressionLenHelper(c, x.NextDomain)
|
||||||
|
case *PTR:
|
||||||
|
compressionLenHelper(c, x.Ptr)
|
||||||
|
case *PX:
|
||||||
|
compressionLenHelper(c, x.Map822)
|
||||||
|
compressionLenHelper(c, x.Mapx400)
|
||||||
|
case *RP:
|
||||||
|
compressionLenHelper(c, x.Mbox)
|
||||||
|
compressionLenHelper(c, x.Txt)
|
||||||
|
case *RRSIG:
|
||||||
|
compressionLenHelper(c, x.SignerName)
|
||||||
|
case *RT:
|
||||||
|
compressionLenHelper(c, x.Host)
|
||||||
|
case *SIG:
|
||||||
|
compressionLenHelper(c, x.SignerName)
|
||||||
|
case *SOA:
|
||||||
|
compressionLenHelper(c, x.Ns)
|
||||||
|
compressionLenHelper(c, x.Mbox)
|
||||||
|
case *SRV:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
|
case *TALINK:
|
||||||
|
compressionLenHelper(c, x.PreviousName)
|
||||||
|
compressionLenHelper(c, x.NextName)
|
||||||
|
case *TKEY:
|
||||||
|
compressionLenHelper(c, x.Algorithm)
|
||||||
|
case *TSIG:
|
||||||
|
compressionLenHelper(c, x.Algorithm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
||||||
|
switch x := r.(type) {
|
||||||
|
case *AFSDB:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Hostname)
|
||||||
|
return k1, ok1
|
||||||
|
case *CNAME:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Target)
|
||||||
|
return k1, ok1
|
||||||
|
case *MB:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mb)
|
||||||
|
return k1, ok1
|
||||||
|
case *MD:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Md)
|
||||||
|
return k1, ok1
|
||||||
|
case *MF:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mf)
|
||||||
|
return k1, ok1
|
||||||
|
case *MG:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mg)
|
||||||
|
return k1, ok1
|
||||||
|
case *MINFO:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
||||||
|
k2, ok2 := compressionLenSearch(c, x.Email)
|
||||||
|
return k1 + k2, ok1 && ok2
|
||||||
|
case *MR:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mr)
|
||||||
|
return k1, ok1
|
||||||
|
case *MX:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mx)
|
||||||
|
return k1, ok1
|
||||||
|
case *NS:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||||
|
return k1, ok1
|
||||||
|
case *PTR:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Ptr)
|
||||||
|
return k1, ok1
|
||||||
|
case *RT:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Host)
|
||||||
|
return k1, ok1
|
||||||
|
case *SOA:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||||
|
k2, ok2 := compressionLenSearch(c, x.Mbox)
|
||||||
|
return k1 + k2, ok1 && ok2
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
120
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
120
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
|
@ -1,5 +1,4 @@
|
||||||
// *** DO NOT MODIFY ***
|
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
|
||||||
// AUTOGENERATED BY go generate from msg_generate.go
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -61,6 +60,20 @@ func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bo
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
headerEnd := off
|
||||||
|
off, err = packStringTxt(rr.Txt, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
rr.Header().Rdlength = uint16(off - headerEnd)
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -175,6 +188,28 @@ func (rr *CNAME) pack(msg []byte, off int, compression map[string]int, compress
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *CSYNC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
headerEnd := off
|
||||||
|
off, err = packUint32(rr.Serial, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
off, err = packUint16(rr.Flags, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
off, err = packDataNsec(rr.TypeBitMap, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
rr.Header().Rdlength = uint16(off - headerEnd)
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *DHCID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (rr *DHCID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -801,10 +836,12 @@ func (rr *NSEC3) pack(msg []byte, off int, compression map[string]int, compress
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
if rr.Salt == "-" { /* do nothing, empty salt */
|
// Only pack salt if value is not "-", i.e. empty
|
||||||
}
|
if rr.Salt != "-" {
|
||||||
if err != nil {
|
off, err = packStringHex(rr.Salt, msg, off)
|
||||||
return off, err
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
off, err = packUint8(rr.HashLength, msg, off)
|
off, err = packUint8(rr.HashLength, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -844,10 +881,12 @@ func (rr *NSEC3PARAM) pack(msg []byte, off int, compression map[string]int, comp
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
if rr.Salt == "-" { /* do nothing, empty salt */
|
// Only pack salt if value is not "-", i.e. empty
|
||||||
}
|
if rr.Salt != "-" {
|
||||||
if err != nil {
|
off, err = packStringHex(rr.Salt, msg, off)
|
||||||
return off, err
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rr.Header().Rdlength = uint16(off - headerEnd)
|
rr.Header().Rdlength = uint16(off - headerEnd)
|
||||||
return off, nil
|
return off, nil
|
||||||
|
@ -1285,7 +1324,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
off, err = packString(rr.Key, msg, off)
|
off, err = packStringHex(rr.Key, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
@ -1293,7 +1332,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
off, err = packString(rr.OtherData, msg, off)
|
off, err = packStringHex(rr.OtherData, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
@ -1524,6 +1563,23 @@ func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
|
rr := new(AVC)
|
||||||
|
rr.Hdr = h
|
||||||
|
if noRdata(h) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
rdStart := off
|
||||||
|
_ = rdStart
|
||||||
|
|
||||||
|
rr.Txt, off, err = unpackStringTxt(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
|
||||||
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
|
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
rr := new(CAA)
|
rr := new(CAA)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
@ -1686,6 +1742,37 @@ func unpackCNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unpackCSYNC(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
|
rr := new(CSYNC)
|
||||||
|
rr.Hdr = h
|
||||||
|
if noRdata(h) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
rdStart := off
|
||||||
|
_ = rdStart
|
||||||
|
|
||||||
|
rr.Serial, off, err = unpackUint32(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
if off == len(msg) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
rr.Flags, off, err = unpackUint16(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
if off == len(msg) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
|
||||||
func unpackDHCID(h RR_Header, msg []byte, off int) (RR, int, error) {
|
func unpackDHCID(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
rr := new(DHCID)
|
rr := new(DHCID)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
@ -3230,13 +3317,10 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return rr, off, nil
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
rr.Key, off, err = unpackString(msg, off)
|
rr.Key, off, err = unpackStringHex(msg, off, off+int(rr.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
if off == len(msg) {
|
|
||||||
return rr, off, nil
|
|
||||||
}
|
|
||||||
rr.OtherLen, off, err = unpackUint16(msg, off)
|
rr.OtherLen, off, err = unpackUint16(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
|
@ -3244,7 +3328,7 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return rr, off, nil
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
rr.OtherData, off, err = unpackString(msg, off)
|
rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
@ -3463,11 +3547,13 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
|
||||||
TypeAAAA: unpackAAAA,
|
TypeAAAA: unpackAAAA,
|
||||||
TypeAFSDB: unpackAFSDB,
|
TypeAFSDB: unpackAFSDB,
|
||||||
TypeANY: unpackANY,
|
TypeANY: unpackANY,
|
||||||
|
TypeAVC: unpackAVC,
|
||||||
TypeCAA: unpackCAA,
|
TypeCAA: unpackCAA,
|
||||||
TypeCDNSKEY: unpackCDNSKEY,
|
TypeCDNSKEY: unpackCDNSKEY,
|
||||||
TypeCDS: unpackCDS,
|
TypeCDS: unpackCDS,
|
||||||
TypeCERT: unpackCERT,
|
TypeCERT: unpackCERT,
|
||||||
TypeCNAME: unpackCNAME,
|
TypeCNAME: unpackCNAME,
|
||||||
|
TypeCSYNC: unpackCSYNC,
|
||||||
TypeDHCID: unpackDHCID,
|
TypeDHCID: unpackDHCID,
|
||||||
TypeDLV: unpackDLV,
|
TypeDLV: unpackDLV,
|
||||||
TypeDNAME: unpackDNAME,
|
TypeDNAME: unpackDNAME,
|
||||||
|
|
97
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
97
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
|
@ -1,5 +1,4 @@
|
||||||
// *** DO NOT MODIFY ***
|
// Code generated by "go run types_generate.go"; DO NOT EDIT.
|
||||||
// AUTOGENERATED BY go generate from type_generate.go
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -14,11 +13,13 @@ 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) },
|
||||||
|
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) },
|
||||||
TypeCDS: func() RR { return new(CDS) },
|
TypeCDS: func() RR { return new(CDS) },
|
||||||
TypeCERT: func() RR { return new(CERT) },
|
TypeCERT: func() RR { return new(CERT) },
|
||||||
TypeCNAME: func() RR { return new(CNAME) },
|
TypeCNAME: func() RR { return new(CNAME) },
|
||||||
|
TypeCSYNC: func() RR { return new(CSYNC) },
|
||||||
TypeDHCID: func() RR { return new(DHCID) },
|
TypeDHCID: func() RR { return new(DHCID) },
|
||||||
TypeDLV: func() RR { return new(DLV) },
|
TypeDLV: func() RR { return new(DLV) },
|
||||||
TypeDNAME: func() RR { return new(DNAME) },
|
TypeDNAME: func() RR { return new(DNAME) },
|
||||||
|
@ -86,12 +87,14 @@ var TypeToString = map[uint16]string{
|
||||||
TypeAFSDB: "AFSDB",
|
TypeAFSDB: "AFSDB",
|
||||||
TypeANY: "ANY",
|
TypeANY: "ANY",
|
||||||
TypeATMA: "ATMA",
|
TypeATMA: "ATMA",
|
||||||
|
TypeAVC: "AVC",
|
||||||
TypeAXFR: "AXFR",
|
TypeAXFR: "AXFR",
|
||||||
TypeCAA: "CAA",
|
TypeCAA: "CAA",
|
||||||
TypeCDNSKEY: "CDNSKEY",
|
TypeCDNSKEY: "CDNSKEY",
|
||||||
TypeCDS: "CDS",
|
TypeCDS: "CDS",
|
||||||
TypeCERT: "CERT",
|
TypeCERT: "CERT",
|
||||||
TypeCNAME: "CNAME",
|
TypeCNAME: "CNAME",
|
||||||
|
TypeCSYNC: "CSYNC",
|
||||||
TypeDHCID: "DHCID",
|
TypeDHCID: "DHCID",
|
||||||
TypeDLV: "DLV",
|
TypeDLV: "DLV",
|
||||||
TypeDNAME: "DNAME",
|
TypeDNAME: "DNAME",
|
||||||
|
@ -161,16 +164,17 @@ var TypeToString = map[uint16]string{
|
||||||
TypeNSAPPTR: "NSAP-PTR",
|
TypeNSAPPTR: "NSAP-PTR",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header() functions
|
|
||||||
func (rr *A) Header() *RR_Header { return &rr.Hdr }
|
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 *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 }
|
||||||
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CSYNC) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
|
func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
|
func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
|
func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
@ -252,9 +256,16 @@ func (rr *ANY) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
func (rr *AVC) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
for _, x := range rr.Txt {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
func (rr *CAA) len() int {
|
func (rr *CAA) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Flag
|
l++ // Flag
|
||||||
l += len(rr.Tag) + 1
|
l += len(rr.Tag) + 1
|
||||||
l += len(rr.Value)
|
l += len(rr.Value)
|
||||||
return l
|
return l
|
||||||
|
@ -263,7 +274,7 @@ func (rr *CERT) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // Type
|
l += 2 // Type
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
|
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -285,16 +296,16 @@ func (rr *DNAME) len() int {
|
||||||
func (rr *DNSKEY) len() int {
|
func (rr *DNSKEY) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // Flags
|
l += 2 // Flags
|
||||||
l += 1 // Protocol
|
l++ // Protocol
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *DS) len() int {
|
func (rr *DS) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += 1 // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -333,10 +344,10 @@ func (rr *HINFO) len() int {
|
||||||
}
|
}
|
||||||
func (rr *HIP) len() int {
|
func (rr *HIP) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // HitLength
|
l++ // HitLength
|
||||||
l += 1 // PublicKeyAlgorithm
|
l++ // PublicKeyAlgorithm
|
||||||
l += 2 // PublicKeyLength
|
l += 2 // PublicKeyLength
|
||||||
l += len(rr.Hit)/2 + 1
|
l += len(rr.Hit) / 2
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
for _, x := range rr.RendezvousServers {
|
for _, x := range rr.RendezvousServers {
|
||||||
l += len(x) + 1
|
l += len(x) + 1
|
||||||
|
@ -363,10 +374,10 @@ func (rr *L64) len() int {
|
||||||
}
|
}
|
||||||
func (rr *LOC) len() int {
|
func (rr *LOC) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Version
|
l++ // Version
|
||||||
l += 1 // Size
|
l++ // Size
|
||||||
l += 1 // HorizPre
|
l++ // HorizPre
|
||||||
l += 1 // VertPre
|
l++ // VertPre
|
||||||
l += 4 // Latitude
|
l += 4 // Latitude
|
||||||
l += 4 // Longitude
|
l += 4 // Longitude
|
||||||
l += 4 // Altitude
|
l += 4 // Altitude
|
||||||
|
@ -455,11 +466,11 @@ func (rr *NSAPPTR) len() int {
|
||||||
}
|
}
|
||||||
func (rr *NSEC3PARAM) len() int {
|
func (rr *NSEC3PARAM) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Hash
|
l++ // Hash
|
||||||
l += 1 // Flags
|
l++ // Flags
|
||||||
l += 2 // Iterations
|
l += 2 // Iterations
|
||||||
l += 1 // SaltLength
|
l++ // SaltLength
|
||||||
l += len(rr.Salt)/2 + 1
|
l += len(rr.Salt) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *OPENPGPKEY) len() int {
|
func (rr *OPENPGPKEY) len() int {
|
||||||
|
@ -487,8 +498,8 @@ func (rr *RFC3597) len() int {
|
||||||
func (rr *RKEY) len() int {
|
func (rr *RKEY) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // Flags
|
l += 2 // Flags
|
||||||
l += 1 // Protocol
|
l++ // Protocol
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -501,8 +512,8 @@ func (rr *RP) len() int {
|
||||||
func (rr *RRSIG) len() int {
|
func (rr *RRSIG) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // TypeCovered
|
l += 2 // TypeCovered
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += 1 // Labels
|
l++ // Labels
|
||||||
l += 4 // OrigTtl
|
l += 4 // OrigTtl
|
||||||
l += 4 // Expiration
|
l += 4 // Expiration
|
||||||
l += 4 // Inception
|
l += 4 // Inception
|
||||||
|
@ -519,9 +530,9 @@ func (rr *RT) len() int {
|
||||||
}
|
}
|
||||||
func (rr *SMIMEA) len() int {
|
func (rr *SMIMEA) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Usage
|
l++ // Usage
|
||||||
l += 1 // Selector
|
l++ // Selector
|
||||||
l += 1 // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -553,16 +564,16 @@ func (rr *SRV) len() int {
|
||||||
}
|
}
|
||||||
func (rr *SSHFP) len() int {
|
func (rr *SSHFP) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += 1 // Type
|
l++ // Type
|
||||||
l += len(rr.FingerPrint)/2 + 1
|
l += len(rr.FingerPrint)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TA) len() int {
|
func (rr *TA) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l += 1 // Algorithm
|
l++ // Algorithm
|
||||||
l += 1 // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -580,16 +591,16 @@ func (rr *TKEY) len() int {
|
||||||
l += 2 // Mode
|
l += 2 // Mode
|
||||||
l += 2 // Error
|
l += 2 // Error
|
||||||
l += 2 // KeySize
|
l += 2 // KeySize
|
||||||
l += len(rr.Key) + 1
|
l += len(rr.Key) / 2
|
||||||
l += 2 // OtherLen
|
l += 2 // OtherLen
|
||||||
l += len(rr.OtherData) + 1
|
l += len(rr.OtherData) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TLSA) len() int {
|
func (rr *TLSA) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l += 1 // Usage
|
l++ // Usage
|
||||||
l += 1 // Selector
|
l++ // Selector
|
||||||
l += 1 // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -599,11 +610,11 @@ func (rr *TSIG) len() int {
|
||||||
l += 6 // TimeSigned
|
l += 6 // TimeSigned
|
||||||
l += 2 // Fudge
|
l += 2 // Fudge
|
||||||
l += 2 // MACSize
|
l += 2 // MACSize
|
||||||
l += len(rr.MAC)/2 + 1
|
l += len(rr.MAC) / 2
|
||||||
l += 2 // OrigId
|
l += 2 // OrigId
|
||||||
l += 2 // Error
|
l += 2 // Error
|
||||||
l += 2 // OtherLen
|
l += 2 // OtherLen
|
||||||
l += len(rr.OtherData)/2 + 1
|
l += len(rr.OtherData) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TXT) len() int {
|
func (rr *TXT) len() int {
|
||||||
|
@ -649,6 +660,11 @@ func (rr *AFSDB) copy() RR {
|
||||||
func (rr *ANY) copy() RR {
|
func (rr *ANY) copy() RR {
|
||||||
return &ANY{*rr.Hdr.copyHeader()}
|
return &ANY{*rr.Hdr.copyHeader()}
|
||||||
}
|
}
|
||||||
|
func (rr *AVC) copy() RR {
|
||||||
|
Txt := make([]string, len(rr.Txt))
|
||||||
|
copy(Txt, rr.Txt)
|
||||||
|
return &AVC{*rr.Hdr.copyHeader(), Txt}
|
||||||
|
}
|
||||||
func (rr *CAA) copy() RR {
|
func (rr *CAA) copy() RR {
|
||||||
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
||||||
}
|
}
|
||||||
|
@ -658,6 +674,11 @@ func (rr *CERT) copy() RR {
|
||||||
func (rr *CNAME) copy() RR {
|
func (rr *CNAME) copy() RR {
|
||||||
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
|
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
|
||||||
}
|
}
|
||||||
|
func (rr *CSYNC) copy() RR {
|
||||||
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
|
return &CSYNC{*rr.Hdr.copyHeader(), rr.Serial, rr.Flags, TypeBitMap}
|
||||||
|
}
|
||||||
func (rr *DHCID) copy() RR {
|
func (rr *DHCID) copy() RR {
|
||||||
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
|
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
|
||||||
}
|
}
|
||||||
|
|
7
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
7
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
|
@ -12,9 +12,10 @@ import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/blowfish"
|
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/blowfish"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -205,7 +206,6 @@ func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
|
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
|
||||||
|
|
||||||
csalt, err := base64Decode(salt)
|
csalt, err := base64Decode(salt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -213,7 +213,8 @@ func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cip
|
||||||
|
|
||||||
// Bug compatibility with C bcrypt implementations. They use the trailing
|
// Bug compatibility with C bcrypt implementations. They use the trailing
|
||||||
// NULL in the key string during expansion.
|
// NULL in the key string during expansion.
|
||||||
ckey := append(key, 0)
|
// We copy the key to prevent changing the underlying array.
|
||||||
|
ckey := append(key[:len(key):len(key)], 0)
|
||||||
|
|
||||||
c, err := blowfish.NewSaltedCipher(ckey, csalt)
|
c, err := blowfish.NewSaltedCipher(ckey, csalt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
4
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
4
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
|
@ -6,7 +6,7 @@
|
||||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
package blowfish // import "golang.org/x/crypto/blowfish"
|
||||||
|
|
||||||
// The code is a port of Bruce Schneier's C implementation.
|
// The code is a port of Bruce Schneier's C implementation.
|
||||||
// See http://www.schneier.com/blowfish.html.
|
// See https://www.schneier.com/blowfish.html.
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func NewCipher(key []byte) (*Cipher, error) {
|
||||||
|
|
||||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
||||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
||||||
// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
|
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
|
||||||
// bytes.
|
// bytes.
|
||||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
||||||
if len(salt) == 0 {
|
if len(salt) == 0 {
|
||||||
|
|
2
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
2
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// The startup permutation array and substitution boxes.
|
// The startup permutation array and substitution boxes.
|
||||||
// They are the hexadecimal digits of PI; see:
|
// They are the hexadecimal digits of PI; see:
|
||||||
// http://www.schneier.com/code/constants.txt.
|
// https://www.schneier.com/code/constants.txt.
|
||||||
|
|
||||||
package blowfish
|
package blowfish
|
||||||
|
|
||||||
|
|
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
Normal file
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
// 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.
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 PublicKey, privateKey PrivateKey, err error) {
|
||||||
|
if rand == nil {
|
||||||
|
rand = cryptorand.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey = make([]byte, PrivateKeySize)
|
||||||
|
publicKey = make([]byte, PublicKeySize)
|
||||||
|
_, err = io.ReadFull(rand, privateKey[:32])
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
digest := sha512.Sum512(privateKey[:32])
|
||||||
|
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)
|
||||||
|
|
||||||
|
copy(privateKey[32:], publicKeyBytes[:])
|
||||||
|
copy(publicKey, publicKeyBytes[:])
|
||||||
|
|
||||||
|
return publicKey, privateKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 b [32]byte
|
||||||
|
copy(b[:], sig[32:])
|
||||||
|
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
||||||
|
|
||||||
|
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
Normal file
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
667
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
667
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
|
@ -9,28 +9,73 @@ package ocsp // import "golang.org/x/crypto/ocsp"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
_ "crypto/sha1"
|
_ "crypto/sha1"
|
||||||
|
_ "crypto/sha256"
|
||||||
|
_ "crypto/sha512"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
|
var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
|
||||||
|
|
||||||
// These are internal structures that reflect the ASN.1 structure of an OCSP
|
// ResponseStatus contains the result of an OCSP request. See
|
||||||
// response. See RFC 2560, section 4.2.
|
// https://tools.ietf.org/html/rfc6960#section-2.3
|
||||||
|
type ResponseStatus int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ocspSuccess = 0
|
Success ResponseStatus = 0
|
||||||
ocspMalformed = 1
|
Malformed ResponseStatus = 1
|
||||||
ocspInternalError = 2
|
InternalError ResponseStatus = 2
|
||||||
ocspTryLater = 3
|
TryLater ResponseStatus = 3
|
||||||
ocspSigRequired = 4
|
// Status code four is unused in OCSP. See
|
||||||
ocspUnauthorized = 5
|
// https://tools.ietf.org/html/rfc6960#section-4.2.1
|
||||||
|
SignatureRequired ResponseStatus = 5
|
||||||
|
Unauthorized ResponseStatus = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (r ResponseStatus) String() string {
|
||||||
|
switch r {
|
||||||
|
case Success:
|
||||||
|
return "success"
|
||||||
|
case Malformed:
|
||||||
|
return "malformed"
|
||||||
|
case InternalError:
|
||||||
|
return "internal error"
|
||||||
|
case TryLater:
|
||||||
|
return "try later"
|
||||||
|
case SignatureRequired:
|
||||||
|
return "signature required"
|
||||||
|
case Unauthorized:
|
||||||
|
return "unauthorized"
|
||||||
|
default:
|
||||||
|
return "unknown OCSP status: " + strconv.Itoa(int(r))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResponseError is an error that may be returned by ParseResponse to indicate
|
||||||
|
// that the response itself is an error, not just that its indicating that a
|
||||||
|
// certificate is revoked, unknown, etc.
|
||||||
|
type ResponseError struct {
|
||||||
|
Status ResponseStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ResponseError) Error() string {
|
||||||
|
return "ocsp: error from server: " + r.Status.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are internal structures that reflect the ASN.1 structure of an OCSP
|
||||||
|
// response. See RFC 2560, section 4.2.
|
||||||
|
|
||||||
type certID struct {
|
type certID struct {
|
||||||
HashAlgorithm pkix.AlgorithmIdentifier
|
HashAlgorithm pkix.AlgorithmIdentifier
|
||||||
NameHash []byte
|
NameHash []byte
|
||||||
|
@ -38,9 +83,24 @@ type certID struct {
|
||||||
SerialNumber *big.Int
|
SerialNumber *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc2560#section-4.1.1
|
||||||
|
type ocspRequest struct {
|
||||||
|
TBSRequest tbsRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
type tbsRequest struct {
|
||||||
|
Version int `asn1:"explicit,tag:0,default:0,optional"`
|
||||||
|
RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"`
|
||||||
|
RequestList []request
|
||||||
|
}
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
Cert certID
|
||||||
|
}
|
||||||
|
|
||||||
type responseASN1 struct {
|
type responseASN1 struct {
|
||||||
Status asn1.Enumerated
|
Status asn1.Enumerated
|
||||||
Response responseBytes `asn1:"explicit,tag:0"`
|
Response responseBytes `asn1:"explicit,tag:0,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseBytes struct {
|
type responseBytes struct {
|
||||||
|
@ -56,26 +116,26 @@ type basicResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseData struct {
|
type responseData struct {
|
||||||
Raw asn1.RawContent
|
Raw asn1.RawContent
|
||||||
Version int `asn1:"optional,default:1,explicit,tag:0"`
|
Version int `asn1:"optional,default:0,explicit,tag:0"`
|
||||||
RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
|
RawResponderID asn1.RawValue
|
||||||
KeyHash []byte `asn1:"optional,explicit,tag:2"`
|
ProducedAt time.Time `asn1:"generalized"`
|
||||||
ProducedAt time.Time
|
Responses []singleResponse
|
||||||
Responses []singleResponse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type singleResponse struct {
|
type singleResponse struct {
|
||||||
CertID certID
|
CertID certID
|
||||||
Good asn1.Flag `asn1:"explicit,tag:0,optional"`
|
Good asn1.Flag `asn1:"tag:0,optional"`
|
||||||
Revoked revokedInfo `asn1:"explicit,tag:1,optional"`
|
Revoked revokedInfo `asn1:"tag:1,optional"`
|
||||||
Unknown asn1.Flag `asn1:"explicit,tag:2,optional"`
|
Unknown asn1.Flag `asn1:"tag:2,optional"`
|
||||||
ThisUpdate time.Time
|
ThisUpdate time.Time `asn1:"generalized"`
|
||||||
NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
|
NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
|
||||||
|
SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type revokedInfo struct {
|
type revokedInfo struct {
|
||||||
RevocationTime time.Time
|
RevocationTime time.Time `asn1:"generalized"`
|
||||||
Reason int `asn1:"explicit,tag:0,optional"`
|
Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -86,61 +146,206 @@ var (
|
||||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
||||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
||||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
||||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
|
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
||||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
||||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
||||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
||||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
|
||||||
|
crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
|
||||||
|
crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
|
||||||
|
crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
|
||||||
|
crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
||||||
|
var signatureAlgorithmDetails = []struct {
|
||||||
|
algo x509.SignatureAlgorithm
|
||||||
|
oid asn1.ObjectIdentifier
|
||||||
|
pubKeyAlgo x509.PublicKeyAlgorithm
|
||||||
|
hash crypto.Hash
|
||||||
|
}{
|
||||||
|
{x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
|
||||||
|
{x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
|
||||||
|
{x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
||||||
|
{x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
|
||||||
|
{x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
|
||||||
|
{x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
|
||||||
|
{x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
|
||||||
|
{x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
|
||||||
|
{x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
|
||||||
|
{x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
|
||||||
|
{x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
|
||||||
|
{x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
||||||
|
func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
||||||
|
var pubType x509.PublicKeyAlgorithm
|
||||||
|
|
||||||
|
switch pub := pub.(type) {
|
||||||
|
case *rsa.PublicKey:
|
||||||
|
pubType = x509.RSA
|
||||||
|
hashFunc = crypto.SHA256
|
||||||
|
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
|
||||||
|
sigAlgo.Parameters = asn1.RawValue{
|
||||||
|
Tag: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
pubType = x509.ECDSA
|
||||||
|
|
||||||
|
switch pub.Curve {
|
||||||
|
case elliptic.P224(), elliptic.P256():
|
||||||
|
hashFunc = crypto.SHA256
|
||||||
|
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
||||||
|
case elliptic.P384():
|
||||||
|
hashFunc = crypto.SHA384
|
||||||
|
sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
|
||||||
|
case elliptic.P521():
|
||||||
|
hashFunc = crypto.SHA512
|
||||||
|
sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
|
||||||
|
default:
|
||||||
|
err = errors.New("x509: unknown elliptic curve")
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = errors.New("x509: only RSA and ECDSA keys supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestedSigAlgo == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, details := range signatureAlgorithmDetails {
|
||||||
|
if details.algo == requestedSigAlgo {
|
||||||
|
if details.pubKeyAlgo != pubType {
|
||||||
|
err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sigAlgo.Algorithm, hashFunc = details.oid, details.hash
|
||||||
|
if hashFunc == 0 {
|
||||||
|
err = errors.New("x509: cannot sign with hash function requested")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
err = errors.New("x509: unknown SignatureAlgorithm")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(agl): this is taken from crypto/x509 and so should probably be exported
|
// TODO(agl): this is taken from crypto/x509 and so should probably be exported
|
||||||
// from crypto/x509 or crypto/x509/pkix.
|
// from crypto/x509 or crypto/x509/pkix.
|
||||||
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
|
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
|
||||||
switch {
|
for _, details := range signatureAlgorithmDetails {
|
||||||
case oid.Equal(oidSignatureMD2WithRSA):
|
if oid.Equal(details.oid) {
|
||||||
return x509.MD2WithRSA
|
return details.algo
|
||||||
case oid.Equal(oidSignatureMD5WithRSA):
|
}
|
||||||
return x509.MD5WithRSA
|
|
||||||
case oid.Equal(oidSignatureSHA1WithRSA):
|
|
||||||
return x509.SHA1WithRSA
|
|
||||||
case oid.Equal(oidSignatureSHA256WithRSA):
|
|
||||||
return x509.SHA256WithRSA
|
|
||||||
case oid.Equal(oidSignatureSHA384WithRSA):
|
|
||||||
return x509.SHA384WithRSA
|
|
||||||
case oid.Equal(oidSignatureSHA512WithRSA):
|
|
||||||
return x509.SHA512WithRSA
|
|
||||||
case oid.Equal(oidSignatureDSAWithSHA1):
|
|
||||||
return x509.DSAWithSHA1
|
|
||||||
case oid.Equal(oidSignatureDSAWithSHA256):
|
|
||||||
return x509.DSAWithSHA256
|
|
||||||
case oid.Equal(oidSignatureECDSAWithSHA1):
|
|
||||||
return x509.ECDSAWithSHA1
|
|
||||||
case oid.Equal(oidSignatureECDSAWithSHA256):
|
|
||||||
return x509.ECDSAWithSHA256
|
|
||||||
case oid.Equal(oidSignatureECDSAWithSHA384):
|
|
||||||
return x509.ECDSAWithSHA384
|
|
||||||
case oid.Equal(oidSignatureECDSAWithSHA512):
|
|
||||||
return x509.ECDSAWithSHA512
|
|
||||||
}
|
}
|
||||||
return x509.UnknownSignatureAlgorithm
|
return x509.UnknownSignatureAlgorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form.
|
||||||
|
func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
|
||||||
|
for hash, oid := range hashOIDs {
|
||||||
|
if oid.Equal(target) {
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crypto.Hash(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
|
||||||
|
for hash, oid := range hashOIDs {
|
||||||
|
if hash == target {
|
||||||
|
return oid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// This is the exposed reflection of the internal OCSP structures.
|
// This is the exposed reflection of the internal OCSP structures.
|
||||||
|
|
||||||
|
// The status values that can be expressed in OCSP. See RFC 6960.
|
||||||
const (
|
const (
|
||||||
// Good means that the certificate is valid.
|
// Good means that the certificate is valid.
|
||||||
Good = iota
|
Good = iota
|
||||||
// Revoked means that the certificate has been deliberately revoked.
|
// Revoked means that the certificate has been deliberately revoked.
|
||||||
Revoked = iota
|
Revoked
|
||||||
// Unknown means that the OCSP responder doesn't know about the certificate.
|
// Unknown means that the OCSP responder doesn't know about the certificate.
|
||||||
Unknown = iota
|
Unknown
|
||||||
// ServerFailed means that the OCSP responder failed to process the request.
|
// ServerFailed is unused and was never used (see
|
||||||
ServerFailed = iota
|
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
||||||
|
// return a ResponseError when an error response is parsed.
|
||||||
|
ServerFailed
|
||||||
)
|
)
|
||||||
|
|
||||||
// Response represents an OCSP response. See RFC 2560.
|
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
||||||
|
const (
|
||||||
|
Unspecified = 0
|
||||||
|
KeyCompromise = 1
|
||||||
|
CACompromise = 2
|
||||||
|
AffiliationChanged = 3
|
||||||
|
Superseded = 4
|
||||||
|
CessationOfOperation = 5
|
||||||
|
CertificateHold = 6
|
||||||
|
|
||||||
|
RemoveFromCRL = 8
|
||||||
|
PrivilegeWithdrawn = 9
|
||||||
|
AACompromise = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request represents an OCSP request. See RFC 6960.
|
||||||
|
type Request struct {
|
||||||
|
HashAlgorithm crypto.Hash
|
||||||
|
IssuerNameHash []byte
|
||||||
|
IssuerKeyHash []byte
|
||||||
|
SerialNumber *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals the OCSP request to ASN.1 DER encoded form.
|
||||||
|
func (req *Request) Marshal() ([]byte, error) {
|
||||||
|
hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm)
|
||||||
|
if hashAlg == nil {
|
||||||
|
return nil, errors.New("Unknown hash algorithm")
|
||||||
|
}
|
||||||
|
return asn1.Marshal(ocspRequest{
|
||||||
|
tbsRequest{
|
||||||
|
Version: 0,
|
||||||
|
RequestList: []request{
|
||||||
|
{
|
||||||
|
Cert: certID{
|
||||||
|
pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: hashAlg,
|
||||||
|
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
||||||
|
},
|
||||||
|
req.IssuerNameHash,
|
||||||
|
req.IssuerKeyHash,
|
||||||
|
req.SerialNumber,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response represents an OCSP response containing a single SingleResponse. See
|
||||||
|
// RFC 6960.
|
||||||
type Response struct {
|
type Response struct {
|
||||||
// Status is one of {Good, Revoked, Unknown, ServerFailed}
|
// Status is one of {Good, Revoked, Unknown}
|
||||||
Status int
|
Status int
|
||||||
SerialNumber *big.Int
|
SerialNumber *big.Int
|
||||||
ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
|
ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
|
||||||
|
@ -151,8 +356,48 @@ type Response struct {
|
||||||
TBSResponseData []byte
|
TBSResponseData []byte
|
||||||
Signature []byte
|
Signature []byte
|
||||||
SignatureAlgorithm x509.SignatureAlgorithm
|
SignatureAlgorithm x509.SignatureAlgorithm
|
||||||
|
|
||||||
|
// IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash.
|
||||||
|
// Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512.
|
||||||
|
// If zero, the default is crypto.SHA1.
|
||||||
|
IssuerHash crypto.Hash
|
||||||
|
|
||||||
|
// RawResponderName optionally contains the DER-encoded subject of the
|
||||||
|
// responder certificate. Exactly one of RawResponderName and
|
||||||
|
// ResponderKeyHash is set.
|
||||||
|
RawResponderName []byte
|
||||||
|
// ResponderKeyHash optionally contains the SHA-1 hash of the
|
||||||
|
// responder's public key. Exactly one of RawResponderName and
|
||||||
|
// ResponderKeyHash is set.
|
||||||
|
ResponderKeyHash []byte
|
||||||
|
|
||||||
|
// Extensions contains raw X.509 extensions from the singleExtensions field
|
||||||
|
// of the OCSP response. When parsing certificates, this can be used to
|
||||||
|
// extract non-critical extensions that are not parsed by this package. When
|
||||||
|
// marshaling OCSP responses, the Extensions field is ignored, see
|
||||||
|
// ExtraExtensions.
|
||||||
|
Extensions []pkix.Extension
|
||||||
|
|
||||||
|
// ExtraExtensions contains extensions to be copied, raw, into any marshaled
|
||||||
|
// OCSP response (in the singleExtensions field). Values override any
|
||||||
|
// extensions that would otherwise be produced based on the other fields. The
|
||||||
|
// ExtraExtensions field is not populated when parsing certificates, see
|
||||||
|
// Extensions.
|
||||||
|
ExtraExtensions []pkix.Extension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are pre-serialized error responses for the various non-success codes
|
||||||
|
// defined by OCSP. The Unauthorized code in particular can be used by an OCSP
|
||||||
|
// responder that supports only pre-signed responses as a response to requests
|
||||||
|
// for certificates with unknown status. See RFC 5019.
|
||||||
|
var (
|
||||||
|
MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
|
||||||
|
InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
|
||||||
|
TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
|
||||||
|
SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
|
||||||
|
UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
|
||||||
|
)
|
||||||
|
|
||||||
// CheckSignatureFrom checks that the signature in resp is a valid signature
|
// CheckSignatureFrom checks that the signature in resp is a valid signature
|
||||||
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
|
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
|
||||||
// the OCSP response contained an intermediate certificate that created the
|
// the OCSP response contained an intermediate certificate that created the
|
||||||
|
@ -169,12 +414,57 @@ func (p ParseError) Error() string {
|
||||||
return string(p)
|
return string(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseRequest parses an OCSP request in DER form. It only supports
|
||||||
|
// requests for a single certificate. Signed requests are not supported.
|
||||||
|
// If a request includes a signature, it will result in a ParseError.
|
||||||
|
func ParseRequest(bytes []byte) (*Request, error) {
|
||||||
|
var req ocspRequest
|
||||||
|
rest, err := asn1.Unmarshal(bytes, &req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rest) > 0 {
|
||||||
|
return nil, ParseError("trailing data in OCSP request")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.TBSRequest.RequestList) == 0 {
|
||||||
|
return nil, ParseError("OCSP request contains no request body")
|
||||||
|
}
|
||||||
|
innerRequest := req.TBSRequest.RequestList[0]
|
||||||
|
|
||||||
|
hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm)
|
||||||
|
if hashFunc == crypto.Hash(0) {
|
||||||
|
return nil, ParseError("OCSP request uses unknown hash function")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Request{
|
||||||
|
HashAlgorithm: hashFunc,
|
||||||
|
IssuerNameHash: innerRequest.Cert.NameHash,
|
||||||
|
IssuerKeyHash: innerRequest.Cert.IssuerKeyHash,
|
||||||
|
SerialNumber: innerRequest.Cert.SerialNumber,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseResponse parses an OCSP response in DER form. It only supports
|
// ParseResponse parses an OCSP response in DER form. It only supports
|
||||||
// responses for a single certificate. If the response contains a certificate
|
// responses for a single certificate. If the response contains a certificate
|
||||||
// then the signature over the response is checked. If issuer is not nil then
|
// then the signature over the response is checked. If issuer is not nil then
|
||||||
// it will be used to validate the signature or embedded certificate. Invalid
|
// it will be used to validate the signature or embedded certificate.
|
||||||
// signatures or parse failures will result in a ParseError.
|
//
|
||||||
|
// Invalid responses and parse failures will result in a ParseError.
|
||||||
|
// Error responses will result in a ResponseError.
|
||||||
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
||||||
|
return ParseResponseForCert(bytes, nil, issuer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResponseForCert parses an OCSP response in DER form and searches for a
|
||||||
|
// Response relating to cert. If such a Response is found and the OCSP response
|
||||||
|
// contains a certificate then the signature over the response is checked. If
|
||||||
|
// issuer is not nil then it will be used to validate the signature or embedded
|
||||||
|
// certificate.
|
||||||
|
//
|
||||||
|
// Invalid responses and parse failures will result in a ParseError.
|
||||||
|
// Error responses will result in a ResponseError.
|
||||||
|
func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
|
||||||
var resp responseASN1
|
var resp responseASN1
|
||||||
rest, err := asn1.Unmarshal(bytes, &resp)
|
rest, err := asn1.Unmarshal(bytes, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,10 +474,8 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
||||||
return nil, ParseError("trailing data in OCSP response")
|
return nil, ParseError("trailing data in OCSP response")
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := new(Response)
|
if status := ResponseStatus(resp.Status); status != Success {
|
||||||
if resp.Status != ocspSuccess {
|
return nil, ResponseError{status}
|
||||||
ret.Status = ServerFailed
|
|
||||||
return ret, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
|
if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
|
||||||
|
@ -204,13 +492,56 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
||||||
return nil, ParseError("OCSP response contains bad number of certificates")
|
return nil, ParseError("OCSP response contains bad number of certificates")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(basicResp.TBSResponseData.Responses) != 1 {
|
if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 {
|
||||||
return nil, ParseError("OCSP response contains bad number of responses")
|
return nil, ParseError("OCSP response contains bad number of responses")
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.TBSResponseData = basicResp.TBSResponseData.Raw
|
var singleResp singleResponse
|
||||||
ret.Signature = basicResp.Signature.RightAlign()
|
if cert == nil {
|
||||||
ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)
|
singleResp = basicResp.TBSResponseData.Responses[0]
|
||||||
|
} else {
|
||||||
|
match := false
|
||||||
|
for _, resp := range basicResp.TBSResponseData.Responses {
|
||||||
|
if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
|
||||||
|
singleResp = resp
|
||||||
|
match = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !match {
|
||||||
|
return nil, ParseError("no response matching the supplied certificate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &Response{
|
||||||
|
TBSResponseData: basicResp.TBSResponseData.Raw,
|
||||||
|
Signature: basicResp.Signature.RightAlign(),
|
||||||
|
SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm),
|
||||||
|
Extensions: singleResp.SingleExtensions,
|
||||||
|
SerialNumber: singleResp.CertID.SerialNumber,
|
||||||
|
ProducedAt: basicResp.TBSResponseData.ProducedAt,
|
||||||
|
ThisUpdate: singleResp.ThisUpdate,
|
||||||
|
NextUpdate: singleResp.NextUpdate,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the ResponderID CHOICE tag. ResponderID can be flattened into
|
||||||
|
// TBSResponseData once https://go-review.googlesource.com/34503 has been
|
||||||
|
// released.
|
||||||
|
rawResponderID := basicResp.TBSResponseData.RawResponderID
|
||||||
|
switch rawResponderID.Tag {
|
||||||
|
case 1: // Name
|
||||||
|
var rdn pkix.RDNSequence
|
||||||
|
if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 {
|
||||||
|
return nil, ParseError("invalid responder name")
|
||||||
|
}
|
||||||
|
ret.RawResponderName = rawResponderID.Bytes
|
||||||
|
case 2: // KeyHash
|
||||||
|
if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 {
|
||||||
|
return nil, ParseError("invalid responder key hash")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, ParseError("invalid responder id tag")
|
||||||
|
}
|
||||||
|
|
||||||
if len(basicResp.Certificates) > 0 {
|
if len(basicResp.Certificates) > 0 {
|
||||||
ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
|
ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
|
||||||
|
@ -219,56 +550,50 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
|
if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
|
||||||
return nil, ParseError("bad OCSP signature")
|
return nil, ParseError("bad signature on embedded certificate: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if issuer != nil {
|
if issuer != nil {
|
||||||
if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
|
if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
|
||||||
return nil, ParseError("bad signature on embedded certificate")
|
return nil, ParseError("bad OCSP signature: " + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if issuer != nil {
|
} else if issuer != nil {
|
||||||
if err := ret.CheckSignatureFrom(issuer); err != nil {
|
if err := ret.CheckSignatureFrom(issuer); err != nil {
|
||||||
return nil, ParseError("bad OCSP signature")
|
return nil, ParseError("bad OCSP signature: " + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r := basicResp.TBSResponseData.Responses[0]
|
for _, ext := range singleResp.SingleExtensions {
|
||||||
|
if ext.Critical {
|
||||||
|
return nil, ParseError("unsupported critical extension")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret.SerialNumber = r.CertID.SerialNumber
|
for h, oid := range hashOIDs {
|
||||||
|
if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) {
|
||||||
|
ret.IssuerHash = h
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ret.IssuerHash == 0 {
|
||||||
|
return nil, ParseError("unsupported issuer hash algorithm")
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case bool(r.Good):
|
case bool(singleResp.Good):
|
||||||
ret.Status = Good
|
ret.Status = Good
|
||||||
case bool(r.Unknown):
|
case bool(singleResp.Unknown):
|
||||||
ret.Status = Unknown
|
ret.Status = Unknown
|
||||||
default:
|
default:
|
||||||
ret.Status = Revoked
|
ret.Status = Revoked
|
||||||
ret.RevokedAt = r.Revoked.RevocationTime
|
ret.RevokedAt = singleResp.Revoked.RevocationTime
|
||||||
ret.RevocationReason = r.Revoked.Reason
|
ret.RevocationReason = int(singleResp.Revoked.Reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
|
|
||||||
ret.ThisUpdate = r.ThisUpdate
|
|
||||||
ret.NextUpdate = r.NextUpdate
|
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc2560#section-4.1.1
|
|
||||||
type ocspRequest struct {
|
|
||||||
TBSRequest tbsRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
type tbsRequest struct {
|
|
||||||
Version int `asn1:"explicit,tag:0,default:0"`
|
|
||||||
RequestList []request
|
|
||||||
}
|
|
||||||
|
|
||||||
type request struct {
|
|
||||||
Cert certID
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestOptions contains options for constructing OCSP requests.
|
// RequestOptions contains options for constructing OCSP requests.
|
||||||
type RequestOptions struct {
|
type RequestOptions struct {
|
||||||
// Hash contains the hash function that should be used when
|
// Hash contains the hash function that should be used when
|
||||||
|
@ -292,17 +617,8 @@ func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte
|
||||||
// OCSP seems to be the only place where these raw hash identifiers are
|
// OCSP seems to be the only place where these raw hash identifiers are
|
||||||
// used. I took the following from
|
// used. I took the following from
|
||||||
// http://msdn.microsoft.com/en-us/library/ff635603.aspx
|
// http://msdn.microsoft.com/en-us/library/ff635603.aspx
|
||||||
var hashOID asn1.ObjectIdentifier
|
_, ok := hashOIDs[hashFunc]
|
||||||
switch hashFunc {
|
if !ok {
|
||||||
case crypto.SHA1:
|
|
||||||
hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
|
|
||||||
case crypto.SHA256:
|
|
||||||
hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
|
|
||||||
case crypto.SHA384:
|
|
||||||
hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
|
|
||||||
case crypto.SHA512:
|
|
||||||
hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
|
|
||||||
default:
|
|
||||||
return nil, x509.ErrUnsupportedAlgorithm
|
return nil, x509.ErrUnsupportedAlgorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,22 +642,137 @@ func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte
|
||||||
h.Write(issuer.RawSubject)
|
h.Write(issuer.RawSubject)
|
||||||
issuerNameHash := h.Sum(nil)
|
issuerNameHash := h.Sum(nil)
|
||||||
|
|
||||||
return asn1.Marshal(ocspRequest{
|
req := &Request{
|
||||||
tbsRequest{
|
HashAlgorithm: hashFunc,
|
||||||
Version: 0,
|
IssuerNameHash: issuerNameHash,
|
||||||
RequestList: []request{
|
IssuerKeyHash: issuerKeyHash,
|
||||||
{
|
SerialNumber: cert.SerialNumber,
|
||||||
Cert: certID{
|
}
|
||||||
pkix.AlgorithmIdentifier{
|
return req.Marshal()
|
||||||
Algorithm: hashOID,
|
}
|
||||||
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
|
||||||
},
|
// CreateResponse returns a DER-encoded OCSP response with the specified contents.
|
||||||
issuerNameHash,
|
// The fields in the response are populated as follows:
|
||||||
issuerKeyHash,
|
//
|
||||||
cert.SerialNumber,
|
// The responder cert is used to populate the responder's name field, and the
|
||||||
},
|
// certificate itself is provided alongside the OCSP response signature.
|
||||||
},
|
//
|
||||||
|
// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields.
|
||||||
|
//
|
||||||
|
// The template is used to populate the SerialNumber, Status, RevokedAt,
|
||||||
|
// RevocationReason, ThisUpdate, and NextUpdate fields.
|
||||||
|
//
|
||||||
|
// If template.IssuerHash is not set, SHA1 will be used.
|
||||||
|
//
|
||||||
|
// The ProducedAt date is automatically set to the current date, to the nearest minute.
|
||||||
|
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
|
||||||
|
var publicKeyInfo struct {
|
||||||
|
Algorithm pkix.AlgorithmIdentifier
|
||||||
|
PublicKey asn1.BitString
|
||||||
|
}
|
||||||
|
if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if template.IssuerHash == 0 {
|
||||||
|
template.IssuerHash = crypto.SHA1
|
||||||
|
}
|
||||||
|
hashOID := getOIDFromHashAlgorithm(template.IssuerHash)
|
||||||
|
if hashOID == nil {
|
||||||
|
return nil, errors.New("unsupported issuer hash algorithm")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !template.IssuerHash.Available() {
|
||||||
|
return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash)
|
||||||
|
}
|
||||||
|
h := template.IssuerHash.New()
|
||||||
|
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
||||||
|
issuerKeyHash := h.Sum(nil)
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write(issuer.RawSubject)
|
||||||
|
issuerNameHash := h.Sum(nil)
|
||||||
|
|
||||||
|
innerResponse := singleResponse{
|
||||||
|
CertID: certID{
|
||||||
|
HashAlgorithm: pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: hashOID,
|
||||||
|
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
||||||
},
|
},
|
||||||
|
NameHash: issuerNameHash,
|
||||||
|
IssuerKeyHash: issuerKeyHash,
|
||||||
|
SerialNumber: template.SerialNumber,
|
||||||
|
},
|
||||||
|
ThisUpdate: template.ThisUpdate.UTC(),
|
||||||
|
NextUpdate: template.NextUpdate.UTC(),
|
||||||
|
SingleExtensions: template.ExtraExtensions,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch template.Status {
|
||||||
|
case Good:
|
||||||
|
innerResponse.Good = true
|
||||||
|
case Unknown:
|
||||||
|
innerResponse.Unknown = true
|
||||||
|
case Revoked:
|
||||||
|
innerResponse.Revoked = revokedInfo{
|
||||||
|
RevocationTime: template.RevokedAt.UTC(),
|
||||||
|
Reason: asn1.Enumerated(template.RevocationReason),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rawResponderID := asn1.RawValue{
|
||||||
|
Class: 2, // context-specific
|
||||||
|
Tag: 1, // Name (explicit tag)
|
||||||
|
IsCompound: true,
|
||||||
|
Bytes: responderCert.RawSubject,
|
||||||
|
}
|
||||||
|
tbsResponseData := responseData{
|
||||||
|
Version: 0,
|
||||||
|
RawResponderID: rawResponderID,
|
||||||
|
ProducedAt: time.Now().Truncate(time.Minute).UTC(),
|
||||||
|
Responses: []singleResponse{innerResponse},
|
||||||
|
}
|
||||||
|
|
||||||
|
tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responseHash := hashFunc.New()
|
||||||
|
responseHash.Write(tbsResponseDataDER)
|
||||||
|
signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := basicResponse{
|
||||||
|
TBSResponseData: tbsResponseData,
|
||||||
|
SignatureAlgorithm: signatureAlgorithm,
|
||||||
|
Signature: asn1.BitString{
|
||||||
|
Bytes: signature,
|
||||||
|
BitLength: 8 * len(signature),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if template.Certificate != nil {
|
||||||
|
response.Certificates = []asn1.RawValue{
|
||||||
|
asn1.RawValue{FullBytes: template.Certificate.Raw},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
responseDER, err := asn1.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return asn1.Marshal(responseASN1{
|
||||||
|
Status: asn1.Enumerated(Success),
|
||||||
|
Response: responseBytes{
|
||||||
|
ResponseType: idPKIXOCSPBasic,
|
||||||
|
Response: responseDER,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
11
vendor/golang.org/x/crypto/scrypt/scrypt.go
generated
vendored
11
vendor/golang.org/x/crypto/scrypt/scrypt.go
generated
vendored
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// Package scrypt implements the scrypt key derivation function as defined in
|
// Package scrypt implements the scrypt key derivation function as defined in
|
||||||
// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
|
// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
|
||||||
// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
|
// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf).
|
||||||
package scrypt // import "golang.org/x/crypto/scrypt"
|
package scrypt // import "golang.org/x/crypto/scrypt"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -218,11 +218,12 @@ func smix(b []byte, r, N int, v, xy []uint32) {
|
||||||
// For example, you can get a derived key for e.g. AES-256 (which needs a
|
// For example, you can get a derived key for e.g. AES-256 (which needs a
|
||||||
// 32-byte key) by doing:
|
// 32-byte key) by doing:
|
||||||
//
|
//
|
||||||
// dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
||||||
//
|
//
|
||||||
// The recommended parameters for interactive logins as of 2009 are N=16384,
|
// The recommended parameters for interactive logins as of 2017 are N=32768, r=8
|
||||||
// r=8, p=1. They should be increased as memory latency and CPU parallelism
|
// and p=1. The parameters N, r, and p should be increased as memory latency and
|
||||||
// increases. Remember to get a good random salt.
|
// CPU parallelism increases; consider setting N to the highest power of 2 you
|
||||||
|
// can derive within 100 milliseconds. Remember to get a good random salt.
|
||||||
func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
|
func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
|
||||||
if N <= 1 || N&(N-1) != 0 {
|
if N <= 1 || N&(N-1) != 0 {
|
||||||
return nil, errors.New("scrypt: N must be > 1 and a power of 2")
|
return nil, errors.New("scrypt: N must be > 1 and a power of 2")
|
||||||
|
|
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Assemble converts insts into raw instructions suitable for loading
|
||||||
|
// into a BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Currently, no optimization is attempted, the assembled program flow
|
||||||
|
// is exactly as provided.
|
||||||
|
func Assemble(insts []Instruction) ([]RawInstruction, error) {
|
||||||
|
ret := make([]RawInstruction, len(insts))
|
||||||
|
var err error
|
||||||
|
for i, inst := range insts {
|
||||||
|
ret[i], err = inst.Assemble()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassemble attempts to parse raw back into
|
||||||
|
// Instructions. Unrecognized RawInstructions are assumed to be an
|
||||||
|
// extension not implemented by this package, and are passed through
|
||||||
|
// unchanged to the output. The allDecoded value reports whether insts
|
||||||
|
// contains no RawInstructions.
|
||||||
|
func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
|
||||||
|
insts = make([]Instruction, len(raw))
|
||||||
|
allDecoded = true
|
||||||
|
for i, r := range raw {
|
||||||
|
insts[i] = r.Disassemble()
|
||||||
|
if _, ok := insts[i].(RawInstruction); ok {
|
||||||
|
allDecoded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insts, allDecoded
|
||||||
|
}
|
218
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
218
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
// A Register is a register of the BPF virtual machine.
|
||||||
|
type Register uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RegA is the accumulator register. RegA is always the
|
||||||
|
// destination register of ALU operations.
|
||||||
|
RegA Register = iota
|
||||||
|
// RegX is the indirection register, used by LoadIndirect
|
||||||
|
// operations.
|
||||||
|
RegX
|
||||||
|
)
|
||||||
|
|
||||||
|
// An ALUOp is an arithmetic or logic operation.
|
||||||
|
type ALUOp uint16
|
||||||
|
|
||||||
|
// ALU binary operation types.
|
||||||
|
const (
|
||||||
|
ALUOpAdd ALUOp = iota << 4
|
||||||
|
ALUOpSub
|
||||||
|
ALUOpMul
|
||||||
|
ALUOpDiv
|
||||||
|
ALUOpOr
|
||||||
|
ALUOpAnd
|
||||||
|
ALUOpShiftLeft
|
||||||
|
ALUOpShiftRight
|
||||||
|
aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
|
||||||
|
ALUOpMod
|
||||||
|
ALUOpXor
|
||||||
|
)
|
||||||
|
|
||||||
|
// A JumpTest is a comparison operator used in conditional jumps.
|
||||||
|
type JumpTest uint16
|
||||||
|
|
||||||
|
// Supported operators for conditional jumps.
|
||||||
|
const (
|
||||||
|
// K == A
|
||||||
|
JumpEqual JumpTest = iota
|
||||||
|
// K != A
|
||||||
|
JumpNotEqual
|
||||||
|
// K > A
|
||||||
|
JumpGreaterThan
|
||||||
|
// K < A
|
||||||
|
JumpLessThan
|
||||||
|
// K >= A
|
||||||
|
JumpGreaterOrEqual
|
||||||
|
// K <= A
|
||||||
|
JumpLessOrEqual
|
||||||
|
// K & A != 0
|
||||||
|
JumpBitsSet
|
||||||
|
// K & A == 0
|
||||||
|
JumpBitsNotSet
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Extension is a function call provided by the kernel that
|
||||||
|
// performs advanced operations that are expensive or impossible
|
||||||
|
// within the BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Extensions are only implemented by the Linux kernel.
|
||||||
|
//
|
||||||
|
// TODO: should we prune this list? Some of these extensions seem
|
||||||
|
// either broken or near-impossible to use correctly, whereas other
|
||||||
|
// (len, random, ifindex) are quite useful.
|
||||||
|
type Extension int
|
||||||
|
|
||||||
|
// Extension functions available in the Linux kernel.
|
||||||
|
const (
|
||||||
|
// extOffset is the negative maximum number of instructions used
|
||||||
|
// to load instructions by overloading the K argument.
|
||||||
|
extOffset = -0x1000
|
||||||
|
// ExtLen returns the length of the packet.
|
||||||
|
ExtLen Extension = 1
|
||||||
|
// ExtProto returns the packet's L3 protocol type.
|
||||||
|
ExtProto Extension = 0
|
||||||
|
// ExtType returns the packet's type (skb->pkt_type in the kernel)
|
||||||
|
//
|
||||||
|
// TODO: better documentation. How nice an API do we want to
|
||||||
|
// provide for these esoteric extensions?
|
||||||
|
ExtType Extension = 4
|
||||||
|
// ExtPayloadOffset returns the offset of the packet payload, or
|
||||||
|
// the first protocol header that the kernel does not know how to
|
||||||
|
// parse.
|
||||||
|
ExtPayloadOffset Extension = 52
|
||||||
|
// ExtInterfaceIndex returns the index of the interface on which
|
||||||
|
// the packet was received.
|
||||||
|
ExtInterfaceIndex Extension = 8
|
||||||
|
// ExtNetlinkAttr returns the netlink attribute of type X at
|
||||||
|
// offset A.
|
||||||
|
ExtNetlinkAttr Extension = 12
|
||||||
|
// ExtNetlinkAttrNested returns the nested netlink attribute of
|
||||||
|
// type X at offset A.
|
||||||
|
ExtNetlinkAttrNested Extension = 16
|
||||||
|
// ExtMark returns the packet's mark value.
|
||||||
|
ExtMark Extension = 20
|
||||||
|
// ExtQueue returns the packet's assigned hardware queue.
|
||||||
|
ExtQueue Extension = 24
|
||||||
|
// ExtLinkLayerType returns the packet's hardware address type
|
||||||
|
// (e.g. Ethernet, Infiniband).
|
||||||
|
ExtLinkLayerType Extension = 28
|
||||||
|
// ExtRXHash returns the packets receive hash.
|
||||||
|
//
|
||||||
|
// TODO: figure out what this rxhash actually is.
|
||||||
|
ExtRXHash Extension = 32
|
||||||
|
// ExtCPUID returns the ID of the CPU processing the current
|
||||||
|
// packet.
|
||||||
|
ExtCPUID Extension = 36
|
||||||
|
// ExtVLANTag returns the packet's VLAN tag.
|
||||||
|
ExtVLANTag Extension = 44
|
||||||
|
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
|
||||||
|
// tag.
|
||||||
|
//
|
||||||
|
// TODO: I think this might be a lie: it reads bit 0x1000 of the
|
||||||
|
// VLAN header, which changed meaning in recent revisions of the
|
||||||
|
// spec - this extension may now return meaningless information.
|
||||||
|
ExtVLANTagPresent Extension = 48
|
||||||
|
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
|
||||||
|
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
|
||||||
|
// other value if no VLAN information is present.
|
||||||
|
ExtVLANProto Extension = 60
|
||||||
|
// ExtRand returns a uniformly random uint32.
|
||||||
|
ExtRand Extension = 56
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following gives names to various bit patterns used in opcode construction.
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMaskCls uint16 = 0x7
|
||||||
|
// opClsLoad masks
|
||||||
|
opMaskLoadDest = 0x01
|
||||||
|
opMaskLoadWidth = 0x18
|
||||||
|
opMaskLoadMode = 0xe0
|
||||||
|
// opClsALU
|
||||||
|
opMaskOperandSrc = 0x08
|
||||||
|
opMaskOperator = 0xf0
|
||||||
|
// opClsJump
|
||||||
|
opMaskJumpConst = 0x0f
|
||||||
|
opMaskJumpCond = 0xf0
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadA uint16 = iota
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadX
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreA
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreX
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsALU
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
// | TestOperator (4b) | 0 | 1 | 0 | 1 |
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
opClsJump
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsReturn
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsMisc
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opAddrModeImmediate uint16 = iota << 5
|
||||||
|
opAddrModeAbsolute
|
||||||
|
opAddrModeIndirect
|
||||||
|
opAddrModeScratch
|
||||||
|
opAddrModePacketLen // actually an extension, not an addressing mode.
|
||||||
|
opAddrModeMemShift
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opLoadWidth4 uint16 = iota << 3
|
||||||
|
opLoadWidth2
|
||||||
|
opLoadWidth1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operator defined by ALUOp*
|
||||||
|
|
||||||
|
const (
|
||||||
|
opALUSrcConstant uint16 = iota << 3
|
||||||
|
opALUSrcX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opJumpAlways = iota << 4
|
||||||
|
opJumpEqual
|
||||||
|
opJumpGT
|
||||||
|
opJumpGE
|
||||||
|
opJumpSet
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opRetSrcConstant uint16 = iota << 4
|
||||||
|
opRetSrcA
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMiscTAX = 0x00
|
||||||
|
opMiscTXA = 0x80
|
||||||
|
)
|
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Package bpf implements marshaling and unmarshaling of programs for the
|
||||||
|
Berkeley Packet Filter virtual machine, and provides a Go implementation
|
||||||
|
of the virtual machine.
|
||||||
|
|
||||||
|
BPF's main use is to specify a packet filter for network taps, so that
|
||||||
|
the kernel doesn't have to expensively copy every packet it sees to
|
||||||
|
userspace. However, it's been repurposed to other areas where running
|
||||||
|
user code in-kernel is needed. For example, Linux's seccomp uses BPF
|
||||||
|
to apply security policies to system calls. For simplicity, this
|
||||||
|
documentation refers only to packets, but other uses of BPF have their
|
||||||
|
own data payloads.
|
||||||
|
|
||||||
|
BPF programs run in a restricted virtual machine. It has almost no
|
||||||
|
access to kernel functions, and while conditional branches are
|
||||||
|
allowed, they can only jump forwards, to guarantee that there are no
|
||||||
|
infinite loops.
|
||||||
|
|
||||||
|
The virtual machine
|
||||||
|
|
||||||
|
The BPF VM is an accumulator machine. Its main register, called
|
||||||
|
register A, is an implicit source and destination in all arithmetic
|
||||||
|
and logic operations. The machine also has 16 scratch registers for
|
||||||
|
temporary storage, and an indirection register (register X) for
|
||||||
|
indirect memory access. All registers are 32 bits wide.
|
||||||
|
|
||||||
|
Each run of a BPF program is given one packet, which is placed in the
|
||||||
|
VM's read-only "main memory". LoadAbsolute and LoadIndirect
|
||||||
|
instructions can fetch up to 32 bits at a time into register A for
|
||||||
|
examination.
|
||||||
|
|
||||||
|
The goal of a BPF program is to produce and return a verdict (uint32),
|
||||||
|
which tells the kernel what to do with the packet. In the context of
|
||||||
|
packet filtering, the returned value is the number of bytes of the
|
||||||
|
packet to forward to userspace, or 0 to ignore the packet. Other
|
||||||
|
contexts like seccomp define their own return values.
|
||||||
|
|
||||||
|
In order to simplify programs, attempts to read past the end of the
|
||||||
|
packet terminate the program execution with a verdict of 0 (ignore
|
||||||
|
packet). This means that the vast majority of BPF programs don't need
|
||||||
|
to do any explicit bounds checking.
|
||||||
|
|
||||||
|
In addition to the bytes of the packet, some BPF programs have access
|
||||||
|
to extensions, which are essentially calls to kernel utility
|
||||||
|
functions. Currently, the only extensions supported by this package
|
||||||
|
are the Linux packet filter extensions.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
|
||||||
|
This packet filter selects all ARP packets.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Load "EtherType" field from the ethernet header.
|
||||||
|
bpf.LoadAbsolute{Off: 12, Size: 2},
|
||||||
|
// Skip over the next instruction if EtherType is not ARP.
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
|
||||||
|
// Verdict is "send up to 4k of the packet to userspace."
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Verdict is "ignore packet."
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
This packet filter captures a random 1% sample of traffic.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Get a 32-bit random number from the Linux kernel.
|
||||||
|
bpf.LoadExtension{Num: bpf.ExtRand},
|
||||||
|
// 1% dice roll?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
|
||||||
|
// Capture.
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Ignore.
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
*/
|
||||||
|
package bpf // import "golang.org/x/net/bpf"
|
704
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
704
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
|
@ -0,0 +1,704 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// An Instruction is one instruction executed by the BPF virtual
|
||||||
|
// machine.
|
||||||
|
type Instruction interface {
|
||||||
|
// Assemble assembles the Instruction into a RawInstruction.
|
||||||
|
Assemble() (RawInstruction, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RawInstruction is a raw BPF virtual machine instruction.
|
||||||
|
type RawInstruction struct {
|
||||||
|
// Operation to execute.
|
||||||
|
Op uint16
|
||||||
|
// For conditional jump instructions, the number of instructions
|
||||||
|
// to skip if the condition is true/false.
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
// Constant parameter. The meaning depends on the Op.
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
|
||||||
|
|
||||||
|
// Disassemble parses ri into an Instruction and returns it. If ri is
|
||||||
|
// not recognized by this package, ri itself is returned.
|
||||||
|
func (ri RawInstruction) Disassemble() Instruction {
|
||||||
|
switch ri.Op & opMaskCls {
|
||||||
|
case opClsLoadA, opClsLoadX:
|
||||||
|
reg := Register(ri.Op & opMaskLoadDest)
|
||||||
|
sz := 0
|
||||||
|
switch ri.Op & opMaskLoadWidth {
|
||||||
|
case opLoadWidth4:
|
||||||
|
sz = 4
|
||||||
|
case opLoadWidth2:
|
||||||
|
sz = 2
|
||||||
|
case opLoadWidth1:
|
||||||
|
sz = 1
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskLoadMode {
|
||||||
|
case opAddrModeImmediate:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadConstant{Dst: reg, Val: ri.K}
|
||||||
|
case opAddrModeScratch:
|
||||||
|
if sz != 4 || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadScratch{Dst: reg, N: int(ri.K)}
|
||||||
|
case opAddrModeAbsolute:
|
||||||
|
if ri.K > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(-extOffset + ri.K)}
|
||||||
|
}
|
||||||
|
return LoadAbsolute{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModeIndirect:
|
||||||
|
return LoadIndirect{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModePacketLen:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadExtension{Num: ExtLen}
|
||||||
|
case opAddrModeMemShift:
|
||||||
|
return LoadMemShift{Off: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsStoreA:
|
||||||
|
if ri.Op != opClsStoreA || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegA, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsStoreX:
|
||||||
|
if ri.Op != opClsStoreX || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegX, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsALU:
|
||||||
|
switch op := ALUOp(ri.Op & opMaskOperator); op {
|
||||||
|
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
|
||||||
|
if ri.Op&opMaskOperandSrc != 0 {
|
||||||
|
return ALUOpX{Op: op}
|
||||||
|
}
|
||||||
|
return ALUOpConstant{Op: op, Val: ri.K}
|
||||||
|
case aluOpNeg:
|
||||||
|
return NegateA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsJump:
|
||||||
|
if ri.Op&opMaskJumpConst != opClsJump {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskJumpCond {
|
||||||
|
case opJumpAlways:
|
||||||
|
return Jump{Skip: ri.K}
|
||||||
|
case opJumpEqual:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpNotEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGT:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpLessOrEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterThan,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGE:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpLessThan,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterOrEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpSet:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpBitsSet,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsReturn:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsReturn | opRetSrcA:
|
||||||
|
return RetA{}
|
||||||
|
case opClsReturn | opRetSrcConstant:
|
||||||
|
return RetConstant{Val: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsMisc:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsMisc | opMiscTAX:
|
||||||
|
return TAX{}
|
||||||
|
case opClsMisc | opMiscTXA:
|
||||||
|
return TXA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("unreachable") // switch is exhaustive on the bit pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConstant loads Val into register Dst.
|
||||||
|
type LoadConstant struct {
|
||||||
|
Dst Register
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadConstant) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld #%d", a.Val)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadScratch loads scratch[N] into register Dst.
|
||||||
|
type LoadScratch struct {
|
||||||
|
Dst Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadScratch) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
||||||
|
// register A.
|
||||||
|
type LoadAbsolute struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadAbsolute) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [%d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [%d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
if a.Off > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ld [%d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
||||||
|
// into register A.
|
||||||
|
type LoadIndirect struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadIndirect) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadIndirect) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [x + %d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [x + %d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
return fmt.Sprintf("ld [x + %d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
||||||
|
// by 4 and stores the result in register X.
|
||||||
|
//
|
||||||
|
// This instruction is mainly useful to load into X the length of an
|
||||||
|
// IPv4 packet header in a single instruction, rather than have to do
|
||||||
|
// the arithmetic on the header's first byte by hand.
|
||||||
|
type LoadMemShift struct {
|
||||||
|
Off uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadMemShift) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadMemShift) String() string {
|
||||||
|
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadExtension invokes a linux-specific extension and stores the
|
||||||
|
// result in register A.
|
||||||
|
type LoadExtension struct {
|
||||||
|
Num Extension
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadExtension) Assemble() (RawInstruction, error) {
|
||||||
|
if a.Num == ExtLen {
|
||||||
|
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
||||||
|
}
|
||||||
|
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadExtension) String() string {
|
||||||
|
switch a.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return "ld #len"
|
||||||
|
case ExtProto:
|
||||||
|
return "ld #proto"
|
||||||
|
case ExtType:
|
||||||
|
return "ld #type"
|
||||||
|
case ExtPayloadOffset:
|
||||||
|
return "ld #poff"
|
||||||
|
case ExtInterfaceIndex:
|
||||||
|
return "ld #ifidx"
|
||||||
|
case ExtNetlinkAttr:
|
||||||
|
return "ld #nla"
|
||||||
|
case ExtNetlinkAttrNested:
|
||||||
|
return "ld #nlan"
|
||||||
|
case ExtMark:
|
||||||
|
return "ld #mark"
|
||||||
|
case ExtQueue:
|
||||||
|
return "ld #queue"
|
||||||
|
case ExtLinkLayerType:
|
||||||
|
return "ld #hatype"
|
||||||
|
case ExtRXHash:
|
||||||
|
return "ld #rxhash"
|
||||||
|
case ExtCPUID:
|
||||||
|
return "ld #cpu"
|
||||||
|
case ExtVLANTag:
|
||||||
|
return "ld #vlan_tci"
|
||||||
|
case ExtVLANTagPresent:
|
||||||
|
return "ld #vlan_avail"
|
||||||
|
case ExtVLANProto:
|
||||||
|
return "ld #vlan_tpid"
|
||||||
|
case ExtRand:
|
||||||
|
return "ld #rand"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoreScratch stores register Src into scratch[N].
|
||||||
|
type StoreScratch struct {
|
||||||
|
Src Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a StoreScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
var op uint16
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
op = opClsStoreA
|
||||||
|
case RegX:
|
||||||
|
op = opClsStoreX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawInstruction{
|
||||||
|
Op: op,
|
||||||
|
K: uint32(a.N),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a StoreScratch) String() string {
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("st M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("stx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpConstant executes A = A <Op> Val.
|
||||||
|
type ALUOpConstant struct {
|
||||||
|
Op ALUOp
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcConstant | uint16(a.Op),
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a ALUOpConstant) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return fmt.Sprintf("add #%d", a.Val)
|
||||||
|
case ALUOpSub:
|
||||||
|
return fmt.Sprintf("sub #%d", a.Val)
|
||||||
|
case ALUOpMul:
|
||||||
|
return fmt.Sprintf("mul #%d", a.Val)
|
||||||
|
case ALUOpDiv:
|
||||||
|
return fmt.Sprintf("div #%d", a.Val)
|
||||||
|
case ALUOpMod:
|
||||||
|
return fmt.Sprintf("mod #%d", a.Val)
|
||||||
|
case ALUOpAnd:
|
||||||
|
return fmt.Sprintf("and #%d", a.Val)
|
||||||
|
case ALUOpOr:
|
||||||
|
return fmt.Sprintf("or #%d", a.Val)
|
||||||
|
case ALUOpXor:
|
||||||
|
return fmt.Sprintf("xor #%d", a.Val)
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return fmt.Sprintf("lsh #%d", a.Val)
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return fmt.Sprintf("rsh #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpX executes A = A <Op> X
|
||||||
|
type ALUOpX struct {
|
||||||
|
Op ALUOp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcX | uint16(a.Op),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a ALUOpX) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return "add x"
|
||||||
|
case ALUOpSub:
|
||||||
|
return "sub x"
|
||||||
|
case ALUOpMul:
|
||||||
|
return "mul x"
|
||||||
|
case ALUOpDiv:
|
||||||
|
return "div x"
|
||||||
|
case ALUOpMod:
|
||||||
|
return "mod x"
|
||||||
|
case ALUOpAnd:
|
||||||
|
return "and x"
|
||||||
|
case ALUOpOr:
|
||||||
|
return "or x"
|
||||||
|
case ALUOpXor:
|
||||||
|
return "xor x"
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return "lsh x"
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return "rsh x"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NegateA executes A = -A.
|
||||||
|
type NegateA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a NegateA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | uint16(aluOpNeg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a NegateA) String() string {
|
||||||
|
return fmt.Sprintf("neg")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump skips the following Skip instructions in the program.
|
||||||
|
type Jump struct {
|
||||||
|
Skip uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a Jump) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | opJumpAlways,
|
||||||
|
K: a.Skip,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a Jump) String() string {
|
||||||
|
return fmt.Sprintf("ja %d", a.Skip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JumpIf skips the following Skip instructions in the program if A
|
||||||
|
// <Cond> Val is true.
|
||||||
|
type JumpIf struct {
|
||||||
|
Cond JumpTest
|
||||||
|
Val uint32
|
||||||
|
SkipTrue uint8
|
||||||
|
SkipFalse uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a JumpIf) Assemble() (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cond uint16
|
||||||
|
flip bool
|
||||||
|
)
|
||||||
|
switch a.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
cond = opJumpEqual
|
||||||
|
case JumpNotEqual:
|
||||||
|
cond, flip = opJumpEqual, true
|
||||||
|
case JumpGreaterThan:
|
||||||
|
cond = opJumpGT
|
||||||
|
case JumpLessThan:
|
||||||
|
cond, flip = opJumpGE, true
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
cond = opJumpGE
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
cond, flip = opJumpGT, true
|
||||||
|
case JumpBitsSet:
|
||||||
|
cond = opJumpSet
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
cond, flip = opJumpSet, true
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond)
|
||||||
|
}
|
||||||
|
jt, jf := a.SkipTrue, a.SkipFalse
|
||||||
|
if flip {
|
||||||
|
jt, jf = jf, jt
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | cond,
|
||||||
|
Jt: jt,
|
||||||
|
Jf: jf,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a JumpIf) String() string {
|
||||||
|
switch a.Cond {
|
||||||
|
// K == A
|
||||||
|
case JumpEqual:
|
||||||
|
return conditionalJump(a, "jeq", "jneq")
|
||||||
|
// K != A
|
||||||
|
case JumpNotEqual:
|
||||||
|
return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K > A
|
||||||
|
case JumpGreaterThan:
|
||||||
|
return conditionalJump(a, "jgt", "jle")
|
||||||
|
// K < A
|
||||||
|
case JumpLessThan:
|
||||||
|
return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K >= A
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
return conditionalJump(a, "jge", "jlt")
|
||||||
|
// K <= A
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K & A != 0
|
||||||
|
case JumpBitsSet:
|
||||||
|
if a.SkipFalse > 0 {
|
||||||
|
return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String()
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string {
|
||||||
|
if inst.SkipTrue > 0 {
|
||||||
|
if inst.SkipFalse > 0 {
|
||||||
|
return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetA exits the BPF program, returning the value of register A.
|
||||||
|
type RetA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a RetA) String() string {
|
||||||
|
return fmt.Sprintf("ret a")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetConstant exits the BPF program, returning a constant value.
|
||||||
|
type RetConstant struct {
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcConstant,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a RetConstant) String() string {
|
||||||
|
return fmt.Sprintf("ret #%d", a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXA copies the value of register X to register A.
|
||||||
|
type TXA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TXA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTXA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a TXA) String() string {
|
||||||
|
return fmt.Sprintf("txa")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAX copies the value of register A to register X.
|
||||||
|
type TAX struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TAX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTAX,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a TAX) String() string {
|
||||||
|
return fmt.Sprintf("tax")
|
||||||
|
}
|
||||||
|
|
||||||
|
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cls uint16
|
||||||
|
sz uint16
|
||||||
|
)
|
||||||
|
switch dst {
|
||||||
|
case RegA:
|
||||||
|
cls = opClsLoadA
|
||||||
|
case RegX:
|
||||||
|
cls = opClsLoadX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
|
||||||
|
}
|
||||||
|
switch loadSize {
|
||||||
|
case 1:
|
||||||
|
sz = opLoadWidth1
|
||||||
|
case 2:
|
||||||
|
sz = opLoadWidth2
|
||||||
|
case 4:
|
||||||
|
sz = opLoadWidth4
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: cls | sz | mode,
|
||||||
|
K: k,
|
||||||
|
}, nil
|
||||||
|
}
|
10
vendor/golang.org/x/net/bpf/setter.go
generated
vendored
Normal file
10
vendor/golang.org/x/net/bpf/setter.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
// A Setter is a type which can attach a compiled BPF filter to itself.
|
||||||
|
type Setter interface {
|
||||||
|
SetBPF(filter []RawInstruction) error
|
||||||
|
}
|
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A VM is an emulated BPF virtual machine.
|
||||||
|
type VM struct {
|
||||||
|
filter []Instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVM returns a new VM using the input BPF program.
|
||||||
|
func NewVM(filter []Instruction) (*VM, error) {
|
||||||
|
if len(filter) == 0 {
|
||||||
|
return nil, errors.New("one or more Instructions must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ins := range filter {
|
||||||
|
check := len(filter) - (i + 1)
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
// Check for out-of-bounds jumps in instructions
|
||||||
|
case Jump:
|
||||||
|
if check <= int(ins.Skip) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
|
||||||
|
}
|
||||||
|
case JumpIf:
|
||||||
|
if check <= int(ins.SkipTrue) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
||||||
|
}
|
||||||
|
if check <= int(ins.SkipFalse) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
||||||
|
}
|
||||||
|
// Check for division or modulus by zero
|
||||||
|
case ALUOpConstant:
|
||||||
|
if ins.Val != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return nil, errors.New("cannot divide by zero using ALUOpConstant")
|
||||||
|
}
|
||||||
|
// Check for unknown extensions
|
||||||
|
case LoadExtension:
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure last instruction is a return instruction
|
||||||
|
switch filter[len(filter)-1].(type) {
|
||||||
|
case RetA, RetConstant:
|
||||||
|
default:
|
||||||
|
return nil, errors.New("BPF program must end with RetA or RetConstant")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Though our VM works using disassembled instructions, we
|
||||||
|
// attempt to assemble the input filter anyway to ensure it is compatible
|
||||||
|
// with an operating system VM.
|
||||||
|
_, err := Assemble(filter)
|
||||||
|
|
||||||
|
return &VM{
|
||||||
|
filter: filter,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run runs the VM's BPF program against the input bytes.
|
||||||
|
// Run returns the number of bytes accepted by the BPF program, and any errors
|
||||||
|
// which occurred while processing the program.
|
||||||
|
func (v *VM) Run(in []byte) (int, error) {
|
||||||
|
var (
|
||||||
|
// Registers of the virtual machine
|
||||||
|
regA uint32
|
||||||
|
regX uint32
|
||||||
|
regScratch [16]uint32
|
||||||
|
|
||||||
|
// OK is true if the program should continue processing the next
|
||||||
|
// instruction, or false if not, causing the loop to break
|
||||||
|
ok = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(mdlayher): implement:
|
||||||
|
// - NegateA:
|
||||||
|
// - would require a change from uint32 registers to int32
|
||||||
|
// registers
|
||||||
|
|
||||||
|
// TODO(mdlayher): add interop tests that check signedness of ALU
|
||||||
|
// operations against kernel implementation, and make sure Go
|
||||||
|
// implementation matches behavior
|
||||||
|
|
||||||
|
for i := 0; i < len(v.filter) && ok; i++ {
|
||||||
|
ins := v.filter[i]
|
||||||
|
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
case ALUOpConstant:
|
||||||
|
regA = aluOpConstant(ins, regA)
|
||||||
|
case ALUOpX:
|
||||||
|
regA, ok = aluOpX(ins, regA, regX)
|
||||||
|
case Jump:
|
||||||
|
i += int(ins.Skip)
|
||||||
|
case JumpIf:
|
||||||
|
jump := jumpIf(ins, regA)
|
||||||
|
i += jump
|
||||||
|
case LoadAbsolute:
|
||||||
|
regA, ok = loadAbsolute(ins, in)
|
||||||
|
case LoadConstant:
|
||||||
|
regA, regX = loadConstant(ins, regA, regX)
|
||||||
|
case LoadExtension:
|
||||||
|
regA = loadExtension(ins, in)
|
||||||
|
case LoadIndirect:
|
||||||
|
regA, ok = loadIndirect(ins, in, regX)
|
||||||
|
case LoadMemShift:
|
||||||
|
regX, ok = loadMemShift(ins, in)
|
||||||
|
case LoadScratch:
|
||||||
|
regA, regX = loadScratch(ins, regScratch, regA, regX)
|
||||||
|
case RetA:
|
||||||
|
return int(regA), nil
|
||||||
|
case RetConstant:
|
||||||
|
return int(ins.Val), nil
|
||||||
|
case StoreScratch:
|
||||||
|
regScratch = storeScratch(ins, regScratch, regA, regX)
|
||||||
|
case TAX:
|
||||||
|
regX = regA
|
||||||
|
case TXA:
|
||||||
|
regA = regX
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
|
||||||
|
return aluOpCommon(ins.Op, regA, ins.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
|
||||||
|
// Guard against division or modulus by zero by terminating
|
||||||
|
// the program, as the OS BPF VM does
|
||||||
|
if regX == 0 {
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aluOpCommon(ins.Op, regA, regX), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
|
||||||
|
switch op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return regA + value
|
||||||
|
case ALUOpSub:
|
||||||
|
return regA - value
|
||||||
|
case ALUOpMul:
|
||||||
|
return regA * value
|
||||||
|
case ALUOpDiv:
|
||||||
|
// Division by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA / value
|
||||||
|
case ALUOpOr:
|
||||||
|
return regA | value
|
||||||
|
case ALUOpAnd:
|
||||||
|
return regA & value
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return regA << value
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return regA >> value
|
||||||
|
case ALUOpMod:
|
||||||
|
// Modulus by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA % value
|
||||||
|
case ALUOpXor:
|
||||||
|
return regA ^ value
|
||||||
|
default:
|
||||||
|
return regA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func jumpIf(ins JumpIf, value uint32) int {
|
||||||
|
var ok bool
|
||||||
|
inV := uint32(ins.Val)
|
||||||
|
|
||||||
|
switch ins.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
ok = value == inV
|
||||||
|
case JumpNotEqual:
|
||||||
|
ok = value != inV
|
||||||
|
case JumpGreaterThan:
|
||||||
|
ok = value > inV
|
||||||
|
case JumpLessThan:
|
||||||
|
ok = value < inV
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
ok = value >= inV
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
ok = value <= inV
|
||||||
|
case JumpBitsSet:
|
||||||
|
ok = (value & inV) != 0
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
ok = (value & inV) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return int(ins.SkipTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(ins.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = ins.Val
|
||||||
|
case RegX:
|
||||||
|
regX = ins.Val
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadExtension(ins LoadExtension, in []byte) uint32 {
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return uint32(len(in))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
|
||||||
|
offset := int(ins.Off) + int(regX)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
|
||||||
|
if !inBounds(len(in), offset, 0) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask off high 4 bits and multiply low 4 bits by 4
|
||||||
|
return uint32(in[offset]&0x0f) * 4, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func inBounds(inLen int, offset int, size int) bool {
|
||||||
|
return offset+size <= inLen
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
|
||||||
|
if !inBounds(len(in), offset, size) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint32(in[offset]), true
|
||||||
|
case 2:
|
||||||
|
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
|
||||||
|
case 4:
|
||||||
|
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid load size: %d", size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = regScratch[ins.N]
|
||||||
|
case RegX:
|
||||||
|
regX = regScratch[ins.N]
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
|
||||||
|
switch ins.Src {
|
||||||
|
case RegA:
|
||||||
|
regScratch[ins.N] = regA
|
||||||
|
case RegX:
|
||||||
|
regScratch[ins.N] = regX
|
||||||
|
}
|
||||||
|
|
||||||
|
return regScratch
|
||||||
|
}
|
104
vendor/golang.org/x/net/context/context.go
generated
vendored
104
vendor/golang.org/x/net/context/context.go
generated
vendored
|
@ -5,6 +5,8 @@
|
||||||
// Package context defines the Context type, which carries deadlines,
|
// Package context defines the Context type, which carries deadlines,
|
||||||
// cancelation signals, and other request-scoped values across API boundaries
|
// cancelation signals, and other request-scoped values across API boundaries
|
||||||
// and between processes.
|
// and between processes.
|
||||||
|
// As of Go 1.7 this package is available in the standard library under the
|
||||||
|
// name context. https://golang.org/pkg/context.
|
||||||
//
|
//
|
||||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
// Incoming requests to a server should create a Context, and outgoing calls to
|
||||||
// servers should accept a Context. The chain of function calls between must
|
// servers should accept a Context. The chain of function calls between must
|
||||||
|
@ -36,103 +38,6 @@
|
||||||
// Contexts.
|
// Contexts.
|
||||||
package context // import "golang.org/x/net/context"
|
package context // import "golang.org/x/net/context"
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// A Context carries a deadline, a cancelation signal, and other values across
|
|
||||||
// API boundaries.
|
|
||||||
//
|
|
||||||
// Context's methods may be called by multiple goroutines simultaneously.
|
|
||||||
type Context interface {
|
|
||||||
// Deadline returns the time when work done on behalf of this context
|
|
||||||
// should be canceled. Deadline returns ok==false when no deadline is
|
|
||||||
// set. Successive calls to Deadline return the same results.
|
|
||||||
Deadline() (deadline time.Time, ok bool)
|
|
||||||
|
|
||||||
// Done returns a channel that's closed when work done on behalf of this
|
|
||||||
// context should be canceled. Done may return nil if this context can
|
|
||||||
// never be canceled. Successive calls to Done return the same value.
|
|
||||||
//
|
|
||||||
// WithCancel arranges for Done to be closed when cancel is called;
|
|
||||||
// WithDeadline arranges for Done to be closed when the deadline
|
|
||||||
// expires; WithTimeout arranges for Done to be closed when the timeout
|
|
||||||
// elapses.
|
|
||||||
//
|
|
||||||
// Done is provided for use in select statements:
|
|
||||||
//
|
|
||||||
// // Stream generates values with DoSomething and sends them to out
|
|
||||||
// // until DoSomething returns an error or ctx.Done is closed.
|
|
||||||
// func Stream(ctx context.Context, out chan<- Value) error {
|
|
||||||
// for {
|
|
||||||
// v, err := DoSomething(ctx)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// select {
|
|
||||||
// case <-ctx.Done():
|
|
||||||
// return ctx.Err()
|
|
||||||
// case out <- v:
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// See http://blog.golang.org/pipelines for more examples of how to use
|
|
||||||
// a Done channel for cancelation.
|
|
||||||
Done() <-chan struct{}
|
|
||||||
|
|
||||||
// Err returns a non-nil error value after Done is closed. Err returns
|
|
||||||
// Canceled if the context was canceled or DeadlineExceeded if the
|
|
||||||
// context's deadline passed. No other values for Err are defined.
|
|
||||||
// After Done is closed, successive calls to Err return the same value.
|
|
||||||
Err() error
|
|
||||||
|
|
||||||
// Value returns the value associated with this context for key, or nil
|
|
||||||
// if no value is associated with key. Successive calls to Value with
|
|
||||||
// the same key returns the same result.
|
|
||||||
//
|
|
||||||
// Use context values only for request-scoped data that transits
|
|
||||||
// processes and API boundaries, not for passing optional parameters to
|
|
||||||
// functions.
|
|
||||||
//
|
|
||||||
// A key identifies a specific value in a Context. Functions that wish
|
|
||||||
// to store values in Context typically allocate a key in a global
|
|
||||||
// variable then use that key as the argument to context.WithValue and
|
|
||||||
// Context.Value. A key can be any type that supports equality;
|
|
||||||
// packages should define keys as an unexported type to avoid
|
|
||||||
// collisions.
|
|
||||||
//
|
|
||||||
// Packages that define a Context key should provide type-safe accessors
|
|
||||||
// for the values stores using that key:
|
|
||||||
//
|
|
||||||
// // Package user defines a User type that's stored in Contexts.
|
|
||||||
// package user
|
|
||||||
//
|
|
||||||
// import "golang.org/x/net/context"
|
|
||||||
//
|
|
||||||
// // User is the type of value stored in the Contexts.
|
|
||||||
// type User struct {...}
|
|
||||||
//
|
|
||||||
// // key is an unexported type for keys defined in this package.
|
|
||||||
// // This prevents collisions with keys defined in other packages.
|
|
||||||
// type key int
|
|
||||||
//
|
|
||||||
// // userKey is the key for user.User values in Contexts. It is
|
|
||||||
// // unexported; clients use user.NewContext and user.FromContext
|
|
||||||
// // instead of using this key directly.
|
|
||||||
// var userKey key = 0
|
|
||||||
//
|
|
||||||
// // NewContext returns a new Context that carries value u.
|
|
||||||
// func NewContext(ctx context.Context, u *User) context.Context {
|
|
||||||
// return context.WithValue(ctx, userKey, u)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // FromContext returns the User value stored in ctx, if any.
|
|
||||||
// func FromContext(ctx context.Context) (*User, bool) {
|
|
||||||
// u, ok := ctx.Value(userKey).(*User)
|
|
||||||
// return u, ok
|
|
||||||
// }
|
|
||||||
Value(key interface{}) interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
// values, and has no deadline. It is typically used by the main function,
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
// initialization, and tests, and as the top-level Context for incoming
|
||||||
|
@ -149,8 +54,3 @@ func Background() Context {
|
||||||
func TODO() Context {
|
func TODO() Context {
|
||||||
return todo
|
return todo
|
||||||
}
|
}
|
||||||
|
|
||||||
// A CancelFunc tells an operation to abandon its work.
|
|
||||||
// A CancelFunc does not wait for the work to stop.
|
|
||||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
|
||||||
type CancelFunc func()
|
|
||||||
|
|
20
vendor/golang.org/x/net/context/go19.go
generated
vendored
Normal file
20
vendor/golang.org/x/net/context/go19.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import "context" // standard library's context, as of Go 1.7
|
||||||
|
|
||||||
|
// A Context carries a deadline, a cancelation signal, and other values across
|
||||||
|
// API boundaries.
|
||||||
|
//
|
||||||
|
// Context's methods may be called by multiple goroutines simultaneously.
|
||||||
|
type Context = context.Context
|
||||||
|
|
||||||
|
// A CancelFunc tells an operation to abandon its work.
|
||||||
|
// A CancelFunc does not wait for the work to stop.
|
||||||
|
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||||
|
type CancelFunc = context.CancelFunc
|
109
vendor/golang.org/x/net/context/pre_go19.go
generated
vendored
Normal file
109
vendor/golang.org/x/net/context/pre_go19.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// A Context carries a deadline, a cancelation signal, and other values across
|
||||||
|
// API boundaries.
|
||||||
|
//
|
||||||
|
// Context's methods may be called by multiple goroutines simultaneously.
|
||||||
|
type Context interface {
|
||||||
|
// Deadline returns the time when work done on behalf of this context
|
||||||
|
// should be canceled. Deadline returns ok==false when no deadline is
|
||||||
|
// set. Successive calls to Deadline return the same results.
|
||||||
|
Deadline() (deadline time.Time, ok bool)
|
||||||
|
|
||||||
|
// Done returns a channel that's closed when work done on behalf of this
|
||||||
|
// context should be canceled. Done may return nil if this context can
|
||||||
|
// never be canceled. Successive calls to Done return the same value.
|
||||||
|
//
|
||||||
|
// WithCancel arranges for Done to be closed when cancel is called;
|
||||||
|
// WithDeadline arranges for Done to be closed when the deadline
|
||||||
|
// expires; WithTimeout arranges for Done to be closed when the timeout
|
||||||
|
// elapses.
|
||||||
|
//
|
||||||
|
// Done is provided for use in select statements:
|
||||||
|
//
|
||||||
|
// // Stream generates values with DoSomething and sends them to out
|
||||||
|
// // until DoSomething returns an error or ctx.Done is closed.
|
||||||
|
// func Stream(ctx context.Context, out chan<- Value) error {
|
||||||
|
// for {
|
||||||
|
// v, err := DoSomething(ctx)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// select {
|
||||||
|
// case <-ctx.Done():
|
||||||
|
// return ctx.Err()
|
||||||
|
// case out <- v:
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// See http://blog.golang.org/pipelines for more examples of how to use
|
||||||
|
// a Done channel for cancelation.
|
||||||
|
Done() <-chan struct{}
|
||||||
|
|
||||||
|
// Err returns a non-nil error value after Done is closed. Err returns
|
||||||
|
// Canceled if the context was canceled or DeadlineExceeded if the
|
||||||
|
// context's deadline passed. No other values for Err are defined.
|
||||||
|
// After Done is closed, successive calls to Err return the same value.
|
||||||
|
Err() error
|
||||||
|
|
||||||
|
// Value returns the value associated with this context for key, or nil
|
||||||
|
// if no value is associated with key. Successive calls to Value with
|
||||||
|
// the same key returns the same result.
|
||||||
|
//
|
||||||
|
// Use context values only for request-scoped data that transits
|
||||||
|
// processes and API boundaries, not for passing optional parameters to
|
||||||
|
// functions.
|
||||||
|
//
|
||||||
|
// A key identifies a specific value in a Context. Functions that wish
|
||||||
|
// to store values in Context typically allocate a key in a global
|
||||||
|
// variable then use that key as the argument to context.WithValue and
|
||||||
|
// Context.Value. A key can be any type that supports equality;
|
||||||
|
// packages should define keys as an unexported type to avoid
|
||||||
|
// collisions.
|
||||||
|
//
|
||||||
|
// Packages that define a Context key should provide type-safe accessors
|
||||||
|
// for the values stores using that key:
|
||||||
|
//
|
||||||
|
// // Package user defines a User type that's stored in Contexts.
|
||||||
|
// package user
|
||||||
|
//
|
||||||
|
// import "golang.org/x/net/context"
|
||||||
|
//
|
||||||
|
// // User is the type of value stored in the Contexts.
|
||||||
|
// type User struct {...}
|
||||||
|
//
|
||||||
|
// // key is an unexported type for keys defined in this package.
|
||||||
|
// // This prevents collisions with keys defined in other packages.
|
||||||
|
// type key int
|
||||||
|
//
|
||||||
|
// // userKey is the key for user.User values in Contexts. It is
|
||||||
|
// // unexported; clients use user.NewContext and user.FromContext
|
||||||
|
// // instead of using this key directly.
|
||||||
|
// var userKey key = 0
|
||||||
|
//
|
||||||
|
// // NewContext returns a new Context that carries value u.
|
||||||
|
// func NewContext(ctx context.Context, u *User) context.Context {
|
||||||
|
// return context.WithValue(ctx, userKey, u)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // FromContext returns the User value stored in ctx, if any.
|
||||||
|
// func FromContext(ctx context.Context) (*User, bool) {
|
||||||
|
// u, ok := ctx.Value(userKey).(*User)
|
||||||
|
// return u, ok
|
||||||
|
// }
|
||||||
|
Value(key interface{}) interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A CancelFunc tells an operation to abandon its work.
|
||||||
|
// A CancelFunc does not wait for the work to stop.
|
||||||
|
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||||
|
type CancelFunc func()
|
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
// A list of the possible cipher suite ids. Taken from
|
||||||
|
// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
|
||||||
|
|
||||||
|
const (
|
||||||
|
cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
|
||||||
|
// Reserved uint16 = 0x001C-1D
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
|
||||||
|
// Reserved uint16 = 0x0047-4F
|
||||||
|
// Reserved uint16 = 0x0050-58
|
||||||
|
// Reserved uint16 = 0x0059-5C
|
||||||
|
// Unassigned uint16 = 0x005D-5F
|
||||||
|
// Reserved uint16 = 0x0060-66
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
|
||||||
|
// Unassigned uint16 = 0x006E-83
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
|
||||||
|
// Unassigned uint16 = 0x00C6-FE
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
|
||||||
|
// Unassigned uint16 = 0x01-55,*
|
||||||
|
cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
|
||||||
|
// Unassigned uint16 = 0x5601 - 0xC000
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
|
||||||
|
// Unassigned uint16 = 0xC0B0-FF
|
||||||
|
// Unassigned uint16 = 0xC1-CB,*
|
||||||
|
// Unassigned uint16 = 0xCC00-A7
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
|
||||||
|
cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
|
||||||
|
)
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
// References:
|
||||||
|
// https://tools.ietf.org/html/rfc7540#appendix-A
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case cipher_TLS_NULL_WITH_NULL_NULL,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
2
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
2
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
|
@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
||||||
// convering panics into errors.
|
// converting panics into errors.
|
||||||
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
|
13
vendor/golang.org/x/net/http2/errors.go
generated
vendored
13
vendor/golang.org/x/net/http2/errors.go
generated
vendored
|
@ -87,13 +87,16 @@ type goAwayFlowError struct{}
|
||||||
|
|
||||||
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
||||||
|
|
||||||
// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
|
// connError represents an HTTP/2 ConnectionError error code, along
|
||||||
|
// with a string (for debugging) explaining why.
|
||||||
|
//
|
||||||
// Errors of this type are only returned by the frame parser functions
|
// Errors of this type are only returned by the frame parser functions
|
||||||
// and converted into ConnectionError(ErrCodeProtocol).
|
// and converted into ConnectionError(Code), after stashing away
|
||||||
|
// the Reason into the Framer's errDetail field, accessible via
|
||||||
|
// the (*Framer).ErrorDetail method.
|
||||||
type connError struct {
|
type connError struct {
|
||||||
Code ErrCode
|
Code ErrCode // the ConnectionError error code
|
||||||
Reason string
|
Reason string // additional reason
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e connError) Error() string {
|
func (e connError) Error() string {
|
||||||
|
|
27
vendor/golang.org/x/net/http2/go16.go
generated
vendored
27
vendor/golang.org/x/net/http2/go16.go
generated
vendored
|
@ -7,7 +7,6 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -15,29 +14,3 @@ import (
|
||||||
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
return t1.ExpectContinueTimeout
|
return t1.ExpectContinueTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// Reject cipher suites from Appendix A.
|
|
||||||
// "This list includes those cipher suites that do not
|
|
||||||
// offer an ephemeral key exchange and those that are
|
|
||||||
// based on the TLS null, stream or block cipher type"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
2
vendor/golang.org/x/net/http2/go18.go
generated
vendored
2
vendor/golang.org/x/net/http2/go18.go
generated
vendored
|
@ -52,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
|
||||||
func reqBodyIsNoBody(body io.ReadCloser) bool {
|
func reqBodyIsNoBody(body io.ReadCloser) bool {
|
||||||
return body == http.NoBody
|
return body == http.NoBody
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only
|
||||||
|
|
16
vendor/golang.org/x/net/http2/go19.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/http2/go19.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configureServer19(s *http.Server, conf *Server) error {
|
||||||
|
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
|
||||||
|
return nil
|
||||||
|
}
|
131
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
131
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
|
@ -125,77 +125,78 @@ func (t *headerFieldTable) idToIndex(id uint64) uint64 {
|
||||||
return k + 1
|
return k + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func pair(name, value string) HeaderField {
|
|
||||||
return HeaderField{Name: name, Value: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
||||||
var staticTable = newStaticTable()
|
var staticTable = newStaticTable()
|
||||||
|
var staticTableEntries = [...]HeaderField{
|
||||||
|
{Name: ":authority"},
|
||||||
|
{Name: ":method", Value: "GET"},
|
||||||
|
{Name: ":method", Value: "POST"},
|
||||||
|
{Name: ":path", Value: "/"},
|
||||||
|
{Name: ":path", Value: "/index.html"},
|
||||||
|
{Name: ":scheme", Value: "http"},
|
||||||
|
{Name: ":scheme", Value: "https"},
|
||||||
|
{Name: ":status", Value: "200"},
|
||||||
|
{Name: ":status", Value: "204"},
|
||||||
|
{Name: ":status", Value: "206"},
|
||||||
|
{Name: ":status", Value: "304"},
|
||||||
|
{Name: ":status", Value: "400"},
|
||||||
|
{Name: ":status", Value: "404"},
|
||||||
|
{Name: ":status", Value: "500"},
|
||||||
|
{Name: "accept-charset"},
|
||||||
|
{Name: "accept-encoding", Value: "gzip, deflate"},
|
||||||
|
{Name: "accept-language"},
|
||||||
|
{Name: "accept-ranges"},
|
||||||
|
{Name: "accept"},
|
||||||
|
{Name: "access-control-allow-origin"},
|
||||||
|
{Name: "age"},
|
||||||
|
{Name: "allow"},
|
||||||
|
{Name: "authorization"},
|
||||||
|
{Name: "cache-control"},
|
||||||
|
{Name: "content-disposition"},
|
||||||
|
{Name: "content-encoding"},
|
||||||
|
{Name: "content-language"},
|
||||||
|
{Name: "content-length"},
|
||||||
|
{Name: "content-location"},
|
||||||
|
{Name: "content-range"},
|
||||||
|
{Name: "content-type"},
|
||||||
|
{Name: "cookie"},
|
||||||
|
{Name: "date"},
|
||||||
|
{Name: "etag"},
|
||||||
|
{Name: "expect"},
|
||||||
|
{Name: "expires"},
|
||||||
|
{Name: "from"},
|
||||||
|
{Name: "host"},
|
||||||
|
{Name: "if-match"},
|
||||||
|
{Name: "if-modified-since"},
|
||||||
|
{Name: "if-none-match"},
|
||||||
|
{Name: "if-range"},
|
||||||
|
{Name: "if-unmodified-since"},
|
||||||
|
{Name: "last-modified"},
|
||||||
|
{Name: "link"},
|
||||||
|
{Name: "location"},
|
||||||
|
{Name: "max-forwards"},
|
||||||
|
{Name: "proxy-authenticate"},
|
||||||
|
{Name: "proxy-authorization"},
|
||||||
|
{Name: "range"},
|
||||||
|
{Name: "referer"},
|
||||||
|
{Name: "refresh"},
|
||||||
|
{Name: "retry-after"},
|
||||||
|
{Name: "server"},
|
||||||
|
{Name: "set-cookie"},
|
||||||
|
{Name: "strict-transport-security"},
|
||||||
|
{Name: "transfer-encoding"},
|
||||||
|
{Name: "user-agent"},
|
||||||
|
{Name: "vary"},
|
||||||
|
{Name: "via"},
|
||||||
|
{Name: "www-authenticate"},
|
||||||
|
}
|
||||||
|
|
||||||
func newStaticTable() *headerFieldTable {
|
func newStaticTable() *headerFieldTable {
|
||||||
t := &headerFieldTable{}
|
t := &headerFieldTable{}
|
||||||
t.init()
|
t.init()
|
||||||
t.addEntry(pair(":authority", ""))
|
for _, e := range staticTableEntries[:] {
|
||||||
t.addEntry(pair(":method", "GET"))
|
t.addEntry(e)
|
||||||
t.addEntry(pair(":method", "POST"))
|
}
|
||||||
t.addEntry(pair(":path", "/"))
|
|
||||||
t.addEntry(pair(":path", "/index.html"))
|
|
||||||
t.addEntry(pair(":scheme", "http"))
|
|
||||||
t.addEntry(pair(":scheme", "https"))
|
|
||||||
t.addEntry(pair(":status", "200"))
|
|
||||||
t.addEntry(pair(":status", "204"))
|
|
||||||
t.addEntry(pair(":status", "206"))
|
|
||||||
t.addEntry(pair(":status", "304"))
|
|
||||||
t.addEntry(pair(":status", "400"))
|
|
||||||
t.addEntry(pair(":status", "404"))
|
|
||||||
t.addEntry(pair(":status", "500"))
|
|
||||||
t.addEntry(pair("accept-charset", ""))
|
|
||||||
t.addEntry(pair("accept-encoding", "gzip, deflate"))
|
|
||||||
t.addEntry(pair("accept-language", ""))
|
|
||||||
t.addEntry(pair("accept-ranges", ""))
|
|
||||||
t.addEntry(pair("accept", ""))
|
|
||||||
t.addEntry(pair("access-control-allow-origin", ""))
|
|
||||||
t.addEntry(pair("age", ""))
|
|
||||||
t.addEntry(pair("allow", ""))
|
|
||||||
t.addEntry(pair("authorization", ""))
|
|
||||||
t.addEntry(pair("cache-control", ""))
|
|
||||||
t.addEntry(pair("content-disposition", ""))
|
|
||||||
t.addEntry(pair("content-encoding", ""))
|
|
||||||
t.addEntry(pair("content-language", ""))
|
|
||||||
t.addEntry(pair("content-length", ""))
|
|
||||||
t.addEntry(pair("content-location", ""))
|
|
||||||
t.addEntry(pair("content-range", ""))
|
|
||||||
t.addEntry(pair("content-type", ""))
|
|
||||||
t.addEntry(pair("cookie", ""))
|
|
||||||
t.addEntry(pair("date", ""))
|
|
||||||
t.addEntry(pair("etag", ""))
|
|
||||||
t.addEntry(pair("expect", ""))
|
|
||||||
t.addEntry(pair("expires", ""))
|
|
||||||
t.addEntry(pair("from", ""))
|
|
||||||
t.addEntry(pair("host", ""))
|
|
||||||
t.addEntry(pair("if-match", ""))
|
|
||||||
t.addEntry(pair("if-modified-since", ""))
|
|
||||||
t.addEntry(pair("if-none-match", ""))
|
|
||||||
t.addEntry(pair("if-range", ""))
|
|
||||||
t.addEntry(pair("if-unmodified-since", ""))
|
|
||||||
t.addEntry(pair("last-modified", ""))
|
|
||||||
t.addEntry(pair("link", ""))
|
|
||||||
t.addEntry(pair("location", ""))
|
|
||||||
t.addEntry(pair("max-forwards", ""))
|
|
||||||
t.addEntry(pair("proxy-authenticate", ""))
|
|
||||||
t.addEntry(pair("proxy-authorization", ""))
|
|
||||||
t.addEntry(pair("range", ""))
|
|
||||||
t.addEntry(pair("referer", ""))
|
|
||||||
t.addEntry(pair("refresh", ""))
|
|
||||||
t.addEntry(pair("retry-after", ""))
|
|
||||||
t.addEntry(pair("server", ""))
|
|
||||||
t.addEntry(pair("set-cookie", ""))
|
|
||||||
t.addEntry(pair("strict-transport-security", ""))
|
|
||||||
t.addEntry(pair("transfer-encoding", ""))
|
|
||||||
t.addEntry(pair("user-agent", ""))
|
|
||||||
t.addEntry(pair("vary", ""))
|
|
||||||
t.addEntry(pair("via", ""))
|
|
||||||
t.addEntry(pair("www-authenticate", ""))
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
vendor/golang.org/x/net/http2/http2.go
generated
vendored
8
vendor/golang.org/x/net/http2/http2.go
generated
vendored
|
@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) {
|
||||||
// validPseudoPath reports whether v is a valid :path pseudo-header
|
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||||
// value. It must be either:
|
// value. It must be either:
|
||||||
//
|
//
|
||||||
// *) a non-empty string starting with '/', but not with with "//",
|
// *) a non-empty string starting with '/'
|
||||||
// *) the string '*', for OPTIONS requests.
|
// *) the string '*', for OPTIONS requests.
|
||||||
//
|
//
|
||||||
// For now this is only used a quick check for deciding when to clean
|
// For now this is only used a quick check for deciding when to clean
|
||||||
// up Opaque URLs before sending requests from the Transport.
|
// up Opaque URLs before sending requests from the Transport.
|
||||||
// See golang.org/issue/16847
|
// See golang.org/issue/16847
|
||||||
|
//
|
||||||
|
// We used to enforce that the path also didn't start with "//", but
|
||||||
|
// Google's GFE accepts such paths and Chrome sends them, so ignore
|
||||||
|
// that part of the spec. See golang.org/issue/19103.
|
||||||
func validPseudoPath(v string) bool {
|
func validPseudoPath(v string) bool {
|
||||||
return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
|
return (len(v) > 0 && v[0] == '/') || v == "*"
|
||||||
}
|
}
|
||||||
|
|
25
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
25
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
|
@ -7,7 +7,6 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -20,27 +19,3 @@ func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// Reject cipher suites from Appendix A.
|
|
||||||
// "This list includes those cipher suites that do not
|
|
||||||
// offer an ephemeral key exchange and those that are
|
|
||||||
// based on the TLS null, stream or block cipher type"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
2
vendor/golang.org/x/net/http2/not_go18.go
generated
vendored
2
vendor/golang.org/x/net/http2/not_go18.go
generated
vendored
|
@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func reqBodyIsNoBody(io.ReadCloser) bool { return false }
|
func reqBodyIsNoBody(io.ReadCloser) bool { return false }
|
||||||
|
|
||||||
|
func go18httpNoBody() io.ReadCloser { return nil } // for tests only
|
||||||
|
|
16
vendor/golang.org/x/net/http2/not_go19.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/http2/not_go19.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configureServer19(s *http.Server, conf *Server) error {
|
||||||
|
// not supported prior to go1.9
|
||||||
|
return nil
|
||||||
|
}
|
16
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
16
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
|
@ -15,8 +15,8 @@ import (
|
||||||
// underlying buffer is an interface. (io.Pipe is always unbuffered)
|
// underlying buffer is an interface. (io.Pipe is always unbuffered)
|
||||||
type pipe struct {
|
type pipe struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
c sync.Cond // c.L lazily initialized to &p.mu
|
c sync.Cond // c.L lazily initialized to &p.mu
|
||||||
b pipeBuffer
|
b pipeBuffer // nil when done reading
|
||||||
err error // read error once empty. non-nil means closed.
|
err error // read error once empty. non-nil means closed.
|
||||||
breakErr error // immediate read error (caller doesn't see rest of b)
|
breakErr error // immediate read error (caller doesn't see rest of b)
|
||||||
donec chan struct{} // closed on error
|
donec chan struct{} // closed on error
|
||||||
|
@ -32,6 +32,9 @@ type pipeBuffer interface {
|
||||||
func (p *pipe) Len() int {
|
func (p *pipe) Len() int {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
if p.b == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return p.b.Len()
|
return p.b.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
if p.breakErr != nil {
|
if p.breakErr != nil {
|
||||||
return 0, p.breakErr
|
return 0, p.breakErr
|
||||||
}
|
}
|
||||||
if p.b.Len() > 0 {
|
if p.b != nil && p.b.Len() > 0 {
|
||||||
return p.b.Read(d)
|
return p.b.Read(d)
|
||||||
}
|
}
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
|
@ -55,6 +58,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
p.readFn() // e.g. copy trailers
|
p.readFn() // e.g. copy trailers
|
||||||
p.readFn = nil // not sticky like p.err
|
p.readFn = nil // not sticky like p.err
|
||||||
}
|
}
|
||||||
|
p.b = nil
|
||||||
return 0, p.err
|
return 0, p.err
|
||||||
}
|
}
|
||||||
p.c.Wait()
|
p.c.Wait()
|
||||||
|
@ -75,6 +79,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
return 0, errClosedPipeWrite
|
return 0, errClosedPipeWrite
|
||||||
}
|
}
|
||||||
|
if p.breakErr != nil {
|
||||||
|
return len(d), nil // discard when there is no reader
|
||||||
|
}
|
||||||
return p.b.Write(d)
|
return p.b.Write(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +116,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.readFn = fn
|
p.readFn = fn
|
||||||
|
if dst == &p.breakErr {
|
||||||
|
p.b = nil
|
||||||
|
}
|
||||||
*dst = err
|
*dst = err
|
||||||
p.closeDoneLocked()
|
p.closeDoneLocked()
|
||||||
}
|
}
|
||||||
|
|
306
vendor/golang.org/x/net/http2/server.go
generated
vendored
306
vendor/golang.org/x/net/http2/server.go
generated
vendored
|
@ -126,6 +126,11 @@ type Server struct {
|
||||||
// NewWriteScheduler constructs a write scheduler for a connection.
|
// NewWriteScheduler constructs a write scheduler for a connection.
|
||||||
// If nil, a default scheduler is chosen.
|
// If nil, a default scheduler is chosen.
|
||||||
NewWriteScheduler func() WriteScheduler
|
NewWriteScheduler func() WriteScheduler
|
||||||
|
|
||||||
|
// Internal state. This is a pointer (rather than embedded directly)
|
||||||
|
// so that we don't embed a Mutex in this struct, which will make the
|
||||||
|
// struct non-copyable, which might break some callers.
|
||||||
|
state *serverInternalState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initialConnRecvWindowSize() int32 {
|
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||||
|
@ -156,6 +161,40 @@ func (s *Server) maxConcurrentStreams() uint32 {
|
||||||
return defaultMaxStreams
|
return defaultMaxStreams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type serverInternalState struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
activeConns map[*serverConn]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) registerConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
s.activeConns[sc] = struct{}{}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) unregisterConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
delete(s.activeConns, sc)
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) startGracefulShutdown() {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
for sc := range s.activeConns {
|
||||||
|
sc.startGracefulShutdown()
|
||||||
|
}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
||||||
//
|
//
|
||||||
// The configuration conf may be nil.
|
// The configuration conf may be nil.
|
||||||
|
@ -168,21 +207,28 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
conf = new(Server)
|
conf = new(Server)
|
||||||
}
|
}
|
||||||
|
conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
|
||||||
if err := configureServer18(s, conf); err != nil {
|
if err := configureServer18(s, conf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := configureServer19(s, conf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if s.TLSConfig == nil {
|
if s.TLSConfig == nil {
|
||||||
s.TLSConfig = new(tls.Config)
|
s.TLSConfig = new(tls.Config)
|
||||||
} else if s.TLSConfig.CipherSuites != nil {
|
} else if s.TLSConfig.CipherSuites != nil {
|
||||||
// If they already provided a CipherSuite list, return
|
// If they already provided a CipherSuite list, return
|
||||||
// an error if it has a bad order or is missing
|
// an error if it has a bad order or is missing
|
||||||
// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
|
// ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
|
||||||
const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
|
||||||
haveRequired := false
|
haveRequired := false
|
||||||
sawBad := false
|
sawBad := false
|
||||||
for i, cs := range s.TLSConfig.CipherSuites {
|
for i, cs := range s.TLSConfig.CipherSuites {
|
||||||
if cs == requiredCipher {
|
switch cs {
|
||||||
|
case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
// Alternative MTI cipher to not discourage ECDSA-only servers.
|
||||||
|
// See http://golang.org/cl/30721 for further information.
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||||
haveRequired = true
|
haveRequired = true
|
||||||
}
|
}
|
||||||
if isBadCipher(cs) {
|
if isBadCipher(cs) {
|
||||||
|
@ -192,7 +238,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !haveRequired {
|
if !haveRequired {
|
||||||
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
|
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +338,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||||
streams: make(map[uint32]*stream),
|
streams: make(map[uint32]*stream),
|
||||||
readFrameCh: make(chan readFrameResult),
|
readFrameCh: make(chan readFrameResult),
|
||||||
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
||||||
wantStartPushCh: make(chan startPushRequest, 8),
|
serveMsgCh: make(chan interface{}, 8),
|
||||||
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
||||||
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
||||||
doneServing: make(chan struct{}),
|
doneServing: make(chan struct{}),
|
||||||
|
@ -305,6 +351,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||||
pushEnabled: true,
|
pushEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.state.registerConn(sc)
|
||||||
|
defer s.state.unregisterConn(sc)
|
||||||
|
|
||||||
// The net/http package sets the write deadline from the
|
// The net/http package sets the write deadline from the
|
||||||
// http.Server.WriteTimeout during the TLS handshake, but then
|
// http.Server.WriteTimeout during the TLS handshake, but then
|
||||||
// passes the connection off to us with the deadline already set.
|
// passes the connection off to us with the deadline already set.
|
||||||
|
@ -405,10 +454,9 @@ type serverConn struct {
|
||||||
doneServing chan struct{} // closed when serverConn.serve ends
|
doneServing chan struct{} // closed when serverConn.serve ends
|
||||||
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
||||||
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
||||||
wantStartPushCh chan startPushRequest // from handlers -> serve
|
|
||||||
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
||||||
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
||||||
testHookCh chan func(int) // code to run on the serve loop
|
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
||||||
flow flow // conn-wide (not stream-specific) outbound flow control
|
flow flow // conn-wide (not stream-specific) outbound flow control
|
||||||
inflow flow // conn-wide inbound flow control
|
inflow flow // conn-wide inbound flow control
|
||||||
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
||||||
|
@ -440,14 +488,15 @@ type serverConn struct {
|
||||||
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
||||||
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
||||||
goAwayCode ErrCode
|
goAwayCode ErrCode
|
||||||
shutdownTimerCh <-chan time.Time // nil until used
|
shutdownTimer *time.Timer // nil until used
|
||||||
shutdownTimer *time.Timer // nil until used
|
idleTimer *time.Timer // nil if unused
|
||||||
idleTimer *time.Timer // nil if unused
|
|
||||||
idleTimerCh <-chan time.Time // nil if unused
|
|
||||||
|
|
||||||
// Owned by the writeFrameAsync goroutine:
|
// Owned by the writeFrameAsync goroutine:
|
||||||
headerWriteBuf bytes.Buffer
|
headerWriteBuf bytes.Buffer
|
||||||
hpackEncoder *hpack.Encoder
|
hpackEncoder *hpack.Encoder
|
||||||
|
|
||||||
|
// Used by startGracefulShutdown.
|
||||||
|
shutdownOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) maxHeaderListSize() uint32 {
|
func (sc *serverConn) maxHeaderListSize() uint32 {
|
||||||
|
@ -603,7 +652,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
|
if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
|
||||||
// Boring, expected errors.
|
// Boring, expected errors.
|
||||||
sc.vlogf(format, args...)
|
sc.vlogf(format, args...)
|
||||||
} else {
|
} else {
|
||||||
|
@ -748,19 +797,15 @@ func (sc *serverConn) serve() {
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
|
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout != 0 {
|
||||||
sc.idleTimer = time.NewTimer(sc.srv.IdleTimeout)
|
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||||
defer sc.idleTimer.Stop()
|
defer sc.idleTimer.Stop()
|
||||||
sc.idleTimerCh = sc.idleTimer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
var gracefulShutdownCh <-chan struct{}
|
|
||||||
if sc.hs != nil {
|
|
||||||
gracefulShutdownCh = h1ServerShutdownChan(sc.hs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go sc.readFrames() // closed by defer sc.conn.Close above
|
go sc.readFrames() // closed by defer sc.conn.Close above
|
||||||
|
|
||||||
settingsTimer := time.NewTimer(firstSettingsTimeout)
|
settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
|
||||||
|
defer settingsTimer.Stop()
|
||||||
|
|
||||||
loopNum := 0
|
loopNum := 0
|
||||||
for {
|
for {
|
||||||
loopNum++
|
loopNum++
|
||||||
|
@ -771,8 +816,6 @@ func (sc *serverConn) serve() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sc.writeFrame(wr)
|
sc.writeFrame(wr)
|
||||||
case spr := <-sc.wantStartPushCh:
|
|
||||||
sc.startPush(spr)
|
|
||||||
case res := <-sc.wroteFrameCh:
|
case res := <-sc.wroteFrameCh:
|
||||||
sc.wroteFrame(res)
|
sc.wroteFrame(res)
|
||||||
case res := <-sc.readFrameCh:
|
case res := <-sc.readFrameCh:
|
||||||
|
@ -780,36 +823,85 @@ func (sc *serverConn) serve() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res.readMore()
|
res.readMore()
|
||||||
if settingsTimer.C != nil {
|
if settingsTimer != nil {
|
||||||
settingsTimer.Stop()
|
settingsTimer.Stop()
|
||||||
settingsTimer.C = nil
|
settingsTimer = nil
|
||||||
}
|
}
|
||||||
case m := <-sc.bodyReadCh:
|
case m := <-sc.bodyReadCh:
|
||||||
sc.noteBodyRead(m.st, m.n)
|
sc.noteBodyRead(m.st, m.n)
|
||||||
case <-settingsTimer.C:
|
case msg := <-sc.serveMsgCh:
|
||||||
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
switch v := msg.(type) {
|
||||||
return
|
case func(int):
|
||||||
case <-gracefulShutdownCh:
|
v(loopNum) // for testing
|
||||||
gracefulShutdownCh = nil
|
case *serverMessage:
|
||||||
sc.startGracefulShutdown()
|
switch v {
|
||||||
case <-sc.shutdownTimerCh:
|
case settingsTimerMsg:
|
||||||
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
||||||
return
|
return
|
||||||
case <-sc.idleTimerCh:
|
case idleTimerMsg:
|
||||||
sc.vlogf("connection is idle")
|
sc.vlogf("connection is idle")
|
||||||
sc.goAway(ErrCodeNo)
|
sc.goAway(ErrCodeNo)
|
||||||
case fn := <-sc.testHookCh:
|
case shutdownTimerMsg:
|
||||||
fn(loopNum)
|
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
||||||
|
return
|
||||||
|
case gracefulShutdownMsg:
|
||||||
|
sc.startGracefulShutdownInternal()
|
||||||
|
default:
|
||||||
|
panic("unknown timer")
|
||||||
|
}
|
||||||
|
case *startPushRequest:
|
||||||
|
sc.startPush(v)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected type %T", v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
|
// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
|
||||||
return
|
// with no error code (graceful shutdown), don't start the timer until
|
||||||
|
// all open streams have been completed.
|
||||||
|
sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
|
||||||
|
gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
|
||||||
|
if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
|
||||||
|
sc.shutDownIn(goAwayTimeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// readPreface reads the ClientPreface greeting from the peer
|
func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
|
||||||
// or returns an error on timeout or an invalid greeting.
|
select {
|
||||||
|
case <-sc.doneServing:
|
||||||
|
case <-sharedCh:
|
||||||
|
close(privateCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverMessage int
|
||||||
|
|
||||||
|
// Message values sent to serveMsgCh.
|
||||||
|
var (
|
||||||
|
settingsTimerMsg = new(serverMessage)
|
||||||
|
idleTimerMsg = new(serverMessage)
|
||||||
|
shutdownTimerMsg = new(serverMessage)
|
||||||
|
gracefulShutdownMsg = new(serverMessage)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
||||||
|
func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
|
||||||
|
func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
|
||||||
|
|
||||||
|
func (sc *serverConn) sendServeMsg(msg interface{}) {
|
||||||
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
select {
|
||||||
|
case sc.serveMsgCh <- msg:
|
||||||
|
case <-sc.doneServing:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errPrefaceTimeout = errors.New("timeout waiting for client preface")
|
||||||
|
|
||||||
|
// readPreface reads the ClientPreface greeting from the peer or
|
||||||
|
// returns errPrefaceTimeout on timeout, or an error if the greeting
|
||||||
|
// is invalid.
|
||||||
func (sc *serverConn) readPreface() error {
|
func (sc *serverConn) readPreface() error {
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -827,7 +919,7 @@ func (sc *serverConn) readPreface() error {
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
return errors.New("timeout waiting for client preface")
|
return errPrefaceTimeout
|
||||||
case err := <-errc:
|
case err := <-errc:
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
|
@ -1125,33 +1217,43 @@ func (sc *serverConn) scheduleFrameWrite() {
|
||||||
sc.inFrameScheduleLoop = false
|
sc.inFrameScheduleLoop = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// startGracefulShutdown sends a GOAWAY with ErrCodeNo to tell the
|
// startGracefulShutdown gracefully shuts down a connection. This
|
||||||
// client we're gracefully shutting down. The connection isn't closed
|
// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
|
||||||
// until all current streams are done.
|
// shutting down. The connection isn't closed until all current
|
||||||
|
// streams are done.
|
||||||
|
//
|
||||||
|
// startGracefulShutdown returns immediately; it does not wait until
|
||||||
|
// the connection has shut down.
|
||||||
func (sc *serverConn) startGracefulShutdown() {
|
func (sc *serverConn) startGracefulShutdown() {
|
||||||
sc.goAwayIn(ErrCodeNo, 0)
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// After sending GOAWAY, the connection will close after goAwayTimeout.
|
||||||
|
// If we close the connection immediately after sending GOAWAY, there may
|
||||||
|
// be unsent data in our kernel receive buffer, which will cause the kernel
|
||||||
|
// to send a TCP RST on close() instead of a FIN. This RST will abort the
|
||||||
|
// connection immediately, whether or not the client had received the GOAWAY.
|
||||||
|
//
|
||||||
|
// Ideally we should delay for at least 1 RTT + epsilon so the client has
|
||||||
|
// a chance to read the GOAWAY and stop sending messages. Measuring RTT
|
||||||
|
// is hard, so we approximate with 1 second. See golang.org/issue/18701.
|
||||||
|
//
|
||||||
|
// This is a var so it can be shorter in tests, where all requests uses the
|
||||||
|
// loopback interface making the expected RTT very small.
|
||||||
|
//
|
||||||
|
// TODO: configurable?
|
||||||
|
var goAwayTimeout = 1 * time.Second
|
||||||
|
|
||||||
|
func (sc *serverConn) startGracefulShutdownInternal() {
|
||||||
|
sc.goAway(ErrCodeNo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) goAway(code ErrCode) {
|
func (sc *serverConn) goAway(code ErrCode) {
|
||||||
sc.serveG.check()
|
|
||||||
var forceCloseIn time.Duration
|
|
||||||
if code != ErrCodeNo {
|
|
||||||
forceCloseIn = 250 * time.Millisecond
|
|
||||||
} else {
|
|
||||||
// TODO: configurable
|
|
||||||
forceCloseIn = 1 * time.Second
|
|
||||||
}
|
|
||||||
sc.goAwayIn(code, forceCloseIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
if sc.inGoAway {
|
if sc.inGoAway {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if forceCloseIn != 0 {
|
|
||||||
sc.shutDownIn(forceCloseIn)
|
|
||||||
}
|
|
||||||
sc.inGoAway = true
|
sc.inGoAway = true
|
||||||
sc.needToSendGoAway = true
|
sc.needToSendGoAway = true
|
||||||
sc.goAwayCode = code
|
sc.goAwayCode = code
|
||||||
|
@ -1160,8 +1262,7 @@ func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
||||||
|
|
||||||
func (sc *serverConn) shutDownIn(d time.Duration) {
|
func (sc *serverConn) shutDownIn(d time.Duration) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
sc.shutdownTimer = time.NewTimer(d)
|
sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
|
||||||
sc.shutdownTimerCh = sc.shutdownTimer.C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) resetStream(se StreamError) {
|
func (sc *serverConn) resetStream(se StreamError) {
|
||||||
|
@ -1359,7 +1460,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
||||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||||
}
|
}
|
||||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p := st.body; p != nil {
|
if p := st.body; p != nil {
|
||||||
|
@ -1546,7 +1647,7 @@ func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
|
||||||
} else {
|
} else {
|
||||||
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
||||||
}
|
}
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.8
|
// http://tools.ietf.org/html/rfc7540#section-6.8
|
||||||
// We should not create any new streams, which means we should disable push.
|
// We should not create any new streams, which means we should disable push.
|
||||||
sc.pushEnabled = false
|
sc.pushEnabled = false
|
||||||
|
@ -2163,6 +2264,7 @@ type responseWriterState struct {
|
||||||
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
||||||
sentHeader bool // have we sent the header frame?
|
sentHeader bool // have we sent the header frame?
|
||||||
handlerDone bool // handler has finished
|
handlerDone bool // handler has finished
|
||||||
|
dirty bool // a Write failed; don't reuse this responseWriterState
|
||||||
|
|
||||||
sentContentLen int64 // non-zero if handler set a Content-Length header
|
sentContentLen int64 // non-zero if handler set a Content-Length header
|
||||||
wroteBytes int64
|
wroteBytes int64
|
||||||
|
@ -2220,7 +2322,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
clen = strconv.Itoa(len(p))
|
clen = strconv.Itoa(len(p))
|
||||||
}
|
}
|
||||||
_, hasContentType := rws.snapHeader["Content-Type"]
|
_, hasContentType := rws.snapHeader["Content-Type"]
|
||||||
if !hasContentType && bodyAllowedForStatus(rws.status) {
|
if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||||
ctype = http.DetectContentType(p)
|
ctype = http.DetectContentType(p)
|
||||||
}
|
}
|
||||||
var date string
|
var date string
|
||||||
|
@ -2244,6 +2346,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
date: date,
|
date: date,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
rws.dirty = true
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if endStream {
|
if endStream {
|
||||||
|
@ -2265,6 +2368,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
if len(p) > 0 || endStream {
|
if len(p) > 0 || endStream {
|
||||||
// only send a 0 byte DATA frame if we're ending the stream.
|
// only send a 0 byte DATA frame if we're ending the stream.
|
||||||
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
||||||
|
rws.dirty = true
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2276,6 +2380,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
trailers: rws.trailers,
|
trailers: rws.trailers,
|
||||||
endStream: true,
|
endStream: true,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
rws.dirty = true
|
||||||
|
}
|
||||||
return len(p), err
|
return len(p), err
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
|
@ -2383,7 +2490,26 @@ func (w *responseWriter) Header() http.Header {
|
||||||
return rws.handlerHeader
|
return rws.handlerHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
|
||||||
|
func checkWriteHeaderCode(code int) {
|
||||||
|
// Issue 22880: require valid WriteHeader status codes.
|
||||||
|
// For now we only enforce that it's three digits.
|
||||||
|
// In the future we might block things over 599 (600 and above aren't defined
|
||||||
|
// at http://httpwg.org/specs/rfc7231.html#status.codes)
|
||||||
|
// and we might block under 200 (once we have more mature 1xx support).
|
||||||
|
// But for now any three digits.
|
||||||
|
//
|
||||||
|
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
|
||||||
|
// no equivalent bogus thing we can realistically send in HTTP/2,
|
||||||
|
// so we'll consistently panic instead and help people find their bugs
|
||||||
|
// early. (We can't return an error from WriteHeader even if we wanted to.)
|
||||||
|
if code < 100 || code > 999 {
|
||||||
|
panic(fmt.Sprintf("invalid WriteHeader code %v", code))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *responseWriter) WriteHeader(code int) {
|
func (w *responseWriter) WriteHeader(code int) {
|
||||||
|
checkWriteHeaderCode(code)
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
if rws == nil {
|
if rws == nil {
|
||||||
panic("WriteHeader called after Handler finished")
|
panic("WriteHeader called after Handler finished")
|
||||||
|
@ -2415,7 +2541,7 @@ func cloneHeader(h http.Header) http.Header {
|
||||||
//
|
//
|
||||||
// * Handler calls w.Write or w.WriteString ->
|
// * Handler calls w.Write or w.WriteString ->
|
||||||
// * -> rws.bw (*bufio.Writer) ->
|
// * -> rws.bw (*bufio.Writer) ->
|
||||||
// * (Handler migth call Flush)
|
// * (Handler might call Flush)
|
||||||
// * -> chunkWriter{rws}
|
// * -> chunkWriter{rws}
|
||||||
// * -> responseWriterState.writeChunk(p []byte)
|
// * -> responseWriterState.writeChunk(p []byte)
|
||||||
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
|
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
|
||||||
|
@ -2454,10 +2580,19 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
|
||||||
|
|
||||||
func (w *responseWriter) handlerDone() {
|
func (w *responseWriter) handlerDone() {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
|
dirty := rws.dirty
|
||||||
rws.handlerDone = true
|
rws.handlerDone = true
|
||||||
w.Flush()
|
w.Flush()
|
||||||
w.rws = nil
|
w.rws = nil
|
||||||
responseWriterStatePool.Put(rws)
|
if !dirty {
|
||||||
|
// Only recycle the pool if all prior Write calls to
|
||||||
|
// the serverConn goroutine completed successfully. If
|
||||||
|
// they returned earlier due to resets from the peer
|
||||||
|
// there might still be write goroutines outstanding
|
||||||
|
// from the serverConn referencing the rws memory. See
|
||||||
|
// issue 20704.
|
||||||
|
responseWriterStatePool.Put(rws)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push errors.
|
// Push errors.
|
||||||
|
@ -2539,7 +2674,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
||||||
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := startPushRequest{
|
msg := &startPushRequest{
|
||||||
parent: st,
|
parent: st,
|
||||||
method: opts.Method,
|
method: opts.Method,
|
||||||
url: u,
|
url: u,
|
||||||
|
@ -2552,7 +2687,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
||||||
return errClientDisconnected
|
return errClientDisconnected
|
||||||
case <-st.cw:
|
case <-st.cw:
|
||||||
return errStreamClosed
|
return errStreamClosed
|
||||||
case sc.wantStartPushCh <- msg:
|
case sc.serveMsgCh <- msg:
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -2574,7 +2709,7 @@ type startPushRequest struct {
|
||||||
done chan error
|
done chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) startPush(msg startPushRequest) {
|
func (sc *serverConn) startPush(msg *startPushRequest) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
||||||
|
@ -2613,7 +2748,7 @@ func (sc *serverConn) startPush(msg startPushRequest) {
|
||||||
// A server that is unable to establish a new stream identifier can send a GOAWAY
|
// A server that is unable to establish a new stream identifier can send a GOAWAY
|
||||||
// frame so that the client is forced to open a new connection for new streams.
|
// frame so that the client is forced to open a new connection for new streams.
|
||||||
if sc.maxPushPromiseID+2 >= 1<<31 {
|
if sc.maxPushPromiseID+2 >= 1<<31 {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
return 0, ErrPushLimitReached
|
return 0, ErrPushLimitReached
|
||||||
}
|
}
|
||||||
sc.maxPushPromiseID += 2
|
sc.maxPushPromiseID += 2
|
||||||
|
@ -2738,31 +2873,6 @@ var badTrailer = map[string]bool{
|
||||||
"Www-Authenticate": true,
|
"Www-Authenticate": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// h1ServerShutdownChan returns a channel that will be closed when the
|
|
||||||
// provided *http.Server wants to shut down.
|
|
||||||
//
|
|
||||||
// This is a somewhat hacky way to get at http1 innards. It works
|
|
||||||
// when the http2 code is bundled into the net/http package in the
|
|
||||||
// standard library. The alternatives ended up making the cmd/go tool
|
|
||||||
// depend on http Servers. This is the lightest option for now.
|
|
||||||
// This is tested via the TestServeShutdown* tests in net/http.
|
|
||||||
func h1ServerShutdownChan(hs *http.Server) <-chan struct{} {
|
|
||||||
if fn := testh1ServerShutdownChan; fn != nil {
|
|
||||||
return fn(hs)
|
|
||||||
}
|
|
||||||
var x interface{} = hs
|
|
||||||
type I interface {
|
|
||||||
getDoneChan() <-chan struct{}
|
|
||||||
}
|
|
||||||
if hs, ok := x.(I); ok {
|
|
||||||
return hs.getDoneChan()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional test hook for h1ServerShutdownChan.
|
|
||||||
var testh1ServerShutdownChan func(hs *http.Server) <-chan struct{}
|
|
||||||
|
|
||||||
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
||||||
// disabled. See comments on h1ServerShutdownChan above for why
|
// disabled. See comments on h1ServerShutdownChan above for why
|
||||||
// the code is written this way.
|
// the code is written this way.
|
||||||
|
|
532
vendor/golang.org/x/net/http2/transport.go
generated
vendored
532
vendor/golang.org/x/net/http2/transport.go
generated
vendored
|
@ -18,6 +18,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
mathrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -86,7 +87,7 @@ type Transport struct {
|
||||||
|
|
||||||
// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
|
// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
|
||||||
// send in the initial settings frame. It is how many bytes
|
// send in the initial settings frame. It is how many bytes
|
||||||
// of response headers are allow. Unlike the http2 spec, zero here
|
// of response headers are allowed. Unlike the http2 spec, zero here
|
||||||
// means to use a default limit (currently 10MB). If you actually
|
// means to use a default limit (currently 10MB). If you actually
|
||||||
// want to advertise an ulimited value to the peer, Transport
|
// want to advertise an ulimited value to the peer, Transport
|
||||||
// interprets the highest possible value here (0xffffffff or 1<<32-1)
|
// interprets the highest possible value here (0xffffffff or 1<<32-1)
|
||||||
|
@ -164,15 +165,17 @@ type ClientConn struct {
|
||||||
goAwayDebug string // goAway frame's debug data, retained as a string
|
goAwayDebug string // goAway frame's debug data, retained as a string
|
||||||
streams map[uint32]*clientStream // client-initiated
|
streams map[uint32]*clientStream // client-initiated
|
||||||
nextStreamID uint32
|
nextStreamID uint32
|
||||||
|
pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
|
||||||
pings map[[8]byte]chan struct{} // in flight ping data to notification channel
|
pings map[[8]byte]chan struct{} // in flight ping data to notification channel
|
||||||
bw *bufio.Writer
|
bw *bufio.Writer
|
||||||
br *bufio.Reader
|
br *bufio.Reader
|
||||||
fr *Framer
|
fr *Framer
|
||||||
lastActive time.Time
|
lastActive time.Time
|
||||||
// Settings from peer: (also guarded by mu)
|
// Settings from peer: (also guarded by mu)
|
||||||
maxFrameSize uint32
|
maxFrameSize uint32
|
||||||
maxConcurrentStreams uint32
|
maxConcurrentStreams uint32
|
||||||
initialWindowSize uint32
|
peerMaxHeaderListSize uint64
|
||||||
|
initialWindowSize uint32
|
||||||
|
|
||||||
hbuf bytes.Buffer // HPACK encoder writes into this
|
hbuf bytes.Buffer // HPACK encoder writes into this
|
||||||
henc *hpack.Encoder
|
henc *hpack.Encoder
|
||||||
|
@ -216,35 +219,45 @@ type clientStream struct {
|
||||||
resTrailer *http.Header // client's Response.Trailer
|
resTrailer *http.Header // client's Response.Trailer
|
||||||
}
|
}
|
||||||
|
|
||||||
// awaitRequestCancel runs in its own goroutine and waits for the user
|
// awaitRequestCancel waits for the user to cancel a request or for the done
|
||||||
// to cancel a RoundTrip request, its context to expire, or for the
|
// channel to be signaled. A non-nil error is returned only if the request was
|
||||||
// request to be done (any way it might be removed from the cc.streams
|
// canceled.
|
||||||
// map: peer reset, successful completion, TCP connection breakage,
|
func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
|
||||||
// etc)
|
|
||||||
func (cs *clientStream) awaitRequestCancel(req *http.Request) {
|
|
||||||
ctx := reqContext(req)
|
ctx := reqContext(req)
|
||||||
if req.Cancel == nil && ctx.Done() == nil {
|
if req.Cancel == nil && ctx.Done() == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-req.Cancel:
|
case <-req.Cancel:
|
||||||
cs.cancelStream()
|
return errRequestCanceled
|
||||||
cs.bufPipe.CloseWithError(errRequestCanceled)
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// awaitRequestCancel waits for the user to cancel a request, its context to
|
||||||
|
// expire, or for the request to be done (any way it might be removed from the
|
||||||
|
// cc.streams map: peer reset, successful completion, TCP connection breakage,
|
||||||
|
// etc). If the request is canceled, then cs will be canceled and closed.
|
||||||
|
func (cs *clientStream) awaitRequestCancel(req *http.Request) {
|
||||||
|
if err := awaitRequestCancel(req, cs.done); err != nil {
|
||||||
cs.cancelStream()
|
cs.cancelStream()
|
||||||
cs.bufPipe.CloseWithError(ctx.Err())
|
cs.bufPipe.CloseWithError(err)
|
||||||
case <-cs.done:
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *clientStream) cancelStream() {
|
func (cs *clientStream) cancelStream() {
|
||||||
cs.cc.mu.Lock()
|
cc := cs.cc
|
||||||
|
cc.mu.Lock()
|
||||||
didReset := cs.didReset
|
didReset := cs.didReset
|
||||||
cs.didReset = true
|
cs.didReset = true
|
||||||
cs.cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
if !didReset {
|
if !didReset {
|
||||||
cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||||
|
cc.forgetStreamID(cs.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +274,13 @@ func (cs *clientStream) checkResetOrDone() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *clientStream) getStartedWrite() bool {
|
||||||
|
cc := cs.cc
|
||||||
|
cc.mu.Lock()
|
||||||
|
defer cc.mu.Unlock()
|
||||||
|
return cs.startedWrite
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *clientStream) abortRequestBodyWrite(err error) {
|
func (cs *clientStream) abortRequestBodyWrite(err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
panic("nil error")
|
panic("nil error")
|
||||||
|
@ -329,17 +349,28 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := authorityAddr(req.URL.Scheme, req.URL.Host)
|
addr := authorityAddr(req.URL.Scheme, req.URL.Host)
|
||||||
for {
|
for retry := 0; ; retry++ {
|
||||||
cc, err := t.connPool().GetClientConn(req, addr)
|
cc, err := t.connPool().GetClientConn(req, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
|
t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
traceGotConn(req, cc)
|
traceGotConn(req, cc)
|
||||||
res, err := cc.RoundTrip(req)
|
res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
|
||||||
if err != nil {
|
if err != nil && retry <= 6 {
|
||||||
if req, err = shouldRetryRequest(req, err); err == nil {
|
if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
|
||||||
continue
|
// After the first retry, do exponential backoff with 10% jitter.
|
||||||
|
if retry == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
backoff := float64(uint(1) << (uint(retry) - 1))
|
||||||
|
backoff += backoff * (0.1 * mathrand.Float64())
|
||||||
|
select {
|
||||||
|
case <-time.After(time.Second * time.Duration(backoff)):
|
||||||
|
continue
|
||||||
|
case <-reqContext(req).Done():
|
||||||
|
return nil, reqContext(req).Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -360,43 +391,50 @@ func (t *Transport) CloseIdleConnections() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errClientConnClosed = errors.New("http2: client conn is closed")
|
errClientConnClosed = errors.New("http2: client conn is closed")
|
||||||
errClientConnUnusable = errors.New("http2: client conn not usable")
|
errClientConnUnusable = errors.New("http2: client conn not usable")
|
||||||
|
errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
|
||||||
errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
|
|
||||||
errClientConnGotGoAwayAfterSomeReqBody = errors.New("http2: Transport received Server's graceful shutdown GOAWAY; some request body already written")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// shouldRetryRequest is called by RoundTrip when a request fails to get
|
// shouldRetryRequest is called by RoundTrip when a request fails to get
|
||||||
// response headers. It is always called with a non-nil error.
|
// response headers. It is always called with a non-nil error.
|
||||||
// It returns either a request to retry (either the same request, or a
|
// It returns either a request to retry (either the same request, or a
|
||||||
// modified clone), or an error if the request can't be replayed.
|
// modified clone), or an error if the request can't be replayed.
|
||||||
func shouldRetryRequest(req *http.Request, err error) (*http.Request, error) {
|
func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
|
||||||
switch err {
|
if !canRetryError(err) {
|
||||||
default:
|
|
||||||
return nil, err
|
return nil, err
|
||||||
case errClientConnUnusable, errClientConnGotGoAway:
|
|
||||||
return req, nil
|
|
||||||
case errClientConnGotGoAwayAfterSomeReqBody:
|
|
||||||
// If the Body is nil (or http.NoBody), it's safe to reuse
|
|
||||||
// this request and its Body.
|
|
||||||
if req.Body == nil || reqBodyIsNoBody(req.Body) {
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
// Otherwise we depend on the Request having its GetBody
|
|
||||||
// func defined.
|
|
||||||
getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
|
|
||||||
if getBody == nil {
|
|
||||||
return nil, errors.New("http2: Transport: peer server initiated graceful shutdown after some of Request.Body was written; define Request.GetBody to avoid this error")
|
|
||||||
}
|
|
||||||
body, err := getBody()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newReq := *req
|
|
||||||
newReq.Body = body
|
|
||||||
return &newReq, nil
|
|
||||||
}
|
}
|
||||||
|
if !afterBodyWrite {
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
// If the Body is nil (or http.NoBody), it's safe to reuse
|
||||||
|
// this request and its Body.
|
||||||
|
if req.Body == nil || reqBodyIsNoBody(req.Body) {
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
// Otherwise we depend on the Request having its GetBody
|
||||||
|
// func defined.
|
||||||
|
getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
|
||||||
|
if getBody == nil {
|
||||||
|
return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
|
||||||
|
}
|
||||||
|
body, err := getBody()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newReq := *req
|
||||||
|
newReq.Body = body
|
||||||
|
return &newReq, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func canRetryError(err error) bool {
|
||||||
|
if err == errClientConnUnusable || err == errClientConnGotGoAway {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if se, ok := err.(StreamError); ok {
|
||||||
|
return se.Code == ErrCodeRefusedStream
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
|
||||||
|
@ -474,17 +512,18 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
|
||||||
|
|
||||||
func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
|
||||||
cc := &ClientConn{
|
cc := &ClientConn{
|
||||||
t: t,
|
t: t,
|
||||||
tconn: c,
|
tconn: c,
|
||||||
readerDone: make(chan struct{}),
|
readerDone: make(chan struct{}),
|
||||||
nextStreamID: 1,
|
nextStreamID: 1,
|
||||||
maxFrameSize: 16 << 10, // spec default
|
maxFrameSize: 16 << 10, // spec default
|
||||||
initialWindowSize: 65535, // spec default
|
initialWindowSize: 65535, // spec default
|
||||||
maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough.
|
maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough.
|
||||||
streams: make(map[uint32]*clientStream),
|
peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
|
||||||
singleUse: singleUse,
|
streams: make(map[uint32]*clientStream),
|
||||||
wantSettingsAck: true,
|
singleUse: singleUse,
|
||||||
pings: make(map[[8]byte]chan struct{}),
|
wantSettingsAck: true,
|
||||||
|
pings: make(map[[8]byte]chan struct{}),
|
||||||
}
|
}
|
||||||
if d := t.idleConnTimeout(); d != 0 {
|
if d := t.idleConnTimeout(); d != 0 {
|
||||||
cc.idleTimeout = d
|
cc.idleTimeout = d
|
||||||
|
@ -560,6 +599,8 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanTakeNewRequest reports whether the connection can take a new request,
|
||||||
|
// meaning it has not been closed or received or sent a GOAWAY.
|
||||||
func (cc *ClientConn) CanTakeNewRequest() bool {
|
func (cc *ClientConn) CanTakeNewRequest() bool {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
|
@ -571,8 +612,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return cc.goAway == nil && !cc.closed &&
|
return cc.goAway == nil && !cc.closed &&
|
||||||
int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
|
int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32
|
||||||
cc.nextStreamID < math.MaxInt32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
|
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
|
||||||
|
@ -694,7 +734,7 @@ func checkConnHeaders(req *http.Request) error {
|
||||||
// req.ContentLength, where 0 actually means zero (not unknown) and -1
|
// req.ContentLength, where 0 actually means zero (not unknown) and -1
|
||||||
// means unknown.
|
// means unknown.
|
||||||
func actualContentLength(req *http.Request) int64 {
|
func actualContentLength(req *http.Request) int64 {
|
||||||
if req.Body == nil {
|
if req.Body == nil || reqBodyIsNoBody(req.Body) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if req.ContentLength != 0 {
|
if req.ContentLength != 0 {
|
||||||
|
@ -704,8 +744,13 @@ func actualContentLength(req *http.Request) int64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
resp, _, err := cc.roundTrip(req)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
|
||||||
if err := checkConnHeaders(req); err != nil {
|
if err := checkConnHeaders(req); err != nil {
|
||||||
return nil, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
if cc.idleTimer != nil {
|
if cc.idleTimer != nil {
|
||||||
cc.idleTimer.Stop()
|
cc.idleTimer.Stop()
|
||||||
|
@ -713,20 +758,19 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
trailers, err := commaSeparatedTrailers(req)
|
trailers, err := commaSeparatedTrailers(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
hasTrailers := trailers != ""
|
hasTrailers := trailers != ""
|
||||||
|
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
cc.lastActive = time.Now()
|
if err := cc.awaitOpenSlotForRequest(req); err != nil {
|
||||||
if cc.closed || !cc.canTakeNewRequestLocked() {
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return nil, errClientConnUnusable
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
body := req.Body
|
body := req.Body
|
||||||
hasBody := body != nil
|
|
||||||
contentLen := actualContentLength(req)
|
contentLen := actualContentLength(req)
|
||||||
|
hasBody := contentLen != 0
|
||||||
|
|
||||||
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
||||||
var requestedGzip bool
|
var requestedGzip bool
|
||||||
|
@ -755,7 +799,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
|
hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return nil, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := cc.newStream()
|
cs := cc.newStream()
|
||||||
|
@ -767,7 +811,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
endStream := !hasBody && !hasTrailers
|
endStream := !hasBody && !hasTrailers
|
||||||
werr := cc.writeHeaders(cs.ID, endStream, hdrs)
|
werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
|
||||||
cc.wmu.Unlock()
|
cc.wmu.Unlock()
|
||||||
traceWroteHeaders(cs.trace)
|
traceWroteHeaders(cs.trace)
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
@ -781,7 +825,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
// Don't bother sending a RST_STREAM (our write already failed;
|
// Don't bother sending a RST_STREAM (our write already failed;
|
||||||
// no need to keep writing)
|
// no need to keep writing)
|
||||||
traceWroteRequest(cs.trace, werr)
|
traceWroteRequest(cs.trace, werr)
|
||||||
return nil, werr
|
return nil, false, werr
|
||||||
}
|
}
|
||||||
|
|
||||||
var respHeaderTimer <-chan time.Time
|
var respHeaderTimer <-chan time.Time
|
||||||
|
@ -800,7 +844,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
bodyWritten := false
|
bodyWritten := false
|
||||||
ctx := reqContext(req)
|
ctx := reqContext(req)
|
||||||
|
|
||||||
handleReadLoopResponse := func(re resAndError) (*http.Response, error) {
|
handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
|
||||||
res := re.res
|
res := re.res
|
||||||
if re.err != nil || res.StatusCode > 299 {
|
if re.err != nil || res.StatusCode > 299 {
|
||||||
// On error or status code 3xx, 4xx, 5xx, etc abort any
|
// On error or status code 3xx, 4xx, 5xx, etc abort any
|
||||||
|
@ -816,19 +860,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
cs.abortRequestBodyWrite(errStopReqBodyWrite)
|
cs.abortRequestBodyWrite(errStopReqBodyWrite)
|
||||||
}
|
}
|
||||||
if re.err != nil {
|
if re.err != nil {
|
||||||
if re.err == errClientConnGotGoAway {
|
|
||||||
cc.mu.Lock()
|
|
||||||
if cs.startedWrite {
|
|
||||||
re.err = errClientConnGotGoAwayAfterSomeReqBody
|
|
||||||
}
|
|
||||||
cc.mu.Unlock()
|
|
||||||
}
|
|
||||||
cc.forgetStreamID(cs.ID)
|
cc.forgetStreamID(cs.ID)
|
||||||
return nil, re.err
|
return nil, cs.getStartedWrite(), re.err
|
||||||
}
|
}
|
||||||
res.Request = req
|
res.Request = req
|
||||||
res.TLS = cc.tlsState
|
res.TLS = cc.tlsState
|
||||||
return res, nil
|
return res, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -836,37 +873,37 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
case re := <-readLoopResCh:
|
case re := <-readLoopResCh:
|
||||||
return handleReadLoopResponse(re)
|
return handleReadLoopResponse(re)
|
||||||
case <-respHeaderTimer:
|
case <-respHeaderTimer:
|
||||||
cc.forgetStreamID(cs.ID)
|
|
||||||
if !hasBody || bodyWritten {
|
if !hasBody || bodyWritten {
|
||||||
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||||
} else {
|
} else {
|
||||||
bodyWriter.cancel()
|
bodyWriter.cancel()
|
||||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||||
}
|
}
|
||||||
return nil, errTimeout
|
cc.forgetStreamID(cs.ID)
|
||||||
|
return nil, cs.getStartedWrite(), errTimeout
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
cc.forgetStreamID(cs.ID)
|
|
||||||
if !hasBody || bodyWritten {
|
if !hasBody || bodyWritten {
|
||||||
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||||
} else {
|
} else {
|
||||||
bodyWriter.cancel()
|
bodyWriter.cancel()
|
||||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||||
}
|
}
|
||||||
return nil, ctx.Err()
|
cc.forgetStreamID(cs.ID)
|
||||||
|
return nil, cs.getStartedWrite(), ctx.Err()
|
||||||
case <-req.Cancel:
|
case <-req.Cancel:
|
||||||
cc.forgetStreamID(cs.ID)
|
|
||||||
if !hasBody || bodyWritten {
|
if !hasBody || bodyWritten {
|
||||||
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||||
} else {
|
} else {
|
||||||
bodyWriter.cancel()
|
bodyWriter.cancel()
|
||||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||||
}
|
}
|
||||||
return nil, errRequestCanceled
|
cc.forgetStreamID(cs.ID)
|
||||||
|
return nil, cs.getStartedWrite(), errRequestCanceled
|
||||||
case <-cs.peerReset:
|
case <-cs.peerReset:
|
||||||
// processResetStream already removed the
|
// processResetStream already removed the
|
||||||
// stream from the streams map; no need for
|
// stream from the streams map; no need for
|
||||||
// forgetStreamID.
|
// forgetStreamID.
|
||||||
return nil, cs.resetErr
|
return nil, cs.getStartedWrite(), cs.resetErr
|
||||||
case err := <-bodyWriter.resc:
|
case err := <-bodyWriter.resc:
|
||||||
// Prefer the read loop's response, if available. Issue 16102.
|
// Prefer the read loop's response, if available. Issue 16102.
|
||||||
select {
|
select {
|
||||||
|
@ -875,7 +912,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, cs.getStartedWrite(), err
|
||||||
}
|
}
|
||||||
bodyWritten = true
|
bodyWritten = true
|
||||||
if d := cc.responseHeaderTimeout(); d != 0 {
|
if d := cc.responseHeaderTimeout(); d != 0 {
|
||||||
|
@ -887,14 +924,52 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams.
|
||||||
|
// Must hold cc.mu.
|
||||||
|
func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
|
||||||
|
var waitingForConn chan struct{}
|
||||||
|
var waitingForConnErr error // guarded by cc.mu
|
||||||
|
for {
|
||||||
|
cc.lastActive = time.Now()
|
||||||
|
if cc.closed || !cc.canTakeNewRequestLocked() {
|
||||||
|
return errClientConnUnusable
|
||||||
|
}
|
||||||
|
if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
|
||||||
|
if waitingForConn != nil {
|
||||||
|
close(waitingForConn)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Unfortunately, we cannot wait on a condition variable and channel at
|
||||||
|
// the same time, so instead, we spin up a goroutine to check if the
|
||||||
|
// request is canceled while we wait for a slot to open in the connection.
|
||||||
|
if waitingForConn == nil {
|
||||||
|
waitingForConn = make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
if err := awaitRequestCancel(req, waitingForConn); err != nil {
|
||||||
|
cc.mu.Lock()
|
||||||
|
waitingForConnErr = err
|
||||||
|
cc.cond.Broadcast()
|
||||||
|
cc.mu.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
cc.pendingRequests++
|
||||||
|
cc.cond.Wait()
|
||||||
|
cc.pendingRequests--
|
||||||
|
if waitingForConnErr != nil {
|
||||||
|
return waitingForConnErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// requires cc.wmu be held
|
// requires cc.wmu be held
|
||||||
func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
|
func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
|
||||||
first := true // first frame written (HEADERS is first, then CONTINUATION)
|
first := true // first frame written (HEADERS is first, then CONTINUATION)
|
||||||
frameSize := int(cc.maxFrameSize)
|
|
||||||
for len(hdrs) > 0 && cc.werr == nil {
|
for len(hdrs) > 0 && cc.werr == nil {
|
||||||
chunk := hdrs
|
chunk := hdrs
|
||||||
if len(chunk) > frameSize {
|
if len(chunk) > maxFrameSize {
|
||||||
chunk = chunk[:frameSize]
|
chunk = chunk[:maxFrameSize]
|
||||||
}
|
}
|
||||||
hdrs = hdrs[len(chunk):]
|
hdrs = hdrs[len(chunk):]
|
||||||
endHeaders := len(hdrs) == 0
|
endHeaders := len(hdrs) == 0
|
||||||
|
@ -1002,17 +1077,26 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
|
||||||
var trls []byte
|
var trls []byte
|
||||||
if hasTrailers {
|
if hasTrailers {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
trls, err = cc.encodeTrailers(req)
|
||||||
trls = cc.encodeTrailers(req)
|
cc.mu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
|
||||||
|
cc.forgetStreamID(cs.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc.mu.Lock()
|
||||||
|
maxFrameSize := int(cc.maxFrameSize)
|
||||||
|
cc.mu.Unlock()
|
||||||
|
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
defer cc.wmu.Unlock()
|
defer cc.wmu.Unlock()
|
||||||
|
|
||||||
// Two ways to send END_STREAM: either with trailers, or
|
// Two ways to send END_STREAM: either with trailers, or
|
||||||
// with an empty DATA frame.
|
// with an empty DATA frame.
|
||||||
if len(trls) > 0 {
|
if len(trls) > 0 {
|
||||||
err = cc.writeHeaders(cs.ID, true, trls)
|
err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
|
||||||
} else {
|
} else {
|
||||||
err = cc.fr.WriteData(cs.ID, true, nil)
|
err = cc.fr.WriteData(cs.ID, true, nil)
|
||||||
}
|
}
|
||||||
|
@ -1106,62 +1190,86 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.1.2.3 Request Pseudo-Header Fields
|
enumerateHeaders := func(f func(name, value string)) {
|
||||||
// The :path pseudo-header field includes the path and query parts of the
|
// 8.1.2.3 Request Pseudo-Header Fields
|
||||||
// target URI (the path-absolute production and optionally a '?' character
|
// The :path pseudo-header field includes the path and query parts of the
|
||||||
// followed by the query production (see Sections 3.3 and 3.4 of
|
// target URI (the path-absolute production and optionally a '?' character
|
||||||
// [RFC3986]).
|
// followed by the query production (see Sections 3.3 and 3.4 of
|
||||||
cc.writeHeader(":authority", host)
|
// [RFC3986]).
|
||||||
cc.writeHeader(":method", req.Method)
|
f(":authority", host)
|
||||||
if req.Method != "CONNECT" {
|
f(":method", req.Method)
|
||||||
cc.writeHeader(":path", path)
|
if req.Method != "CONNECT" {
|
||||||
cc.writeHeader(":scheme", req.URL.Scheme)
|
f(":path", path)
|
||||||
}
|
f(":scheme", req.URL.Scheme)
|
||||||
if trailers != "" {
|
}
|
||||||
cc.writeHeader("trailer", trailers)
|
if trailers != "" {
|
||||||
|
f("trailer", trailers)
|
||||||
|
}
|
||||||
|
|
||||||
|
var didUA bool
|
||||||
|
for k, vv := range req.Header {
|
||||||
|
if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
|
||||||
|
// Host is :authority, already sent.
|
||||||
|
// Content-Length is automatic, set below.
|
||||||
|
continue
|
||||||
|
} else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
|
||||||
|
strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
|
||||||
|
strings.EqualFold(k, "keep-alive") {
|
||||||
|
// Per 8.1.2.2 Connection-Specific Header
|
||||||
|
// Fields, don't send connection-specific
|
||||||
|
// fields. We have already checked if any
|
||||||
|
// are error-worthy so just ignore the rest.
|
||||||
|
continue
|
||||||
|
} else if strings.EqualFold(k, "user-agent") {
|
||||||
|
// Match Go's http1 behavior: at most one
|
||||||
|
// User-Agent. If set to nil or empty string,
|
||||||
|
// then omit it. Otherwise if not mentioned,
|
||||||
|
// include the default (below).
|
||||||
|
didUA = true
|
||||||
|
if len(vv) < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vv = vv[:1]
|
||||||
|
if vv[0] == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range vv {
|
||||||
|
f(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if shouldSendReqContentLength(req.Method, contentLength) {
|
||||||
|
f("content-length", strconv.FormatInt(contentLength, 10))
|
||||||
|
}
|
||||||
|
if addGzipHeader {
|
||||||
|
f("accept-encoding", "gzip")
|
||||||
|
}
|
||||||
|
if !didUA {
|
||||||
|
f("user-agent", defaultUserAgent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var didUA bool
|
// Do a first pass over the headers counting bytes to ensure
|
||||||
for k, vv := range req.Header {
|
// we don't exceed cc.peerMaxHeaderListSize. This is done as a
|
||||||
lowKey := strings.ToLower(k)
|
// separate pass before encoding the headers to prevent
|
||||||
switch lowKey {
|
// modifying the hpack state.
|
||||||
case "host", "content-length":
|
hlSize := uint64(0)
|
||||||
// Host is :authority, already sent.
|
enumerateHeaders(func(name, value string) {
|
||||||
// Content-Length is automatic, set below.
|
hf := hpack.HeaderField{Name: name, Value: value}
|
||||||
continue
|
hlSize += uint64(hf.Size())
|
||||||
case "connection", "proxy-connection", "transfer-encoding", "upgrade", "keep-alive":
|
})
|
||||||
// Per 8.1.2.2 Connection-Specific Header
|
|
||||||
// Fields, don't send connection-specific
|
if hlSize > cc.peerMaxHeaderListSize {
|
||||||
// fields. We have already checked if any
|
return nil, errRequestHeaderListSize
|
||||||
// are error-worthy so just ignore the rest.
|
|
||||||
continue
|
|
||||||
case "user-agent":
|
|
||||||
// Match Go's http1 behavior: at most one
|
|
||||||
// User-Agent. If set to nil or empty string,
|
|
||||||
// then omit it. Otherwise if not mentioned,
|
|
||||||
// include the default (below).
|
|
||||||
didUA = true
|
|
||||||
if len(vv) < 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vv = vv[:1]
|
|
||||||
if vv[0] == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, v := range vv {
|
|
||||||
cc.writeHeader(lowKey, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if shouldSendReqContentLength(req.Method, contentLength) {
|
|
||||||
cc.writeHeader("content-length", strconv.FormatInt(contentLength, 10))
|
|
||||||
}
|
|
||||||
if addGzipHeader {
|
|
||||||
cc.writeHeader("accept-encoding", "gzip")
|
|
||||||
}
|
|
||||||
if !didUA {
|
|
||||||
cc.writeHeader("user-agent", defaultUserAgent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Header list size is ok. Write the headers.
|
||||||
|
enumerateHeaders(func(name, value string) {
|
||||||
|
cc.writeHeader(strings.ToLower(name), value)
|
||||||
|
})
|
||||||
|
|
||||||
return cc.hbuf.Bytes(), nil
|
return cc.hbuf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1188,17 +1296,29 @@ func shouldSendReqContentLength(method string, contentLength int64) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires cc.mu be held.
|
// requires cc.mu be held.
|
||||||
func (cc *ClientConn) encodeTrailers(req *http.Request) []byte {
|
func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
|
||||||
cc.hbuf.Reset()
|
cc.hbuf.Reset()
|
||||||
|
|
||||||
|
hlSize := uint64(0)
|
||||||
for k, vv := range req.Trailer {
|
for k, vv := range req.Trailer {
|
||||||
// Transfer-Encoding, etc.. have already been filter at the
|
for _, v := range vv {
|
||||||
|
hf := hpack.HeaderField{Name: k, Value: v}
|
||||||
|
hlSize += uint64(hf.Size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hlSize > cc.peerMaxHeaderListSize {
|
||||||
|
return nil, errRequestHeaderListSize
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, vv := range req.Trailer {
|
||||||
|
// Transfer-Encoding, etc.. have already been filtered at the
|
||||||
// start of RoundTrip
|
// start of RoundTrip
|
||||||
lowKey := strings.ToLower(k)
|
lowKey := strings.ToLower(k)
|
||||||
for _, v := range vv {
|
for _, v := range vv {
|
||||||
cc.writeHeader(lowKey, v)
|
cc.writeHeader(lowKey, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cc.hbuf.Bytes()
|
return cc.hbuf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) writeHeader(name, value string) {
|
func (cc *ClientConn) writeHeader(name, value string) {
|
||||||
|
@ -1246,7 +1366,9 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
|
||||||
cc.idleTimer.Reset(cc.idleTimeout)
|
cc.idleTimer.Reset(cc.idleTimeout)
|
||||||
}
|
}
|
||||||
close(cs.done)
|
close(cs.done)
|
||||||
cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
|
// Wake up checkResetOrDone via clientStream.awaitFlowControl and
|
||||||
|
// wake up RoundTrip if there is a pending request.
|
||||||
|
cc.cond.Broadcast()
|
||||||
}
|
}
|
||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
@ -1254,17 +1376,12 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
|
||||||
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
|
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
|
||||||
type clientConnReadLoop struct {
|
type clientConnReadLoop struct {
|
||||||
cc *ClientConn
|
cc *ClientConn
|
||||||
activeRes map[uint32]*clientStream // keyed by streamID
|
|
||||||
closeWhenIdle bool
|
closeWhenIdle bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// readLoop runs in its own goroutine and reads and dispatches frames.
|
// readLoop runs in its own goroutine and reads and dispatches frames.
|
||||||
func (cc *ClientConn) readLoop() {
|
func (cc *ClientConn) readLoop() {
|
||||||
rl := &clientConnReadLoop{
|
rl := &clientConnReadLoop{cc: cc}
|
||||||
cc: cc,
|
|
||||||
activeRes: make(map[uint32]*clientStream),
|
|
||||||
}
|
|
||||||
|
|
||||||
defer rl.cleanup()
|
defer rl.cleanup()
|
||||||
cc.readerErr = rl.run()
|
cc.readerErr = rl.run()
|
||||||
if ce, ok := cc.readerErr.(ConnectionError); ok {
|
if ce, ok := cc.readerErr.(ConnectionError); ok {
|
||||||
|
@ -1319,10 +1436,8 @@ func (rl *clientConnReadLoop) cleanup() {
|
||||||
} else if err == io.EOF {
|
} else if err == io.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
for _, cs := range rl.activeRes {
|
|
||||||
cs.bufPipe.CloseWithError(err)
|
|
||||||
}
|
|
||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
|
cs.bufPipe.CloseWithError(err) // no-op if already closed
|
||||||
select {
|
select {
|
||||||
case cs.resc <- resAndError{err: err}:
|
case cs.resc <- resAndError{err: err}:
|
||||||
default:
|
default:
|
||||||
|
@ -1345,8 +1460,9 @@ func (rl *clientConnReadLoop) run() error {
|
||||||
cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
|
cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
|
||||||
}
|
}
|
||||||
if se, ok := err.(StreamError); ok {
|
if se, ok := err.(StreamError); ok {
|
||||||
if cs := cc.streamByID(se.StreamID, true /*ended; remove it*/); cs != nil {
|
if cs := cc.streamByID(se.StreamID, false); cs != nil {
|
||||||
cs.cc.writeStreamReset(cs.ID, se.Code, err)
|
cs.cc.writeStreamReset(cs.ID, se.Code, err)
|
||||||
|
cs.cc.forgetStreamID(cs.ID)
|
||||||
if se.Cause == nil {
|
if se.Cause == nil {
|
||||||
se.Cause = cc.fr.errDetail
|
se.Cause = cc.fr.errDetail
|
||||||
}
|
}
|
||||||
|
@ -1399,7 +1515,7 @@ func (rl *clientConnReadLoop) run() error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
|
if rl.closeWhenIdle && gotReply && maybeIdle {
|
||||||
cc.closeIfIdle()
|
cc.closeIfIdle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1407,13 +1523,31 @@ func (rl *clientConnReadLoop) run() error {
|
||||||
|
|
||||||
func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
||||||
cc := rl.cc
|
cc := rl.cc
|
||||||
cs := cc.streamByID(f.StreamID, f.StreamEnded())
|
cs := cc.streamByID(f.StreamID, false)
|
||||||
if cs == nil {
|
if cs == nil {
|
||||||
// We'd get here if we canceled a request while the
|
// We'd get here if we canceled a request while the
|
||||||
// server had its response still in flight. So if this
|
// server had its response still in flight. So if this
|
||||||
// was just something we canceled, ignore it.
|
// was just something we canceled, ignore it.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if f.StreamEnded() {
|
||||||
|
// Issue 20521: If the stream has ended, streamByID() causes
|
||||||
|
// clientStream.done to be closed, which causes the request's bodyWriter
|
||||||
|
// to be closed with an errStreamClosed, which may be received by
|
||||||
|
// clientConn.RoundTrip before the result of processing these headers.
|
||||||
|
// Deferring stream closure allows the header processing to occur first.
|
||||||
|
// clientConn.RoundTrip may still receive the bodyWriter error first, but
|
||||||
|
// the fix for issue 16102 prioritises any response.
|
||||||
|
//
|
||||||
|
// Issue 22413: If there is no request body, we should close the
|
||||||
|
// stream before writing to cs.resc so that the stream is closed
|
||||||
|
// immediately once RoundTrip returns.
|
||||||
|
if cs.req.Body != nil {
|
||||||
|
defer cc.forgetStreamID(f.StreamID)
|
||||||
|
} else {
|
||||||
|
cc.forgetStreamID(f.StreamID)
|
||||||
|
}
|
||||||
|
}
|
||||||
if !cs.firstByte {
|
if !cs.firstByte {
|
||||||
if cs.trace != nil {
|
if cs.trace != nil {
|
||||||
// TODO(bradfitz): move first response byte earlier,
|
// TODO(bradfitz): move first response byte earlier,
|
||||||
|
@ -1437,6 +1571,7 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
||||||
}
|
}
|
||||||
// Any other error type is a stream error.
|
// Any other error type is a stream error.
|
||||||
cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
|
cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
|
||||||
|
cc.forgetStreamID(cs.ID)
|
||||||
cs.resc <- resAndError{err: err}
|
cs.resc <- resAndError{err: err}
|
||||||
return nil // return nil from process* funcs to keep conn alive
|
return nil // return nil from process* funcs to keep conn alive
|
||||||
}
|
}
|
||||||
|
@ -1444,9 +1579,6 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
||||||
// (nil, nil) special case. See handleResponse docs.
|
// (nil, nil) special case. See handleResponse docs.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if res.Body != noBody {
|
|
||||||
rl.activeRes[cs.ID] = cs
|
|
||||||
}
|
|
||||||
cs.resTrailer = &res.Trailer
|
cs.resTrailer = &res.Trailer
|
||||||
cs.resc <- resAndError{res: res}
|
cs.resc <- resAndError{res: res}
|
||||||
return nil
|
return nil
|
||||||
|
@ -1466,11 +1598,11 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
||||||
|
|
||||||
status := f.PseudoValue("status")
|
status := f.PseudoValue("status")
|
||||||
if status == "" {
|
if status == "" {
|
||||||
return nil, errors.New("missing status pseudo header")
|
return nil, errors.New("malformed response from server: missing status pseudo header")
|
||||||
}
|
}
|
||||||
statusCode, err := strconv.Atoi(status)
|
statusCode, err := strconv.Atoi(status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("malformed non-numeric status pseudo header")
|
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusCode == 100 {
|
if statusCode == 100 {
|
||||||
|
@ -1655,6 +1787,7 @@ func (b transportResponseBody) Close() error {
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
if !serverSentStreamEnd {
|
if !serverSentStreamEnd {
|
||||||
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
||||||
|
cs.didReset = true
|
||||||
}
|
}
|
||||||
// Return connection-level flow control.
|
// Return connection-level flow control.
|
||||||
if unread > 0 {
|
if unread > 0 {
|
||||||
|
@ -1667,6 +1800,7 @@ func (b transportResponseBody) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.bufPipe.BreakWithError(errClosedResponseBody)
|
cs.bufPipe.BreakWithError(errClosedResponseBody)
|
||||||
|
cc.forgetStreamID(cs.ID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,13 +1835,23 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if !cs.firstByte {
|
||||||
|
cc.logf("protocol error: received DATA before a HEADERS frame")
|
||||||
|
rl.endStreamError(cs, StreamError{
|
||||||
|
StreamID: f.StreamID,
|
||||||
|
Code: ErrCodeProtocol,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
if len(data) > 0 && cs.bufPipe.b == nil {
|
if cs.req.Method == "HEAD" && len(data) > 0 {
|
||||||
// Data frame after it's already closed?
|
cc.logf("protocol error: received DATA on a HEAD request")
|
||||||
cc.logf("http2: Transport received DATA frame for closed stream; closing connection")
|
rl.endStreamError(cs, StreamError{
|
||||||
return ConnectionError(ErrCodeProtocol)
|
StreamID: f.StreamID,
|
||||||
|
Code: ErrCodeProtocol,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check connection-level flow control.
|
// Check connection-level flow control.
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
if cs.inflow.available() >= int32(f.Length) {
|
if cs.inflow.available() >= int32(f.Length) {
|
||||||
|
@ -1718,16 +1862,27 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
||||||
}
|
}
|
||||||
// Return any padded flow control now, since we won't
|
// Return any padded flow control now, since we won't
|
||||||
// refund it later on body reads.
|
// refund it later on body reads.
|
||||||
if pad := int32(f.Length) - int32(len(data)); pad > 0 {
|
var refund int
|
||||||
cs.inflow.add(pad)
|
if pad := int(f.Length) - len(data); pad > 0 {
|
||||||
cc.inflow.add(pad)
|
refund += pad
|
||||||
|
}
|
||||||
|
// Return len(data) now if the stream is already closed,
|
||||||
|
// since data will never be read.
|
||||||
|
didReset := cs.didReset
|
||||||
|
if didReset {
|
||||||
|
refund += len(data)
|
||||||
|
}
|
||||||
|
if refund > 0 {
|
||||||
|
cc.inflow.add(int32(refund))
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
cc.fr.WriteWindowUpdate(0, uint32(pad))
|
cc.fr.WriteWindowUpdate(0, uint32(refund))
|
||||||
cc.fr.WriteWindowUpdate(cs.ID, uint32(pad))
|
if !didReset {
|
||||||
|
cs.inflow.add(int32(refund))
|
||||||
|
cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
|
||||||
|
}
|
||||||
cc.bw.Flush()
|
cc.bw.Flush()
|
||||||
cc.wmu.Unlock()
|
cc.wmu.Unlock()
|
||||||
}
|
}
|
||||||
didReset := cs.didReset
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
if len(data) > 0 && !didReset {
|
if len(data) > 0 && !didReset {
|
||||||
|
@ -1758,11 +1913,10 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
code = cs.copyTrailers
|
code = cs.copyTrailers
|
||||||
}
|
}
|
||||||
cs.bufPipe.closeWithErrorAndCode(err, code)
|
|
||||||
delete(rl.activeRes, cs.ID)
|
|
||||||
if isConnectionCloseRequest(cs.req) {
|
if isConnectionCloseRequest(cs.req) {
|
||||||
rl.closeWhenIdle = true
|
rl.closeWhenIdle = true
|
||||||
}
|
}
|
||||||
|
cs.bufPipe.closeWithErrorAndCode(err, code)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case cs.resc <- resAndError{err: err}:
|
case cs.resc <- resAndError{err: err}:
|
||||||
|
@ -1810,6 +1964,8 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
|
||||||
cc.maxFrameSize = s.Val
|
cc.maxFrameSize = s.Val
|
||||||
case SettingMaxConcurrentStreams:
|
case SettingMaxConcurrentStreams:
|
||||||
cc.maxConcurrentStreams = s.Val
|
cc.maxConcurrentStreams = s.Val
|
||||||
|
case SettingMaxHeaderListSize:
|
||||||
|
cc.peerMaxHeaderListSize = uint64(s.Val)
|
||||||
case SettingInitialWindowSize:
|
case SettingInitialWindowSize:
|
||||||
// Values above the maximum flow-control
|
// Values above the maximum flow-control
|
||||||
// window size of 2^31-1 MUST be treated as a
|
// window size of 2^31-1 MUST be treated as a
|
||||||
|
@ -1887,7 +2043,6 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
|
||||||
cs.bufPipe.CloseWithError(err)
|
cs.bufPipe.CloseWithError(err)
|
||||||
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
|
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
|
||||||
}
|
}
|
||||||
delete(rl.activeRes, cs.ID)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1976,6 +2131,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
|
errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
|
||||||
|
errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit")
|
||||||
errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers")
|
errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
7
vendor/golang.org/x/net/http2/write.go
generated
vendored
7
vendor/golang.org/x/net/http2/write.go
generated
vendored
|
@ -10,7 +10,6 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
"golang.org/x/net/lex/httplex"
|
"golang.org/x/net/lex/httplex"
|
||||||
|
@ -90,11 +89,7 @@ type writeGoAway struct {
|
||||||
|
|
||||||
func (p *writeGoAway) writeFrame(ctx writeContext) error {
|
func (p *writeGoAway) writeFrame(ctx writeContext) error {
|
||||||
err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
|
err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
|
||||||
if p.code != 0 {
|
ctx.Flush() // ignore error: we're hanging up on them anyway
|
||||||
ctx.Flush() // ignore error: we're hanging up on them anyway
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
ctx.CloseConn()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
|
@ -53,7 +53,7 @@ type PriorityWriteSchedulerConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
||||||
// frames by following HTTP/2 priorities as described in RFC 7340 Section 5.3.
|
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
|
||||||
// If cfg is nil, default options are used.
|
// If cfg is nil, default options are used.
|
||||||
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
|
|
126
vendor/golang.org/x/net/idna/idna.go
generated
vendored
126
vendor/golang.org/x/net/idna/idna.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/text/secure/bidirule"
|
"golang.org/x/text/secure/bidirule"
|
||||||
|
"golang.org/x/text/unicode/bidi"
|
||||||
"golang.org/x/text/unicode/norm"
|
"golang.org/x/text/unicode/norm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,6 +68,15 @@ func VerifyDNSLength(verify bool) Option {
|
||||||
return func(o *options) { o.verifyDNSLength = verify }
|
return func(o *options) { o.verifyDNSLength = verify }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveLeadingDots removes leading label separators. Leading runes that map to
|
||||||
|
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
|
||||||
|
//
|
||||||
|
// This is the behavior suggested by the UTS #46 and is adopted by some
|
||||||
|
// browsers.
|
||||||
|
func RemoveLeadingDots(remove bool) Option {
|
||||||
|
return func(o *options) { o.removeLeadingDots = remove }
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateLabels sets whether to check the mandatory label validation criteria
|
// ValidateLabels sets whether to check the mandatory label validation criteria
|
||||||
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
||||||
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
||||||
|
@ -83,7 +93,7 @@ func ValidateLabels(enable bool) Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StrictDomainName limits the set of permissable ASCII characters to those
|
// StrictDomainName limits the set of permissible ASCII characters to those
|
||||||
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||||
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
||||||
//
|
//
|
||||||
|
@ -137,10 +147,11 @@ func MapForLookup() Option {
|
||||||
}
|
}
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
transitional bool
|
transitional bool
|
||||||
useSTD3Rules bool
|
useSTD3Rules bool
|
||||||
validateLabels bool
|
validateLabels bool
|
||||||
verifyDNSLength bool
|
verifyDNSLength bool
|
||||||
|
removeLeadingDots bool
|
||||||
|
|
||||||
trie *idnaTrie
|
trie *idnaTrie
|
||||||
|
|
||||||
|
@ -149,14 +160,14 @@ type options struct {
|
||||||
|
|
||||||
// mapping implements a validation and mapping step as defined in RFC 5895
|
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||||
// or UTS 46, tailored to, for example, domain registration or lookup.
|
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||||
mapping func(p *Profile, s string) (string, error)
|
mapping func(p *Profile, s string) (mapped string, isBidi bool, err error)
|
||||||
|
|
||||||
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||||
// defined in RFC 5893.
|
// defined in RFC 5893.
|
||||||
bidirule func(s string) bool
|
bidirule func(s string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Profile defines the configuration of a IDNA mapper.
|
// A Profile defines the configuration of an IDNA mapper.
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
options
|
options
|
||||||
}
|
}
|
||||||
|
@ -289,12 +300,16 @@ func (e runeError) Error() string {
|
||||||
// see http://www.unicode.org/reports/tr46.
|
// see http://www.unicode.org/reports/tr46.
|
||||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
|
var isBidi bool
|
||||||
if p.mapping != nil {
|
if p.mapping != nil {
|
||||||
s, err = p.mapping(p, s)
|
s, isBidi, err = p.mapping(p, s)
|
||||||
}
|
}
|
||||||
// Remove leading empty labels.
|
// Remove leading empty labels.
|
||||||
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
if p.removeLeadingDots {
|
||||||
|
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: allow for a quick check of the tables data.
|
||||||
// It seems like we should only create this error on ToASCII, but the
|
// It seems like we should only create this error on ToASCII, but the
|
||||||
// UTS 46 conformance tests suggests we should always check this.
|
// UTS 46 conformance tests suggests we should always check this.
|
||||||
if err == nil && p.verifyDNSLength && s == "" {
|
if err == nil && p.verifyDNSLength && s == "" {
|
||||||
|
@ -320,6 +335,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||||
// Spec says keep the old label.
|
// Spec says keep the old label.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
|
||||||
labels.set(u)
|
labels.set(u)
|
||||||
if err == nil && p.validateLabels {
|
if err == nil && p.validateLabels {
|
||||||
err = p.fromPuny(p, u)
|
err = p.fromPuny(p, u)
|
||||||
|
@ -334,6 +350,14 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||||
err = p.validateLabel(label)
|
err = p.validateLabel(label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if isBidi && p.bidirule != nil && err == nil {
|
||||||
|
for labels.reset(); !labels.done(); labels.next() {
|
||||||
|
if !p.bidirule(labels.label()) {
|
||||||
|
err = &labelError{s, "B"}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if toASCII {
|
if toASCII {
|
||||||
for labels.reset(); !labels.done(); labels.next() {
|
for labels.reset(); !labels.done(); labels.next() {
|
||||||
label := labels.label()
|
label := labels.label()
|
||||||
|
@ -365,41 +389,77 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalize(p *Profile, s string) (string, error) {
|
func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
|
||||||
return norm.NFC.String(s), nil
|
// TODO: consider first doing a quick check to see if any of these checks
|
||||||
|
// need to be done. This will make it slower in the general case, but
|
||||||
|
// faster in the common case.
|
||||||
|
mapped = norm.NFC.String(s)
|
||||||
|
isBidi = bidirule.DirectionString(mapped) == bidi.RightToLeft
|
||||||
|
return mapped, isBidi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateRegistration(p *Profile, s string) (string, error) {
|
func validateRegistration(p *Profile, s string) (idem string, bidi bool, err error) {
|
||||||
|
// TODO: filter need for normalization in loop below.
|
||||||
if !norm.NFC.IsNormalString(s) {
|
if !norm.NFC.IsNormalString(s) {
|
||||||
return s, &labelError{s, "V1"}
|
return s, false, &labelError{s, "V1"}
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
v, sz := trie.lookupString(s[i:])
|
v, sz := trie.lookupString(s[i:])
|
||||||
i += sz
|
if sz == 0 {
|
||||||
|
return s, bidi, runeError(utf8.RuneError)
|
||||||
|
}
|
||||||
|
bidi = bidi || info(v).isBidi(s[i:])
|
||||||
// Copy bytes not copied so far.
|
// Copy bytes not copied so far.
|
||||||
switch p.simplify(info(v).category()) {
|
switch p.simplify(info(v).category()) {
|
||||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||||
// for strict conformance to IDNA2008.
|
// for strict conformance to IDNA2008.
|
||||||
case valid, deviation:
|
case valid, deviation:
|
||||||
case disallowed, mapped, unknown, ignored:
|
case disallowed, mapped, unknown, ignored:
|
||||||
if err == nil {
|
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
return s, bidi, runeError(r)
|
||||||
err = runeError(r)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
i += sz
|
||||||
}
|
}
|
||||||
return s, err
|
return s, bidi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAndMap(p *Profile, s string) (string, error) {
|
func (c info) isBidi(s string) bool {
|
||||||
|
if !c.isMapped() {
|
||||||
|
return c&attributesMask == rtl
|
||||||
|
}
|
||||||
|
// TODO: also store bidi info for mapped data. This is possible, but a bit
|
||||||
|
// cumbersome and not for the common case.
|
||||||
|
p, _ := bidi.LookupString(s)
|
||||||
|
switch p.Class() {
|
||||||
|
case bidi.R, bidi.AL, bidi.AN:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
|
||||||
var (
|
var (
|
||||||
err error
|
b []byte
|
||||||
b []byte
|
k int
|
||||||
k int
|
|
||||||
)
|
)
|
||||||
|
// combinedInfoBits contains the or-ed bits of all runes. We use this
|
||||||
|
// to derive the mayNeedNorm bit later. This may trigger normalization
|
||||||
|
// overeagerly, but it will not do so in the common case. The end result
|
||||||
|
// is another 10% saving on BenchmarkProfile for the common case.
|
||||||
|
var combinedInfoBits info
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
v, sz := trie.lookupString(s[i:])
|
v, sz := trie.lookupString(s[i:])
|
||||||
|
if sz == 0 {
|
||||||
|
b = append(b, s[k:i]...)
|
||||||
|
b = append(b, "\ufffd"...)
|
||||||
|
k = len(s)
|
||||||
|
if err == nil {
|
||||||
|
err = runeError(utf8.RuneError)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
combinedInfoBits |= info(v)
|
||||||
|
bidi = bidi || info(v).isBidi(s[i:])
|
||||||
start := i
|
start := i
|
||||||
i += sz
|
i += sz
|
||||||
// Copy bytes not copied so far.
|
// Copy bytes not copied so far.
|
||||||
|
@ -408,7 +468,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
|
||||||
continue
|
continue
|
||||||
case disallowed:
|
case disallowed:
|
||||||
if err == nil {
|
if err == nil {
|
||||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
r, _ := utf8.DecodeRuneInString(s[start:])
|
||||||
err = runeError(r)
|
err = runeError(r)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -426,7 +486,9 @@ func validateAndMap(p *Profile, s string) (string, error) {
|
||||||
}
|
}
|
||||||
if k == 0 {
|
if k == 0 {
|
||||||
// No changes so far.
|
// No changes so far.
|
||||||
s = norm.NFC.String(s)
|
if combinedInfoBits&mayNeedNorm != 0 {
|
||||||
|
s = norm.NFC.String(s)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
b = append(b, s[k:]...)
|
b = append(b, s[k:]...)
|
||||||
if norm.NFC.QuickSpan(b) != len(b) {
|
if norm.NFC.QuickSpan(b) != len(b) {
|
||||||
|
@ -435,7 +497,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
|
||||||
// TODO: the punycode converters require strings as input.
|
// TODO: the punycode converters require strings as input.
|
||||||
s = string(b)
|
s = string(b)
|
||||||
}
|
}
|
||||||
return s, err
|
return s, bidi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A labelIter allows iterating over domain name labels.
|
// A labelIter allows iterating over domain name labels.
|
||||||
|
@ -530,8 +592,13 @@ func validateFromPunycode(p *Profile, s string) error {
|
||||||
if !norm.NFC.IsNormalString(s) {
|
if !norm.NFC.IsNormalString(s) {
|
||||||
return &labelError{s, "V1"}
|
return &labelError{s, "V1"}
|
||||||
}
|
}
|
||||||
|
// TODO: detect whether string may have to be normalized in the following
|
||||||
|
// loop.
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
v, sz := trie.lookupString(s[i:])
|
v, sz := trie.lookupString(s[i:])
|
||||||
|
if sz == 0 {
|
||||||
|
return runeError(utf8.RuneError)
|
||||||
|
}
|
||||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||||
return &labelError{s, "V6"}
|
return &labelError{s, "V6"}
|
||||||
}
|
}
|
||||||
|
@ -604,16 +671,13 @@ var joinStates = [][numJoinTypes]joinState{
|
||||||
|
|
||||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||||
// already implicitly satisfied by the overall implementation.
|
// already implicitly satisfied by the overall implementation.
|
||||||
func (p *Profile) validateLabel(s string) error {
|
func (p *Profile) validateLabel(s string) (err error) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
if p.verifyDNSLength {
|
if p.verifyDNSLength {
|
||||||
return &labelError{s, "A4"}
|
return &labelError{s, "A4"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if p.bidirule != nil && !p.bidirule(s) {
|
|
||||||
return &labelError{s, "B"}
|
|
||||||
}
|
|
||||||
if !p.validateLabels {
|
if !p.validateLabels {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
4396
vendor/golang.org/x/net/idna/tables.go
generated
vendored
4396
vendor/golang.org/x/net/idna/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
17
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
17
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
|
@ -26,9 +26,9 @@ package idna
|
||||||
// 15..3 index into xor or mapping table
|
// 15..3 index into xor or mapping table
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
// 15..13 unused
|
// 15..14 unused
|
||||||
// 12 modifier (including virama)
|
// 13 mayNeedNorm
|
||||||
// 11 virama modifier
|
// 12..11 attributes
|
||||||
// 10..8 joining type
|
// 10..8 joining type
|
||||||
// 7..3 category type
|
// 7..3 category type
|
||||||
// }
|
// }
|
||||||
|
@ -49,15 +49,20 @@ const (
|
||||||
joinShift = 8
|
joinShift = 8
|
||||||
joinMask = 0x07
|
joinMask = 0x07
|
||||||
|
|
||||||
viramaModifier = 0x0800
|
// Attributes
|
||||||
|
attributesMask = 0x1800
|
||||||
|
viramaModifier = 0x1800
|
||||||
modifier = 0x1000
|
modifier = 0x1000
|
||||||
|
rtl = 0x0800
|
||||||
|
|
||||||
|
mayNeedNorm = 0x2000
|
||||||
)
|
)
|
||||||
|
|
||||||
// A category corresponds to a category defined in the IDNA mapping table.
|
// A category corresponds to a category defined in the IDNA mapping table.
|
||||||
type category uint16
|
type category uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
unknown category = 0 // not defined currently in unicode.
|
unknown category = 0 // not currently defined in unicode.
|
||||||
mapped category = 1
|
mapped category = 1
|
||||||
disallowedSTD3Mapped category = 2
|
disallowedSTD3Mapped category = 2
|
||||||
deviation category = 3
|
deviation category = 3
|
||||||
|
@ -110,5 +115,5 @@ func (c info) isModifier() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c info) isViramaModifier() bool {
|
func (c info) isViramaModifier() bool {
|
||||||
return c&(viramaModifier|catSmallMask) == viramaModifier
|
return c&(attributesMask|catSmallMask) == viramaModifier
|
||||||
}
|
}
|
||||||
|
|
180
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
Normal file
180
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
// go generate gen.go
|
||||||
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
||||||
|
package iana // import "golang.org/x/net/internal/iana"
|
||||||
|
|
||||||
|
// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12
|
||||||
|
const (
|
||||||
|
DiffServCS0 = 0x0 // CS0
|
||||||
|
DiffServCS1 = 0x20 // CS1
|
||||||
|
DiffServCS2 = 0x40 // CS2
|
||||||
|
DiffServCS3 = 0x60 // CS3
|
||||||
|
DiffServCS4 = 0x80 // CS4
|
||||||
|
DiffServCS5 = 0xa0 // CS5
|
||||||
|
DiffServCS6 = 0xc0 // CS6
|
||||||
|
DiffServCS7 = 0xe0 // CS7
|
||||||
|
DiffServAF11 = 0x28 // AF11
|
||||||
|
DiffServAF12 = 0x30 // AF12
|
||||||
|
DiffServAF13 = 0x38 // AF13
|
||||||
|
DiffServAF21 = 0x48 // AF21
|
||||||
|
DiffServAF22 = 0x50 // AF22
|
||||||
|
DiffServAF23 = 0x58 // AF23
|
||||||
|
DiffServAF31 = 0x68 // AF31
|
||||||
|
DiffServAF32 = 0x70 // AF32
|
||||||
|
DiffServAF33 = 0x78 // AF33
|
||||||
|
DiffServAF41 = 0x88 // AF41
|
||||||
|
DiffServAF42 = 0x90 // AF42
|
||||||
|
DiffServAF43 = 0x98 // AF43
|
||||||
|
DiffServEF = 0xb8 // EF
|
||||||
|
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
|
||||||
|
const (
|
||||||
|
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
|
||||||
|
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
|
||||||
|
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
|
||||||
|
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Protocol Numbers, Updated: 2016-06-22
|
||||||
|
const (
|
||||||
|
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
||||||
|
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||||
|
ProtocolICMP = 1 // Internet Control Message
|
||||||
|
ProtocolIGMP = 2 // Internet Group Management
|
||||||
|
ProtocolGGP = 3 // Gateway-to-Gateway
|
||||||
|
ProtocolIPv4 = 4 // IPv4 encapsulation
|
||||||
|
ProtocolST = 5 // Stream
|
||||||
|
ProtocolTCP = 6 // Transmission Control
|
||||||
|
ProtocolCBT = 7 // CBT
|
||||||
|
ProtocolEGP = 8 // Exterior Gateway Protocol
|
||||||
|
ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
|
||||||
|
ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
|
||||||
|
ProtocolNVPII = 11 // Network Voice Protocol
|
||||||
|
ProtocolPUP = 12 // PUP
|
||||||
|
ProtocolEMCON = 14 // EMCON
|
||||||
|
ProtocolXNET = 15 // Cross Net Debugger
|
||||||
|
ProtocolCHAOS = 16 // Chaos
|
||||||
|
ProtocolUDP = 17 // User Datagram
|
||||||
|
ProtocolMUX = 18 // Multiplexing
|
||||||
|
ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
|
||||||
|
ProtocolHMP = 20 // Host Monitoring
|
||||||
|
ProtocolPRM = 21 // Packet Radio Measurement
|
||||||
|
ProtocolXNSIDP = 22 // XEROX NS IDP
|
||||||
|
ProtocolTRUNK1 = 23 // Trunk-1
|
||||||
|
ProtocolTRUNK2 = 24 // Trunk-2
|
||||||
|
ProtocolLEAF1 = 25 // Leaf-1
|
||||||
|
ProtocolLEAF2 = 26 // Leaf-2
|
||||||
|
ProtocolRDP = 27 // Reliable Data Protocol
|
||||||
|
ProtocolIRTP = 28 // Internet Reliable Transaction
|
||||||
|
ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
|
||||||
|
ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
|
||||||
|
ProtocolMFENSP = 31 // MFE Network Services Protocol
|
||||||
|
ProtocolMERITINP = 32 // MERIT Internodal Protocol
|
||||||
|
ProtocolDCCP = 33 // Datagram Congestion Control Protocol
|
||||||
|
Protocol3PC = 34 // Third Party Connect Protocol
|
||||||
|
ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
|
||||||
|
ProtocolXTP = 36 // XTP
|
||||||
|
ProtocolDDP = 37 // Datagram Delivery Protocol
|
||||||
|
ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
|
||||||
|
ProtocolTPPP = 39 // TP++ Transport Protocol
|
||||||
|
ProtocolIL = 40 // IL Transport Protocol
|
||||||
|
ProtocolIPv6 = 41 // IPv6 encapsulation
|
||||||
|
ProtocolSDRP = 42 // Source Demand Routing Protocol
|
||||||
|
ProtocolIPv6Route = 43 // Routing Header for IPv6
|
||||||
|
ProtocolIPv6Frag = 44 // Fragment Header for IPv6
|
||||||
|
ProtocolIDRP = 45 // Inter-Domain Routing Protocol
|
||||||
|
ProtocolRSVP = 46 // Reservation Protocol
|
||||||
|
ProtocolGRE = 47 // Generic Routing Encapsulation
|
||||||
|
ProtocolDSR = 48 // Dynamic Source Routing Protocol
|
||||||
|
ProtocolBNA = 49 // BNA
|
||||||
|
ProtocolESP = 50 // Encap Security Payload
|
||||||
|
ProtocolAH = 51 // Authentication Header
|
||||||
|
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
|
||||||
|
ProtocolNARP = 54 // NBMA Address Resolution Protocol
|
||||||
|
ProtocolMOBILE = 55 // IP Mobility
|
||||||
|
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
|
||||||
|
ProtocolSKIP = 57 // SKIP
|
||||||
|
ProtocolIPv6ICMP = 58 // ICMP for IPv6
|
||||||
|
ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
|
||||||
|
ProtocolIPv6Opts = 60 // Destination Options for IPv6
|
||||||
|
ProtocolCFTP = 62 // CFTP
|
||||||
|
ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
|
||||||
|
ProtocolKRYPTOLAN = 65 // Kryptolan
|
||||||
|
ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
|
||||||
|
ProtocolIPPC = 67 // Internet Pluribus Packet Core
|
||||||
|
ProtocolSATMON = 69 // SATNET Monitoring
|
||||||
|
ProtocolVISA = 70 // VISA Protocol
|
||||||
|
ProtocolIPCV = 71 // Internet Packet Core Utility
|
||||||
|
ProtocolCPNX = 72 // Computer Protocol Network Executive
|
||||||
|
ProtocolCPHB = 73 // Computer Protocol Heart Beat
|
||||||
|
ProtocolWSN = 74 // Wang Span Network
|
||||||
|
ProtocolPVP = 75 // Packet Video Protocol
|
||||||
|
ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
|
||||||
|
ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
|
||||||
|
ProtocolWBMON = 78 // WIDEBAND Monitoring
|
||||||
|
ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
|
||||||
|
ProtocolISOIP = 80 // ISO Internet Protocol
|
||||||
|
ProtocolVMTP = 81 // VMTP
|
||||||
|
ProtocolSECUREVMTP = 82 // SECURE-VMTP
|
||||||
|
ProtocolVINES = 83 // VINES
|
||||||
|
ProtocolTTP = 84 // Transaction Transport Protocol
|
||||||
|
ProtocolIPTM = 84 // Internet Protocol Traffic Manager
|
||||||
|
ProtocolNSFNETIGP = 85 // NSFNET-IGP
|
||||||
|
ProtocolDGP = 86 // Dissimilar Gateway Protocol
|
||||||
|
ProtocolTCF = 87 // TCF
|
||||||
|
ProtocolEIGRP = 88 // EIGRP
|
||||||
|
ProtocolOSPFIGP = 89 // OSPFIGP
|
||||||
|
ProtocolSpriteRPC = 90 // Sprite RPC Protocol
|
||||||
|
ProtocolLARP = 91 // Locus Address Resolution Protocol
|
||||||
|
ProtocolMTP = 92 // Multicast Transport Protocol
|
||||||
|
ProtocolAX25 = 93 // AX.25 Frames
|
||||||
|
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
|
||||||
|
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
|
||||||
|
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
|
||||||
|
ProtocolENCAP = 98 // Encapsulation Header
|
||||||
|
ProtocolGMTP = 100 // GMTP
|
||||||
|
ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
|
||||||
|
ProtocolPNNI = 102 // PNNI over IP
|
||||||
|
ProtocolPIM = 103 // Protocol Independent Multicast
|
||||||
|
ProtocolARIS = 104 // ARIS
|
||||||
|
ProtocolSCPS = 105 // SCPS
|
||||||
|
ProtocolQNX = 106 // QNX
|
||||||
|
ProtocolAN = 107 // Active Networks
|
||||||
|
ProtocolIPComp = 108 // IP Payload Compression Protocol
|
||||||
|
ProtocolSNP = 109 // Sitara Networks Protocol
|
||||||
|
ProtocolCompaqPeer = 110 // Compaq Peer Protocol
|
||||||
|
ProtocolIPXinIP = 111 // IPX in IP
|
||||||
|
ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
|
||||||
|
ProtocolPGM = 113 // PGM Reliable Transport Protocol
|
||||||
|
ProtocolL2TP = 115 // Layer Two Tunneling Protocol
|
||||||
|
ProtocolDDX = 116 // D-II Data Exchange (DDX)
|
||||||
|
ProtocolIATP = 117 // Interactive Agent Transfer Protocol
|
||||||
|
ProtocolSTP = 118 // Schedule Transfer Protocol
|
||||||
|
ProtocolSRP = 119 // SpectraLink Radio Protocol
|
||||||
|
ProtocolUTI = 120 // UTI
|
||||||
|
ProtocolSMP = 121 // Simple Message Protocol
|
||||||
|
ProtocolPTP = 123 // Performance Transparency Protocol
|
||||||
|
ProtocolISIS = 124 // ISIS over IPv4
|
||||||
|
ProtocolFIRE = 125 // FIRE
|
||||||
|
ProtocolCRTP = 126 // Combat Radio Transport Protocol
|
||||||
|
ProtocolCRUDP = 127 // Combat Radio User Datagram
|
||||||
|
ProtocolSSCOPMCE = 128 // SSCOPMCE
|
||||||
|
ProtocolIPLT = 129 // IPLT
|
||||||
|
ProtocolSPS = 130 // Secure Packet Shield
|
||||||
|
ProtocolPIPE = 131 // Private IP Encapsulation within IP
|
||||||
|
ProtocolSCTP = 132 // Stream Control Transmission Protocol
|
||||||
|
ProtocolFC = 133 // Fibre Channel
|
||||||
|
ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
|
||||||
|
ProtocolMobilityHeader = 135 // Mobility Header
|
||||||
|
ProtocolUDPLite = 136 // UDPLite
|
||||||
|
ProtocolMPLSinIP = 137 // MPLS-in-IP
|
||||||
|
ProtocolMANET = 138 // MANET Protocols
|
||||||
|
ProtocolHIP = 139 // Host Identity Protocol
|
||||||
|
ProtocolShim6 = 140 // Shim6 Protocol
|
||||||
|
ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
|
||||||
|
ProtocolROHC = 142 // Robust Header Compression
|
||||||
|
ProtocolReserved = 255 // Reserved
|
||||||
|
)
|
293
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
Normal file
293
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
// This program generates internet protocol constants and tables by
|
||||||
|
// reading IANA protocol registries.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registries = []struct {
|
||||||
|
url string
|
||||||
|
parse func(io.Writer, io.Reader) error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
||||||
|
parseDSCPRegistry,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
|
||||||
|
parseTOSTCByte,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||||
|
parseProtocolNumbers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var bb bytes.Buffer
|
||||||
|
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||||
|
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
||||||
|
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
||||||
|
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
||||||
|
for _, r := range registries {
|
||||||
|
resp, err := http.Get(r.url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := r.parse(&bb, resp.Body); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&bb, "\n")
|
||||||
|
}
|
||||||
|
b, err := format.Source(bb.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var dr dscpRegistry
|
||||||
|
if err := dec.Decode(&dr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
drs := dr.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, dr := range drs {
|
||||||
|
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type dscpRegistry struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Note string `xml:"note"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
PoolRecords []struct {
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Space string `xml:"space"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
Records []struct {
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Space string `xml:"space"`
|
||||||
|
} `xml:"registry>registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonDSCPRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (drr *dscpRegistry) escape() []canonDSCPRecord {
|
||||||
|
drs := make([]canonDSCPRecord, len(drr.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, dr := range drr.Records {
|
||||||
|
s := strings.TrimSpace(dr.Name)
|
||||||
|
drs[i].OrigName = s
|
||||||
|
drs[i].Name = sr.Replace(s)
|
||||||
|
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
drs[i].Value = int(n) << 2
|
||||||
|
}
|
||||||
|
return drs
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTOSTCByte(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var ttb tosTCByte
|
||||||
|
if err := dec.Decode(&ttb); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
trs := ttb.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, tr := range trs {
|
||||||
|
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type tosTCByte struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Note string `xml:"note"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Records []struct {
|
||||||
|
Binary string `xml:"binary"`
|
||||||
|
Keyword string `xml:"keyword"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonTOSTCByteRecord struct {
|
||||||
|
OrigKeyword string
|
||||||
|
Keyword string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
|
||||||
|
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"Capable", "",
|
||||||
|
"(", "",
|
||||||
|
")", "",
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, tr := range ttb.Records {
|
||||||
|
s := strings.TrimSpace(tr.Keyword)
|
||||||
|
trs[i].OrigKeyword = s
|
||||||
|
ss := strings.Split(s, " ")
|
||||||
|
if len(ss) > 1 {
|
||||||
|
trs[i].Keyword = strings.Join(ss[1:], " ")
|
||||||
|
} else {
|
||||||
|
trs[i].Keyword = ss[0]
|
||||||
|
}
|
||||||
|
trs[i].Keyword = sr.Replace(trs[i].Keyword)
|
||||||
|
n, err := strconv.ParseUint(tr.Binary, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
trs[i].Value = int(n)
|
||||||
|
}
|
||||||
|
return trs
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var pn protocolNumbers
|
||||||
|
if err := dec.Decode(&pn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prs := pn.escape()
|
||||||
|
prs = append([]canonProtocolRecord{{
|
||||||
|
Name: "IP",
|
||||||
|
Descr: "IPv4 encapsulation, pseudo protocol number",
|
||||||
|
Value: 0,
|
||||||
|
}}, prs...)
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
||||||
|
s := pr.Descr
|
||||||
|
if s == "" {
|
||||||
|
s = pr.OrigName
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "// %s\n", s)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type protocolNumbers struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Note string `xml:"registry>note"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonProtocolRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Descr string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
||||||
|
prs := make([]canonProtocolRecord, len(pn.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"-in-", "in",
|
||||||
|
"-within-", "within",
|
||||||
|
"-over-", "over",
|
||||||
|
"+", "P",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, pr := range pn.Records {
|
||||||
|
if strings.Contains(pr.Name, "Deprecated") ||
|
||||||
|
strings.Contains(pr.Name, "deprecated") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
prs[i].OrigName = pr.Name
|
||||||
|
s := strings.TrimSpace(pr.Name)
|
||||||
|
switch pr.Name {
|
||||||
|
case "ISIS over IPv4":
|
||||||
|
prs[i].Name = "ISIS"
|
||||||
|
case "manet":
|
||||||
|
prs[i].Name = "MANET"
|
||||||
|
default:
|
||||||
|
prs[i].Name = sr.Replace(s)
|
||||||
|
}
|
||||||
|
ss := strings.Split(pr.Descr, "\n")
|
||||||
|
for i := range ss {
|
||||||
|
ss[i] = strings.TrimSpace(ss[i])
|
||||||
|
}
|
||||||
|
if len(ss) > 1 {
|
||||||
|
prs[i].Descr = strings.Join(ss, " ")
|
||||||
|
} else {
|
||||||
|
prs[i].Descr = ss[0]
|
||||||
|
}
|
||||||
|
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||||
|
}
|
||||||
|
return prs
|
||||||
|
}
|
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return int(h.Len) }
|
||||||
|
func (h *cmsghdr) lvl() int { return int(h.Level) }
|
||||||
|
func (h *cmsghdr) typ() int { return int(h.Type) }
|
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint64(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct{}
|
||||||
|
|
||||||
|
const sizeofCmsghdr = 0
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return 0 }
|
||||||
|
func (h *cmsghdr) lvl() int { return 0 }
|
||||||
|
func (h *cmsghdr) typ() int { return 0 }
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {}
|
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/in6.h>
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <sys/socket.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errEAGAIN error = syscall.EAGAIN
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
errENOENT error = syscall.ENOENT
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.EAGAIN:
|
||||||
|
return errEAGAIN
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
case syscall.ENOENT:
|
||||||
|
return errENOENT
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.ERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint32(l)
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(l)
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*int8)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(l)
|
||||||
|
}
|
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type iovec struct{}
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {}
|
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !linux,!netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdr struct{}
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
return nil
|
||||||
|
}
|
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build linux netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
for i := range hs {
|
||||||
|
vs := make([]iovec, len(ms[i].Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if parseFn != nil {
|
||||||
|
sa = make([]byte, sizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
if marshalFn != nil {
|
||||||
|
sa = marshalFn(ms[i].Addr)
|
||||||
|
}
|
||||||
|
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
for i := range hs {
|
||||||
|
ms[i].N = int(hs[i].Len)
|
||||||
|
ms[i].NN = hs[i].Hdr.controllen()
|
||||||
|
ms[i].Flags = hs[i].Hdr.flags()
|
||||||
|
if parseFn != nil {
|
||||||
|
var err error
|
||||||
|
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.setIov(vs)
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||||
|
h.Controllen = uint32(len(oob))
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) name() []byte {
|
||||||
|
if h.Name != nil && h.Namelen > 0 {
|
||||||
|
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Controllen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(h.Flags)
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue