Merge branch 'v1.5' into master

This commit is contained in:
Fernandez Ludovic 2018-03-02 15:21:33 +01:00
commit bf43149d7e
293 changed files with 23915 additions and 1441 deletions

View file

@ -54,7 +54,7 @@ deploy:
on: on:
repo: containous/traefik repo: containous/traefik
- provider: pages - provider: pages
edge: true edge: false
github_token: ${GITHUB_TOKEN} github_token: ${GITHUB_TOKEN}
local_dir: site local_dir: site
skip_cleanup: true skip_cleanup: true

16
Gopkg.lock generated
View file

@ -879,9 +879,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"
@ -1256,29 +1257,36 @@
packages = [ packages = [
"bcrypt", "bcrypt",
"blowfish", "blowfish",
"ed25519",
"ed25519/internal/edwards25519",
"ocsp", "ocsp",
"pbkdf2", "pbkdf2",
"scrypt", "scrypt",
"ssh/terminal" "ssh/terminal"
] ]
revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac" revision = "91a49db82a88618983a78a06c1cbd4e00ab749ab"
[[projects]] [[projects]]
branch = "master" branch = "master"
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",
"trace", "trace",
"websocket" "websocket"
] ]
revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" revision = "22ae77b79946ea320088417e4d50825671d82d57"
[[projects]] [[projects]]
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
@ -1565,6 +1573,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "b748d60cfaddd7ff38c63bdf1004ae7dc2dcd084b220076f8eed2a8971c8e234" inputs-digest = "bca5f65f32c7bfc2696eccbebe4145ce6dae7745894d111d3fa32c4d25008049"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -254,6 +254,18 @@
name = "github.com/mailgun/timetools" name = "github.com/mailgun/timetools"
revision = "7e6055773c5137efbeb3bd2410d705fe10ab6bfd" revision = "7e6055773c5137efbeb3bd2410d705fe10ab6bfd"
[[override]]
branch = "master"
name = "github.com/miekg/dns"
#
#[[override]]
# name = "golang.org/x/crypto"
# revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac"
#
#[[override]]
# name = "golang.org/x/net"
# revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
[prune] [prune]
non-go = true non-go = true
go-tests = true go-tests = true

View file

@ -243,7 +243,7 @@ entryPoint = "https"
Specify the entryPoint to use during the challenges. Specify the entryPoint to use during the challenges.
```toml ```toml
defaultEntryPoints = ["http", "http"] defaultEntryPoints = ["http", "https"]
[entryPoints] [entryPoints]
[entryPoints.http] [entryPoints.http]
@ -399,11 +399,9 @@ Each domain & SANs will lead to a certificate request.
### `dnsProvider` (Deprecated) ### `dnsProvider` (Deprecated)
!!! danger "DEPRECATED" !!! danger "DEPRECATED"
This option is deprecated. This option is deprecated, use [dnsChallenge.provider](/configuration/acme/#acmednschallenge) instead.
Please refer to [DNS challenge provider section](/configuration/acme/#provider)
### `delayDontCheckDNS` (Deprecated) ### `delayDontCheckDNS` (Deprecated)
!!! danger "DEPRECATED" !!! danger "DEPRECATED"
This option is deprecated. This option is deprecated, use [dnsChallenge.delayBeforeCheck](/configuration/acme/#acmednschallenge) instead.
Please refer to [DNS challenge delayBeforeCheck section](/configuration/acme/#delaybeforecheck)

View file

@ -43,7 +43,7 @@ For more customization, see [entry points](/configuration/entrypoints/) document
| Path | Method | Description | | Path | Method | Description |
|-----------------------------------------------------------------|------------------|-------------------------------------------| |-----------------------------------------------------------------|------------------|-------------------------------------------|
| `/` | `GET` | Provides a simple HTML frontend of Træfik | | `/` | `GET` | Provides a simple HTML frontend of Træfik |
| `/health` | `GET` | json health metrics | | `/health` | `GET` | JSON health metrics |
| `/api` | `GET` | Configuration for all providers | | `/api` | `GET` | Configuration for all providers |
| `/api/providers` | `GET` | Providers | | `/api/providers` | `GET` | Providers |
| `/api/providers/{provider}` | `GET`, `PUT` | Get or update provider (1) | | `/api/providers/{provider}` | `GET`, `PUT` | Get or update provider (1) |
@ -62,7 +62,102 @@ For more customization, see [entry points](/configuration/entrypoints/) document
For compatibility reason, when you activate the rest provider, you can use `web` or `rest` as `provider` value. For compatibility reason, when you activate the rest provider, you can use `web` or `rest` as `provider` value.
But be careful, in the configuration for all providers the key is still `web`. But be careful, in the configuration for all providers the key is still `web`.
### Provider configurations ### Address / Port
You can define a custom address/port like this:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.foo]
address = ":8082"
[entryPoints.bar]
address = ":8083"
[ping]
entryPoint = "foo"
[api]
entryPoint = "bar"
```
In the above example, you would access a regular path, administration panel, and health-check as follows:
* Regular path: `http://hostname:80/path`
* Admin Panel: `http://hostname:8083/`
* Ping URL: `http://hostname:8082/ping`
In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`.
Otherwise, you are likely to expose _all_ services via that entry point.
### Custom Path
You can define a custom path like this:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.foo]
address = ":8080"
[entryPoints.bar]
address = ":8081"
# Activate API and Dashboard
[api]
entryPoint = "bar"
dashboard = true
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://127.0.0.1:8081"
[frontends]
[frontends.frontend1]
entryPoints = ["foo"]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/yourprefix;PathPrefix:/yourprefix"
```
### Authentication
You can define the authentication like this:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.foo]
address=":8080"
[entryPoints.foo.auth]
[entryPoints.foo.auth.basic]
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
[api]
entrypoint="foo"
```
For more information, see [entry points](/configuration/entrypoints/) .
### Provider call example
```shell ```shell
curl -s "http://localhost:8080/api" | jq . curl -s "http://localhost:8080/api" | jq .

View file

@ -29,9 +29,10 @@ Træfik can be configured:
```shell ```shell
curl -XPUT @file "http://localhost:8080/api" curl -XPUT @file "http://localhost:8080/api/providers/rest"
``` ```
with `@file`
with `@file`:
```json ```json
{ {
"frontends": { "frontends": {

View file

@ -386,41 +386,6 @@ curl -s "http://localhost:8080/api" | jq .
### Deprecation compatibility ### Deprecation compatibility
#### Path
As the web provider is deprecated, you can handle the `Path` option like this:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.dashboard]
address = ":8080"
[entryPoints.api]
address = ":8081"
# Activate API and Dashboard
[api]
entryPoint = "api"
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://127.0.0.1:8081"
[frontends]
[frontends.frontend1]
entryPoints = ["dashboard"]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/yourprefix;PathPrefix:/yourprefix"
```
#### Address #### Address
As the web provider is deprecated, you can handle the `Address` option like this: As the web provider is deprecated, you can handle the `Address` option like this:
@ -432,28 +397,64 @@ defaultEntryPoints = ["http"]
[entryPoints.http] [entryPoints.http]
address = ":80" address = ":80"
[entryPoints.ping] [entryPoints.foo]
address = ":8082" address = ":8082"
[entryPoints.api] [entryPoints.bar]
address = ":8083" address = ":8083"
[ping] [ping]
entryPoint = "ping" entryPoint = "foo"
[api] [api]
entryPoint = "api" entryPoint = "bar"
``` ```
In the above example, you would access a regular path, administration panel, and health-check as follows: In the above example, you would access a regular path, administration panel, and health-check as follows:
* Regular path: `http://hostname:80/foo` * Regular path: `http://hostname:80/path`
* Admin Panel: `http://hostname:8083/` * Admin Panel: `http://hostname:8083/`
* Ping URL: `http://hostname:8082/ping` * Ping URL: `http://hostname:8082/ping`
In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`. In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`.
Otherwise, you are likely to expose _all_ services via that entry point. Otherwise, you are likely to expose _all_ services via that entry point.
#### Path
As the web provider is deprecated, you can handle the `Path` option like this:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.foo]
address = ":8080"
[entryPoints.bar]
address = ":8081"
# Activate API and Dashboard
[api]
entryPoint = "bar"
dashboard = true
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://127.0.0.1:8081"
[frontends]
[frontends.frontend1]
entryPoints = ["foo"]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/yourprefix;PathPrefix:/yourprefix"
```
#### Authentication #### Authentication
As the web provider is deprecated, you can handle the `auth` option like this: As the web provider is deprecated, you can handle the `auth` option like this:
@ -465,17 +466,17 @@ defaultEntryPoints = ["http"]
[entryPoints.http] [entryPoints.http]
address = ":80" address = ":80"
[entryPoints.api] [entryPoints.foo]
address=":8080" address=":8080"
[entryPoints.api.auth] [entryPoints.foo.auth]
[entryPoints.api.auth.basic] [entryPoints.foo.auth.basic]
users = [ users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
] ]
[api] [api]
entrypoint="api" entrypoint="foo"
``` ```
For more information, see [entry points](/configuration/entrypoints/) . For more information, see [entry points](/configuration/entrypoints/) .

View file

@ -21,24 +21,67 @@
!!! warning !!! warning
Even if you have authentication configured on entry point, the `/ping` path of the api is excluded from authentication. Even if you have authentication configured on entry point, the `/ping` path of the api is excluded from authentication.
## Example ## Examples
The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`.
Thus, if you have a regular path for `/foo` and an entrypoint on `:80`, you would access them as follows:
* Regular path: `http://hostname:80/foo`
* Admin panel: `http://hostname:8080/`
* Ping URL: `http://hostname:8080/ping`
However, for security reasons, you may want to be able to expose the `/ping` health-check URL to outside health-checkers, e.g. an Internet service or cloud load-balancer, _without_ exposing your administration panel's port.
In many environments, the security staff may not _allow_ you to expose it.
You have two options:
* Enable `/ping` on a regular entry point
* Enable `/ping` on a dedicated port
### Ping health check on a regular entry point
To proxy `/ping` from a regular entry point to the administration one without exposing the panel, do the following:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[ping]
entryPoint = "http"
```shell
curl -sv "http://localhost:8080/ping"
``` ```
```shell
* Trying ::1... The above link `ping` on the `http` entry point and then expose it on port `80`
* Connected to localhost (::1) port 8080 (#0)
> GET /ping HTTP/1.1 ### Enable ping health check on dedicated port
> Host: localhost:8080
> User-Agent: curl/7.43.0 If you do not want to or cannot expose the health-check on a regular entry point - e.g. your security rules do not allow it, or you have a conflicting path - then you can enable health-check on its own entry point.
> Accept: */* Use the following configuration:
>
< HTTP/1.1 200 OK ```toml
< Date: Thu, 25 Aug 2016 01:35:36 GMT defaultEntryPoints = ["http"]
< Content-Length: 2
< Content-Type: text/plain; charset=utf-8 [entryPoints]
< [entryPoints.http]
* Connection #0 to host localhost left intact address = ":80"
OK [entryPoints.ping]
address = ":8082"
[ping]
entryPoint = "ping"
``` ```
The above is similar to the previous example, but instead of enabling `/ping` on the _default_ entry point, we enable it on a _dedicated_ entry point.
In the above example, you would access a regular path and health-check as follows:
* Regular path: `http://hostname:80/foo`
* Ping URL: `http://hostname:8082/ping`
Note the dedicated port `:8082` for `/ping`.
In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`.
Otherwise, you are likely to expose _all_ services via this entry point.

View file

@ -335,68 +335,3 @@ providersThrottleDuration = "5s"
[respondingTimeouts] [respondingTimeouts]
idleTimeout = "360s" idleTimeout = "360s"
``` ```
## Ping Health Check
The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`.
Thus, if you have a regular path for `/foo` and an entrypoint on `:80`, you would access them as follows:
* Regular path: `http://hostname:80/foo`
* Admin panel: `http://hostname:8080/`
* Ping URL: `http://hostname:8080/ping`
However, for security reasons, you may want to be able to expose the `/ping` health-check URL to outside health-checkers, e.g. an Internet service or cloud load-balancer, _without_ exposing your administration panel's port.
In many environments, the security staff may not _allow_ you to expose it.
You have two options:
* Enable `/ping` on a regular entry point
* Enable `/ping` on a dedicated port
### Enable ping health check on a regular entry point
To proxy `/ping` from a regular entry point to the administration one without exposing the panel, do the following:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[ping]
entryPoint = "http"
```
The above link `ping` on the `http` entry point and then expose it on port `80`
### Enable ping health check on dedicated port
If you do not want to or cannot expose the health-check on a regular entry point - e.g. your security rules do not allow it, or you have a conflicting path - then you can enable health-check on its own entry point.
Use the following configuration:
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.ping]
address = ":8082"
[ping]
entryPoint = "ping"
```
The above is similar to the previous example, but instead of enabling `/ping` on the _default_ entry point, we enable it on a _dedicated_ entry point.
In the above example, you would access a regular path and health-check as follows:
* Regular path: `http://hostname:80/foo`
* Ping URL: `http://hostname:8082/ping`
Note the dedicated port `:8082` for `/ping`.
In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`.
Otherwise, you are likely to expose _all_ services via this entry point.

299
vendor/github.com/miekg/dns/client.go generated vendored
View file

@ -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
@ -29,11 +31,15 @@ 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,14 +204,11 @@ 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 {
return m, ErrSecret return m, ErrSecret
@ -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)
} }

View file

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

View file

@ -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
View file

@ -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.

View file

@ -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,6 +308,21 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
return ErrAlg return ErrAlg
} }
switch rr.Algorithm {
case ED25519:
// 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
}
rr.Signature = toBase64(signature)
default:
h := hash.New() h := hash.New()
h.Write(signdata) h.Write(signdata)
h.Write(wire) h.Write(wire)
@ -311,6 +333,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
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:

View file

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

View file

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

View file

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

31
vendor/github.com/miekg/dns/doc.go generated vendored
View file

@ -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,
@ -22,9 +22,9 @@ 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:
@ -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
View file

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

View file

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

296
vendor/github.com/miekg/dns/msg.go generated vendored
View file

@ -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()
compressionLenHelper(compression, r.Name)
} }
for i := 0; i < len(dns.Question); i++ { l += compressionLenSlice(compression, dns.Answer)
l += dns.Question[i].len() l += compressionLenSlice(compression, dns.Ns)
if dns.Compress { l += compressionLenSlice(compression, dns.Extra)
compressionLenHelper(compression, dns.Question[i].Name) } else {
for _, r := range dns.Question {
l += r.len()
}
for _, r := range dns.Answer {
if r != nil {
l += r.len()
} }
} }
for i := 0; i < len(dns.Answer); i++ { for _, r := range dns.Ns {
if dns.Answer[i] == nil { if r != nil {
l += r.len()
}
}
for _, r := range dns.Extra {
if r != nil {
l += r.len()
}
}
}
return l
}
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) compressionLenHelper(c, r.Header().Name)
k, ok = compressionLenSearchType(compression, dns.Answer[i]) k, ok = compressionLenSearchType(c, r)
if ok { if ok {
l += 1 - k l += 1 - k
} }
compressionLenHelperType(compression, dns.Answer[i]) compressionLenHelperType(c, r)
}
}
for i := 0; i < len(dns.Ns); i++ {
if dns.Ns[i] == nil {
continue
}
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])
}
} }
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 }

View file

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

View file

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

74
vendor/github.com/miekg/dns/nsecx.go generated vendored
View file

@ -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
} }
if ownerHash > nextHash { // end of zone
if nameHash > ownerHash { // covered since there is nothing after ownerHash
return true 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

View file

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

View file

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

236
vendor/github.com/miekg/dns/scan.go generated vendored
View file

@ -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) origin = Fqdn(origin)
if _, ok := IsDomainName(origin); !ok { if _, ok := IsDomainName(origin); !ok {
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}} t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
return 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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -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()
} }
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 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 {
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
continue continue
} }
srv.inFlight.Add(1) return err
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw) }
go func() {
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,12 +635,9 @@ 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
} }

View file

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

View file

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

178
vendor/github.com/miekg/dns/types.go generated vendored
View file

@ -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,13 +165,14 @@ 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
) )
@ -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.

View file

@ -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
View file

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

View file

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

View file

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

View file

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

View file

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

60
vendor/github.com/miekg/dns/xfr.go generated vendored
View file

@ -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) {
c <- &Envelope{in.Answer, nil}
return 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 {
// Now we need to check each message for SOA records, to see what we need to do
if !first {
t.tsigTimersOnly = true
// If the last record in the IXFR contains the servers' SOA, we should quit
if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
if v.Serial == serial {
c <- &Envelope{in.Answer, nil} c <- &Envelope{in.Answer, nil}
return return
} }
} }
// Now we need to check each message for SOA records, to see what we need to do
t.tsigTimersOnly = true
for _, rr := range in.Answer {
if v, ok := rr.(*SOA); ok {
if v.Serial == serial {
n++
// 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} c <- &Envelope{in.Answer, nil}
return
} }
} else if axfr {
// it's an ixfr
axfr = false
}
}
}
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
View 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
}

112
vendor/github.com/miekg/dns/zmsg.go generated vendored
View file

@ -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,11 +836,13 @@ 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 != "-" {
off, err = packStringHex(rr.Salt, msg, off)
if err != nil { if err != nil {
return off, err return off, err
} }
}
off, err = packUint8(rr.HashLength, msg, off) off, err = packUint8(rr.HashLength, msg, off)
if err != nil { if err != nil {
return off, err return off, err
@ -844,11 +881,13 @@ 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 != "-" {
off, err = packStringHex(rr.Salt, msg, off)
if err != nil { if err != nil {
return off, err 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,

View file

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

181
vendor/golang.org/x/crypto/ed25519/ed25519.go generated vendored Normal file
View 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[:])
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -93,5 +93,13 @@ func ReadPassword(fd int) ([]byte, error) {
windows.SetConsoleMode(windows.Handle(fd), old) windows.SetConsoleMode(windows.Handle(fd), old)
}() }()
return readPasswordLine(os.NewFile(uintptr(fd), "stdin")) var h windows.Handle
p, _ := windows.GetCurrentProcess()
if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
return nil, err
}
f := os.NewFile(uintptr(h), "stdin")
defer f.Close()
return readPasswordLine(f)
} }

41
vendor/golang.org/x/net/bpf/asm.go generated vendored Normal file
View 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
View 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
View 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
View 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 instruction in assembler notation.
func (a LoadConstant) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld #%d", a.Val)
case RegX:
return fmt.Sprintf("ldx #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadScratch loads scratch[N] into register Dst.
type LoadScratch struct {
Dst Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a LoadScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
}
// String returns the instruction in assembler notation.
func (a LoadScratch) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld M[%d]", a.N)
case RegX:
return fmt.Sprintf("ldx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
// register A.
type LoadAbsolute struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadAbsolute) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [%d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [%d]", a.Off)
case 4: // word
if a.Off > extOffset+0xffffffff {
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
}
return fmt.Sprintf("ld [%d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
// into register A.
type LoadIndirect struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadIndirect) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadIndirect) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [x + %d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [x + %d]", a.Off)
case 4: // word
return fmt.Sprintf("ld [x + %d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
// by 4 and stores the result in register X.
//
// This instruction is mainly useful to load into X the length of an
// IPv4 packet header in a single instruction, rather than have to do
// the arithmetic on the header's first byte by hand.
type LoadMemShift struct {
Off uint32
}
// Assemble implements the Instruction Assemble method.
func (a LoadMemShift) Assemble() (RawInstruction, error) {
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadMemShift) String() string {
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
}
// LoadExtension invokes a linux-specific extension and stores the
// result in register A.
type LoadExtension struct {
Num Extension
}
// Assemble implements the Instruction Assemble method.
func (a LoadExtension) Assemble() (RawInstruction, error) {
if a.Num == ExtLen {
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
}
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
}
// String returns the instruction in assembler notation.
func (a LoadExtension) String() string {
switch a.Num {
case ExtLen:
return "ld #len"
case ExtProto:
return "ld #proto"
case ExtType:
return "ld #type"
case ExtPayloadOffset:
return "ld #poff"
case ExtInterfaceIndex:
return "ld #ifidx"
case ExtNetlinkAttr:
return "ld #nla"
case ExtNetlinkAttrNested:
return "ld #nlan"
case ExtMark:
return "ld #mark"
case ExtQueue:
return "ld #queue"
case ExtLinkLayerType:
return "ld #hatype"
case ExtRXHash:
return "ld #rxhash"
case ExtCPUID:
return "ld #cpu"
case ExtVLANTag:
return "ld #vlan_tci"
case ExtVLANTagPresent:
return "ld #vlan_avail"
case ExtVLANProto:
return "ld #vlan_tpid"
case ExtRand:
return "ld #rand"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// StoreScratch stores register Src into scratch[N].
type StoreScratch struct {
Src Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a StoreScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
var op uint16
switch a.Src {
case RegA:
op = opClsStoreA
case RegX:
op = opClsStoreX
default:
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
}
return RawInstruction{
Op: op,
K: uint32(a.N),
}, nil
}
// String returns the instruction in assembler notation.
func (a StoreScratch) String() string {
switch a.Src {
case RegA:
return fmt.Sprintf("st M[%d]", a.N)
case RegX:
return fmt.Sprintf("stx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpConstant executes A = A <Op> Val.
type ALUOpConstant struct {
Op ALUOp
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | opALUSrcConstant | uint16(a.Op),
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpConstant) String() string {
switch a.Op {
case ALUOpAdd:
return fmt.Sprintf("add #%d", a.Val)
case ALUOpSub:
return fmt.Sprintf("sub #%d", a.Val)
case ALUOpMul:
return fmt.Sprintf("mul #%d", a.Val)
case ALUOpDiv:
return fmt.Sprintf("div #%d", a.Val)
case ALUOpMod:
return fmt.Sprintf("mod #%d", a.Val)
case ALUOpAnd:
return fmt.Sprintf("and #%d", a.Val)
case ALUOpOr:
return fmt.Sprintf("or #%d", a.Val)
case ALUOpXor:
return fmt.Sprintf("xor #%d", a.Val)
case ALUOpShiftLeft:
return fmt.Sprintf("lsh #%d", a.Val)
case ALUOpShiftRight:
return fmt.Sprintf("rsh #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpX executes A = A <Op> X
type ALUOpX struct {
Op ALUOp
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | opALUSrcX | uint16(a.Op),
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpX) String() string {
switch a.Op {
case ALUOpAdd:
return "add x"
case ALUOpSub:
return "sub x"
case ALUOpMul:
return "mul x"
case ALUOpDiv:
return "div x"
case ALUOpMod:
return "mod x"
case ALUOpAnd:
return "and x"
case ALUOpOr:
return "or x"
case ALUOpXor:
return "xor x"
case ALUOpShiftLeft:
return "lsh x"
case ALUOpShiftRight:
return "rsh x"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// NegateA executes A = -A.
type NegateA struct{}
// Assemble implements the Instruction Assemble method.
func (a NegateA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(aluOpNeg),
}, nil
}
// String returns the instruction in assembler notation.
func (a NegateA) String() string {
return fmt.Sprintf("neg")
}
// Jump skips the following Skip instructions in the program.
type Jump struct {
Skip uint32
}
// Assemble implements the Instruction Assemble method.
func (a Jump) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsJump | opJumpAlways,
K: a.Skip,
}, nil
}
// String returns the instruction in assembler notation.
func (a Jump) String() string {
return fmt.Sprintf("ja %d", a.Skip)
}
// JumpIf skips the following Skip instructions in the program if A
// <Cond> Val is true.
type JumpIf struct {
Cond JumpTest
Val uint32
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIf) Assemble() (RawInstruction, error) {
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 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 instruction in assembler notation.
func (a RetA) String() string {
return fmt.Sprintf("ret a")
}
// RetConstant exits the BPF program, returning a constant value.
type RetConstant struct {
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a RetConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsReturn | opRetSrcConstant,
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a RetConstant) String() string {
return fmt.Sprintf("ret #%d", a.Val)
}
// TXA copies the value of register X to register A.
type TXA struct{}
// Assemble implements the Instruction Assemble method.
func (a TXA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTXA,
}, nil
}
// String returns the instruction in assembler notation.
func (a TXA) String() string {
return fmt.Sprintf("txa")
}
// TAX copies the value of register A to register X.
type TAX struct{}
// Assemble implements the Instruction Assemble method.
func (a TAX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTAX,
}, nil
}
// String returns the instruction in assembler notation.
func (a TAX) String() string {
return fmt.Sprintf("tax")
}
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
var (
cls uint16
sz uint16
)
switch dst {
case RegA:
cls = opClsLoadA
case RegX:
cls = opClsLoadX
default:
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
}
switch loadSize {
case 1:
sz = opLoadWidth1
case 2:
sz = opLoadWidth2
case 4:
sz = opLoadWidth4
default:
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
}
return RawInstruction{
Op: cls | sz | mode,
K: k,
}, nil
}

10
vendor/golang.org/x/net/bpf/setter.go generated vendored Normal file
View 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
View 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
View 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
}

View file

@ -5,7 +5,7 @@
package http2 package http2
// A list of the possible cipher suite ids. Taken from // A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt // https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
const ( const (
cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000 cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000

View file

@ -206,7 +206,7 @@ func appendVarInt(dst []byte, n byte, i uint64) []byte {
} }
// appendHpackString appends s, as encoded in "String Literal" // appendHpackString appends s, as encoded in "String Literal"
// representation, to dst and returns the the extended buffer. // representation, to dst and returns the extended buffer.
// //
// s will be encoded in Huffman codes only when it produces strictly // s will be encoded in Huffman codes only when it produces strictly
// shorter byte string. // shorter byte string.

View file

@ -312,7 +312,7 @@ func mustUint31(v int32) uint32 {
} }
// bodyAllowedForStatus reports whether a given response status code // bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 2616, section 4.4. // permits a body. See RFC 7230, section 3.3.
func bodyAllowedForStatus(status int) bool { func bodyAllowedForStatus(status int) bool {
switch { switch {
case status >= 100 && status <= 199: case status >= 100 && status <= 199:

View file

@ -406,7 +406,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
// addresses during development. // addresses during development.
// //
// TODO: optionally enforce? Or enforce at the time we receive // TODO: optionally enforce? Or enforce at the time we receive
// a new request, and verify the the ServerName matches the :authority? // a new request, and verify the ServerName matches the :authority?
// But that precludes proxy situations, perhaps. // But that precludes proxy situations, perhaps.
// //
// So for now, do nothing here again. // So for now, do nothing here again.
@ -2285,7 +2285,7 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
func (rws *responseWriterState) declareTrailer(k string) { func (rws *responseWriterState) declareTrailer(k string) {
k = http.CanonicalHeaderKey(k) k = http.CanonicalHeaderKey(k)
if !ValidTrailerHeader(k) { if !ValidTrailerHeader(k) {
// Forbidden by RFC 2616 14.40. // Forbidden by RFC 7230, section 4.1.2.
rws.conn.logf("ignoring invalid trailer %q", k) rws.conn.logf("ignoring invalid trailer %q", k)
return return
} }
@ -2406,7 +2406,7 @@ const TrailerPrefix = "Trailer:"
// after the header has already been flushed. Because the Go // after the header has already been flushed. Because the Go
// ResponseWriter interface has no way to set Trailers (only the // ResponseWriter interface has no way to set Trailers (only the
// Header), and because we didn't want to expand the ResponseWriter // Header), and because we didn't want to expand the ResponseWriter
// interface, and because nobody used trailers, and because RFC 2616 // interface, and because nobody used trailers, and because RFC 7230
// says you SHOULD (but not must) predeclare any trailers in the // says you SHOULD (but not must) predeclare any trailers in the
// header, the official ResponseWriter rules said trailers in Go must // header, the official ResponseWriter rules said trailers in Go must
// be predeclared, and then we reuse the same ResponseWriter.Header() // be predeclared, and then we reuse the same ResponseWriter.Header()
@ -2790,7 +2790,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
} }
// foreachHeaderElement splits v according to the "#rule" construction // foreachHeaderElement splits v according to the "#rule" construction
// in RFC 2616 section 2.1 and calls fn for each non-empty element. // in RFC 7230 section 7 and calls fn for each non-empty element.
func foreachHeaderElement(v string, fn func(string)) { func foreachHeaderElement(v string, fn func(string)) {
v = textproto.TrimString(v) v = textproto.TrimString(v)
if v == "" { if v == "" {

180
vendor/golang.org/x/net/internal/iana/const.go generated vendored Normal file
View 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
View 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
}{
{
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
parseDSCPRegistry,
},
{
"https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
parseTOSTCByte,
},
{
"https://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
View 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
View 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)
}

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

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

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

View 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
View 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
)

View 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
)

View 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
View 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
View 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
)

View 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
)

View 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
View 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
}

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

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

View 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
}

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

View file

@ -0,0 +1,16 @@
// 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
package socket
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = int32(l)
}

View file

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

View file

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

View file

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

View file

@ -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.
package socket
func (h *msghdr) setIov(vs []iovec) {
l := len(vs)
if l == 0 {
return
}
h.Iov = &vs[0]
h.Iovlen = uint32(l)
}

View file

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

14
vendor/golang.org/x/net/internal/socket/msghdr_stub.go generated vendored Normal file
View 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 !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket
type msghdr struct{}
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {}
func (h *msghdr) name() []byte { return nil }
func (h *msghdr) controllen() int { return 0 }
func (h *msghdr) flags() int { return 0 }

66
vendor/golang.org/x/net/internal/socket/rawconn.go generated vendored Normal file
View file

@ -0,0 +1,66 @@
// 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 socket
import (
"errors"
"net"
"os"
"syscall"
)
// A Conn represents a raw connection.
type Conn struct {
network string
c syscall.RawConn
}
// NewConn returns a new raw connection.
func NewConn(c net.Conn) (*Conn, error) {
var err error
var cc Conn
switch c := c.(type) {
case *net.TCPConn:
cc.network = "tcp"
cc.c, err = c.SyscallConn()
case *net.UDPConn:
cc.network = "udp"
cc.c, err = c.SyscallConn()
case *net.IPConn:
cc.network = "ip"
cc.c, err = c.SyscallConn()
default:
return nil, errors.New("unknown connection type")
}
if err != nil {
return nil, err
}
return &cc, nil
}
func (o *Option) get(c *Conn, b []byte) (int, error) {
var operr error
var n int
fn := func(s uintptr) {
n, operr = getsockopt(s, o.Level, o.Name, b)
}
if err := c.c.Control(fn); err != nil {
return 0, err
}
return n, os.NewSyscallError("getsockopt", operr)
}
func (o *Option) set(c *Conn, b []byte) error {
var operr error
fn := func(s uintptr) {
operr = setsockopt(s, o.Level, o.Name, b)
}
if err := c.c.Control(fn); err != nil {
return err
}
return os.NewSyscallError("setsockopt", operr)
}

View file

@ -0,0 +1,74 @@
// 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
// +build linux
package socket
import (
"net"
"os"
"syscall"
)
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
hs := make(mmsghdrs, len(ms))
var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" {
parseFn = parseInetAddr
}
if err := hs.pack(ms, parseFn, nil); err != nil {
return 0, err
}
var operr error
var n int
fn := func(s uintptr) bool {
n, operr = recvmmsg(s, hs, flags)
if operr == syscall.EAGAIN {
return false
}
return true
}
if err := c.c.Read(fn); err != nil {
return n, err
}
if operr != nil {
return n, os.NewSyscallError("recvmmsg", operr)
}
if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil {
return n, err
}
return n, nil
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
hs := make(mmsghdrs, len(ms))
var marshalFn func(net.Addr) []byte
if c.network != "tcp" {
marshalFn = marshalInetAddr
}
if err := hs.pack(ms, nil, marshalFn); err != nil {
return 0, err
}
var operr error
var n int
fn := func(s uintptr) bool {
n, operr = sendmmsg(s, hs, flags)
if operr == syscall.EAGAIN {
return false
}
return true
}
if err := c.c.Write(fn); err != nil {
return n, err
}
if operr != nil {
return n, os.NewSyscallError("sendmmsg", operr)
}
if err := hs[:n].unpack(ms[:n], nil, ""); err != nil {
return n, err
}
return n, nil
}

77
vendor/golang.org/x/net/internal/socket/rawconn_msg.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
// 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
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package socket
import (
"os"
"syscall"
)
func (c *Conn) recvMsg(m *Message, flags int) error {
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
if c.network != "tcp" {
sa = make([]byte, sizeofSockaddrInet6)
}
h.pack(vs, m.Buffers, m.OOB, sa)
var operr error
var n int
fn := func(s uintptr) bool {
n, operr = recvmsg(s, &h, flags)
if operr == syscall.EAGAIN {
return false
}
return true
}
if err := c.c.Read(fn); err != nil {
return err
}
if operr != nil {
return os.NewSyscallError("recvmsg", operr)
}
if c.network != "tcp" {
var err error
m.Addr, err = parseInetAddr(sa[:], c.network)
if err != nil {
return err
}
}
m.N = n
m.NN = h.controllen()
m.Flags = h.flags()
return nil
}
func (c *Conn) sendMsg(m *Message, flags int) error {
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
if m.Addr != nil {
sa = marshalInetAddr(m.Addr)
}
h.pack(vs, m.Buffers, m.OOB, sa)
var operr error
var n int
fn := func(s uintptr) bool {
n, operr = sendmsg(s, &h, flags)
if operr == syscall.EAGAIN {
return false
}
return true
}
if err := c.c.Write(fn); err != nil {
return err
}
if operr != nil {
return os.NewSyscallError("sendmsg", operr)
}
m.N = n
m.NN = len(m.OOB)
return nil
}

View file

@ -0,0 +1,18 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
// +build !linux
package socket
import "errors"
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}

View file

@ -0,0 +1,18 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package socket
import "errors"
func (c *Conn) recvMsg(m *Message, flags int) error {
return errors.New("not implemented")
}
func (c *Conn) sendMsg(m *Message, flags int) error {
return errors.New("not implemented")
}

View file

@ -0,0 +1,25 @@
// 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 socket
import "errors"
func (c *Conn) recvMsg(m *Message, flags int) error {
return errors.New("not implemented")
}
func (c *Conn) sendMsg(m *Message, flags int) error {
return errors.New("not implemented")
}
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}

62
vendor/golang.org/x/net/internal/socket/reflect.go generated vendored Normal file
View file

@ -0,0 +1,62 @@
// 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 socket
import (
"errors"
"net"
"os"
"reflect"
"runtime"
)
// A Conn represents a raw connection.
type Conn struct {
c net.Conn
}
// NewConn returns a new raw connection.
func NewConn(c net.Conn) (*Conn, error) {
return &Conn{c: c}, nil
}
func (o *Option) get(c *Conn, b []byte) (int, error) {
s, err := socketOf(c.c)
if err != nil {
return 0, err
}
n, err := getsockopt(s, o.Level, o.Name, b)
return n, os.NewSyscallError("getsockopt", err)
}
func (o *Option) set(c *Conn, b []byte) error {
s, err := socketOf(c.c)
if err != nil {
return err
}
return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
}
func socketOf(c net.Conn) (uintptr, error) {
switch c.(type) {
case *net.TCPConn, *net.UDPConn, *net.IPConn:
v := reflect.ValueOf(c)
switch e := v.Elem(); e.Kind() {
case reflect.Struct:
fd := e.FieldByName("conn").FieldByName("fd")
switch e := fd.Elem(); e.Kind() {
case reflect.Struct:
sysfd := e.FieldByName("sysfd")
if runtime.GOOS == "windows" {
return uintptr(sysfd.Uint()), nil
}
return uintptr(sysfd.Int()), nil
}
}
}
return 0, errors.New("invalid type")
}

285
vendor/golang.org/x/net/internal/socket/socket.go generated vendored Normal file
View file

@ -0,0 +1,285 @@
// 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 provides a portable interface for socket system
// calls.
package socket // import "golang.org/x/net/internal/socket"
import (
"errors"
"net"
"unsafe"
)
// An Option represents a sticky socket option.
type Option struct {
Level int // level
Name int // name; must be equal or greater than 1
Len int // length of value in bytes; must be equal or greater than 1
}
// Get reads a value for the option from the kernel.
// It returns the number of bytes written into b.
func (o *Option) Get(c *Conn, b []byte) (int, error) {
if o.Name < 1 || o.Len < 1 {
return 0, errors.New("invalid option")
}
if len(b) < o.Len {
return 0, errors.New("short buffer")
}
return o.get(c, b)
}
// GetInt returns an integer value for the option.
//
// The Len field of Option must be either 1 or 4.
func (o *Option) GetInt(c *Conn) (int, error) {
if o.Len != 1 && o.Len != 4 {
return 0, errors.New("invalid option")
}
var b []byte
var bb [4]byte
if o.Len == 1 {
b = bb[:1]
} else {
b = bb[:4]
}
n, err := o.get(c, b)
if err != nil {
return 0, err
}
if n != o.Len {
return 0, errors.New("invalid option length")
}
if o.Len == 1 {
return int(b[0]), nil
}
return int(NativeEndian.Uint32(b[:4])), nil
}
// Set writes the option and value to the kernel.
func (o *Option) Set(c *Conn, b []byte) error {
if o.Name < 1 || o.Len < 1 {
return errors.New("invalid option")
}
if len(b) < o.Len {
return errors.New("short buffer")
}
return o.set(c, b)
}
// SetInt writes the option and value to the kernel.
//
// The Len field of Option must be either 1 or 4.
func (o *Option) SetInt(c *Conn, v int) error {
if o.Len != 1 && o.Len != 4 {
return errors.New("invalid option")
}
var b []byte
if o.Len == 1 {
b = []byte{byte(v)}
} else {
var bb [4]byte
NativeEndian.PutUint32(bb[:o.Len], uint32(v))
b = bb[:4]
}
return o.set(c, b)
}
func controlHeaderLen() int {
return roundup(sizeofCmsghdr)
}
func controlMessageLen(dataLen int) int {
return roundup(sizeofCmsghdr) + dataLen
}
// ControlMessageSpace returns the whole length of control message.
func ControlMessageSpace(dataLen int) int {
return roundup(sizeofCmsghdr) + roundup(dataLen)
}
// A ControlMessage represents the head message in a stream of control
// messages.
//
// A control message comprises of a header, data and a few padding
// fields to conform to the interface to the kernel.
//
// See RFC 3542 for further information.
type ControlMessage []byte
// Data returns the data field of the control message at the head on
// m.
func (m ControlMessage) Data(dataLen int) []byte {
l := controlHeaderLen()
if len(m) < l || len(m) < l+dataLen {
return nil
}
return m[l : l+dataLen]
}
// Next returns the control message at the next on m.
//
// Next works only for standard control messages.
func (m ControlMessage) Next(dataLen int) ControlMessage {
l := ControlMessageSpace(dataLen)
if len(m) < l {
return nil
}
return m[l:]
}
// MarshalHeader marshals the header fields of the control message at
// the head on m.
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
if len(m) < controlHeaderLen() {
return errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(dataLen), lvl, typ)
return nil
}
// ParseHeader parses and returns the header fields of the control
// message at the head on m.
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
l := controlHeaderLen()
if len(m) < l {
return 0, 0, 0, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
}
// Marshal marshals the control message at the head on m, and returns
// the next control message.
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
l := len(data)
if len(m) < ControlMessageSpace(l) {
return nil, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(l), lvl, typ)
if l > 0 {
copy(m.Data(l), data)
}
return m.Next(l), nil
}
// Parse parses m as a single or multiple control messages.
//
// Parse works for both standard and compatible messages.
func (m ControlMessage) Parse() ([]ControlMessage, error) {
var ms []ControlMessage
for len(m) >= controlHeaderLen() {
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
l := h.len()
if l <= 0 {
return nil, errors.New("invalid header length")
}
if uint64(l) < uint64(controlHeaderLen()) {
return nil, errors.New("invalid message length")
}
if uint64(l) > uint64(len(m)) {
return nil, errors.New("short buffer")
}
// On message reception:
//
// |<- ControlMessageSpace --------------->|
// |<- controlMessageLen ---------->| |
// |<- controlHeaderLen ->| | |
// +---------------+------+---------+------+
// | Header | PadH | Data | PadD |
// +---------------+------+---------+------+
//
// On compatible message reception:
//
// | ... |<- controlMessageLen ----------->|
// | ... |<- controlHeaderLen ->| |
// +-----+---------------+------+----------+
// | ... | Header | PadH | Data |
// +-----+---------------+------+----------+
ms = append(ms, ControlMessage(m[:l]))
ll := l - controlHeaderLen()
if len(m) >= ControlMessageSpace(ll) {
m = m[ControlMessageSpace(ll):]
} else {
m = m[controlMessageLen(ll):]
}
}
return ms, nil
}
// NewControlMessage returns a new stream of control messages.
func NewControlMessage(dataLen []int) ControlMessage {
var l int
for i := range dataLen {
l += ControlMessageSpace(dataLen[i])
}
return make([]byte, l)
}
// A Message represents an IO message.
type Message struct {
// When writing, the Buffers field must contain at least one
// byte to write.
// When reading, the Buffers field will always contain a byte
// to read.
Buffers [][]byte
// OOB contains protocol-specific control or miscellaneous
// ancillary data known as out-of-band data.
OOB []byte
// Addr specifies a destination address when writing.
// It can be nil when the underlying protocol of the raw
// connection uses connection-oriented communication.
// After a successful read, it may contain the source address
// on the received packet.
Addr net.Addr
N int // # of bytes read or written from/to Buffers
NN int // # of bytes read or written from/to OOB
Flags int // protocol-specific information on the received message
}
// RecvMsg wraps recvmsg system call.
//
// The provided flags is a set of platform-dependent flags, such as
// syscall.MSG_PEEK.
func (c *Conn) RecvMsg(m *Message, flags int) error {
return c.recvMsg(m, flags)
}
// SendMsg wraps sendmsg system call.
//
// The provided flags is a set of platform-dependent flags, such as
// syscall.MSG_DONTROUTE.
func (c *Conn) SendMsg(m *Message, flags int) error {
return c.sendMsg(m, flags)
}
// RecvMsgs wraps recvmmsg system call.
//
// It returns the number of processed messages.
//
// The provided flags is a set of platform-dependent flags, such as
// syscall.MSG_PEEK.
//
// Only Linux supports this.
func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
return c.recvMsgs(ms, flags)
}
// SendMsgs wraps sendmmsg system call.
//
// It returns the number of processed messages.
//
// The provided flags is a set of platform-dependent flags, such as
// syscall.MSG_DONTROUTE.
//
// Only Linux supports this.
func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
return c.sendMsgs(ms, flags)
}

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