diff --git a/manager.go b/manager.go
index 76910d12f52f92609396b37e8c879b9d300128a2..a2f099edec7c1628d46cfb8f2306d5a40573b181 100644
--- a/manager.go
+++ b/manager.go
@@ -17,7 +17,7 @@ import (
 	"sync"
 	"time"
 
-	"git.autistici.org/ai3/go-common/clientutil"
+	"git.autistici.org/ai3/replds"
 	"github.com/prometheus/client_golang/prometheus"
 )
 
@@ -109,13 +109,13 @@ func NewManager(config *Config, certGen CertGenerator) (*Manager, error) {
 	if config.ReplDS == nil {
 		m.storage = ds
 	} else {
-		be, err := clientutil.NewBackend(config.ReplDS)
+		r, err := replds.NewPublicClient(config.ReplDS)
 		if err != nil {
 			return nil, err
 		}
 		m.storage = &replStorage{
 			dirStorage: ds,
-			replClient: be,
+			replClient: r,
 		}
 	}
 
diff --git a/storage.go b/storage.go
index b94d6545b5df8a2941bbf6d11e1801411f24d742..9641fe67ffb1d187b0cbfc57d58be77ac00ab274 100644
--- a/storage.go
+++ b/storage.go
@@ -16,7 +16,6 @@ import (
 	"strings"
 	"time"
 
-	"git.autistici.org/ai3/go-common/clientutil"
 	"git.autistici.org/ai3/replds"
 )
 
@@ -93,7 +92,7 @@ func dumpCertsAndKey(cn string, der [][]byte, key crypto.Signer) (map[string][]b
 // certificates to replds instead.
 type replStorage struct {
 	*dirStorage
-	replClient clientutil.Backend
+	replClient replds.PublicClient
 }
 
 func (d *replStorage) PutCert(cn string, der [][]byte, key crypto.Signer) error {
@@ -115,8 +114,8 @@ func (d *replStorage) PutCert(cn string, der [][]byte, key crypto.Signer) error
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 	defer cancel()
 
-	var resp replds.SetNodesResponse
-	if err := clientutil.DoJSONHTTPRequest(ctx, d.replClient.Client(""), d.replClient.URL("")+"/api/set_nodes", req, &resp); err != nil {
+	resp, err := d.replClient.SetNodes(ctx, &req)
+	if err != nil {
 		return err
 	}
 	if resp.HostsOk < 1 {
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/backend.go b/vendor/git.autistici.org/ai3/go-common/clientutil/backend.go
index 1f49a7e58d4ef0e51c1bc36369e1399441273ef2..6580d0eb42ae0070a803db7df6ce15d7da595e3b 100644
--- a/vendor/git.autistici.org/ai3/go-common/clientutil/backend.go
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/backend.go
@@ -1,15 +1,10 @@
 package clientutil
 
 import (
-	"crypto/tls"
-	"fmt"
-	"net/http"
-	"net/url"
-	"sync"
-	"time"
+	"context"
 )
 
-// BackendConfig specifies the configuration to access a service.
+// BackendConfig specifies the configuration of a service backend.
 //
 // Services with multiple backends can be replicated or partitioned,
 // depending on a configuration switch, making it a deployment-time
@@ -18,102 +13,30 @@ import (
 // 'shard' parameter on their APIs.
 type BackendConfig struct {
 	URL       string           `yaml:"url"`
-	Sharded   bool             `yaml:"sharded"`
 	TLSConfig *TLSClientConfig `yaml:"tls_config"`
+	Sharded   bool             `yaml:"sharded"`
+	Debug     bool             `yaml:"debug"`
 }
 
 // Backend is a runtime class that provides http Clients for use with
 // a specific service backend. If the service can't be partitioned,
-// pass an empty string to the Client method.
+// pass an empty string to the Call method.
 type Backend interface {
-	// URL for the service for a specific shard.
-	URL(string) string
+	// Call a remote method. The sharding behavior is the following:
+	//
+	// Services that support sharding (partitioning) should always
+	// include the shard ID in their Call() requests. Users can
+	// then configure backends to be sharded or not in their
+	// Config. When invoking Call with a shard ID on a non-sharded
+	// service, the shard ID is simply ignored. Invoking Call
+	// *without* a shard ID on a sharded service is an error.
+	Call(context.Context, string, string, interface{}, interface{}) error
 
-	// Client that can be used to make a request to the service.
-	Client(string) *http.Client
+	// Close all resources associated with the backend.
+	Close()
 }
 
 // NewBackend returns a new Backend with the given config.
 func NewBackend(config *BackendConfig) (Backend, error) {
-	u, err := url.Parse(config.URL)
-	if err != nil {
-		return nil, err
-	}
-
-	var tlsConfig *tls.Config
-	if config.TLSConfig != nil {
-		tlsConfig, err = config.TLSConfig.TLSConfig()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if config.Sharded {
-		return &replicatedClient{
-			u: u,
-			c: newHTTPClient(u, tlsConfig),
-		}, nil
-	}
-	return &shardedClient{
-		baseURL:   u,
-		tlsConfig: tlsConfig,
-		urls:      make(map[string]*url.URL),
-		shards:    make(map[string]*http.Client),
-	}, nil
-}
-
-type replicatedClient struct {
-	c *http.Client
-	u *url.URL
-}
-
-func (r *replicatedClient) Client(_ string) *http.Client { return r.c }
-func (r *replicatedClient) URL(_ string) string          { return r.u.String() }
-
-type shardedClient struct {
-	baseURL   *url.URL
-	tlsConfig *tls.Config
-	mx        sync.Mutex
-	urls      map[string]*url.URL
-	shards    map[string]*http.Client
-}
-
-func (s *shardedClient) getShardURL(shard string) *url.URL {
-	if shard == "" {
-		return s.baseURL
-	}
-	u, ok := s.urls[shard]
-	if !ok {
-		var tmp = *s.baseURL
-		tmp.Host = fmt.Sprintf("%s.%s", shard, tmp.Host)
-		u = &tmp
-		s.urls[shard] = u
-	}
-	return u
-}
-
-func (s *shardedClient) URL(shard string) string {
-	s.mx.Lock()
-	defer s.mx.Unlock()
-	return s.getShardURL(shard).String()
-}
-
-func (s *shardedClient) Client(shard string) *http.Client {
-	s.mx.Lock()
-	defer s.mx.Unlock()
-
-	client, ok := s.shards[shard]
-	if !ok {
-		u := s.getShardURL(shard)
-		client = newHTTPClient(u, s.tlsConfig)
-		s.shards[shard] = client
-	}
-	return client
-}
-
-func newHTTPClient(u *url.URL, tlsConfig *tls.Config) *http.Client {
-	return &http.Client{
-		Transport: NewTransport([]string{u.Host}, tlsConfig, nil),
-		Timeout:   30 * time.Second,
-	}
+	return newBalancedBackend(config, defaultResolver)
 }
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go b/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go
new file mode 100644
index 0000000000000000000000000000000000000000..9d9b7dd6cdf2f9f66b93d3f6c7f0778de44060fb
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go
@@ -0,0 +1,271 @@
+package clientutil
+
+import (
+	"bytes"
+	"context"
+	"crypto/tls"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"math/rand"
+	"net/http"
+	"net/url"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/cenkalti/backoff"
+)
+
+// Our own narrow logger interface.
+type logger interface {
+	Printf(string, ...interface{})
+}
+
+// A nilLogger is used when Config.Debug is false.
+type nilLogger struct{}
+
+func (l nilLogger) Printf(_ string, _ ...interface{}) {}
+
+// Parameters that define the exponential backoff algorithm used.
+var (
+	ExponentialBackOffInitialInterval = 100 * time.Millisecond
+	ExponentialBackOffMultiplier      = 1.4142
+)
+
+// newExponentialBackOff creates a backoff.ExponentialBackOff object
+// with our own default values.
+func newExponentialBackOff() *backoff.ExponentialBackOff {
+	b := backoff.NewExponentialBackOff()
+	b.InitialInterval = ExponentialBackOffInitialInterval
+	b.Multiplier = ExponentialBackOffMultiplier
+
+	// Set MaxElapsedTime to 0 because we expect the overall
+	// timeout to be dictated by the request Context.
+	b.MaxElapsedTime = 0
+
+	return b
+}
+
+// Balancer for HTTP connections. It will round-robin across available
+// backends, trying to avoid ones that are erroring out, until one
+// succeeds or returns a permanent error.
+//
+// This object should not be used for load balancing of individual
+// HTTP requests: it doesn't do anything smart beyond trying to avoid
+// broken targets. It's meant to provide a *reliable* connection to a
+// set of equivalent services for HA purposes.
+type balancedBackend struct {
+	*backendTracker
+	*transportCache
+	baseURI  *url.URL
+	sharded  bool
+	resolver resolver
+	log      logger
+}
+
+func newBalancedBackend(config *BackendConfig, resolver resolver) (*balancedBackend, error) {
+	u, err := url.Parse(config.URL)
+	if err != nil {
+		return nil, err
+	}
+
+	var tlsConfig *tls.Config
+	if config.TLSConfig != nil {
+		tlsConfig, err = config.TLSConfig.TLSConfig()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	var logger logger = &nilLogger{}
+	if config.Debug {
+		logger = log.New(os.Stderr, fmt.Sprintf("backend %s: ", u.Host), 0)
+	}
+	return &balancedBackend{
+		backendTracker: newBackendTracker(u.Host, resolver, logger),
+		transportCache: newTransportCache(tlsConfig),
+		sharded:        config.Sharded,
+		baseURI:        u,
+		resolver:       resolver,
+		log:            logger,
+	}, nil
+}
+
+// Call the backend. Makes an HTTP POST request to the specified uri,
+// with a JSON-encoded request body. It will attempt to decode the
+// response body as JSON.
+func (b *balancedBackend) Call(ctx context.Context, shard, path string, req, resp interface{}) error {
+	data, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+
+	var tg targetGenerator = b.backendTracker
+	if b.sharded && shard != "" {
+		tg = newShardedGenerator(shard, b.baseURI.Host, b.resolver)
+	}
+	seq := newSequence(tg)
+	b.log.Printf("%016x: initialized", seq.ID())
+
+	var httpResp *http.Response
+	err = backoff.Retry(func() error {
+		req, rerr := b.newJSONRequest(path, shard, data)
+		if rerr != nil {
+			return rerr
+		}
+		httpResp, rerr = b.do(ctx, seq, req)
+		return rerr
+	}, backoff.WithContext(newExponentialBackOff(), ctx))
+	if err != nil {
+		return err
+	}
+	defer httpResp.Body.Close() // nolint
+
+	if httpResp.Header.Get("Content-Type") != "application/json" {
+		return errors.New("not a JSON response")
+	}
+
+	if resp == nil {
+		return nil
+	}
+	return json.NewDecoder(httpResp.Body).Decode(resp)
+}
+
+// Return the URI to be used for the request. This is used both in the
+// Host HTTP header and as the TLS server name used to pick a server
+// certificate (if using TLS).
+func (b *balancedBackend) getURIForRequest(shard, path string) string {
+	u := *b.baseURI
+	if b.sharded && shard != "" {
+		u.Host = fmt.Sprintf("%s.%s", shard, u.Host)
+	}
+	u.Path = appendPath(u.Path, path)
+	return u.String()
+}
+
+// Build a http.Request object.
+func (b *balancedBackend) newJSONRequest(path, shard string, data []byte) (*http.Request, error) {
+	req, err := http.NewRequest("POST", b.getURIForRequest(shard, path), bytes.NewReader(data))
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", "application/json")
+	req.Header.Set("Content-Length", strconv.FormatInt(int64(len(data)), 10))
+	return req, nil
+}
+
+// Select a new target from the given sequence and send the request to
+// it. Wrap HTTP errors in a RemoteError object.
+func (b *balancedBackend) do(ctx context.Context, seq *sequence, req *http.Request) (resp *http.Response, err error) {
+	target, terr := seq.Next()
+	if terr != nil {
+		return
+	}
+
+	b.log.Printf("sequence %016x: connecting to %s", seq.ID(), target)
+	client := &http.Client{
+		Transport: b.transportCache.getTransport(target),
+	}
+	resp, err = client.Do(req.WithContext(ctx))
+	if err == nil && resp.StatusCode != 200 {
+		err = remoteErrorFromResponse(resp)
+		if !isStatusTemporary(resp.StatusCode) {
+			err = backoff.Permanent(err)
+		}
+		resp.Body.Close() // nolint
+		resp = nil
+	}
+
+	seq.Done(target, err)
+	return
+}
+
+var errNoTargets = errors.New("no available backends")
+
+type targetGenerator interface {
+	getTargets() []string
+	setStatus(string, bool)
+}
+
+// A replicatedSequence repeatedly iterates over available backends in order of
+// preference. Once in a while it refreshes its list of available
+// targets.
+type sequence struct {
+	id      uint64
+	tg      targetGenerator
+	targets []string
+	pos     int
+}
+
+func newSequence(tg targetGenerator) *sequence {
+	return &sequence{
+		id:      rand.Uint64(),
+		tg:      tg,
+		targets: tg.getTargets(),
+	}
+}
+
+func (s *sequence) ID() uint64 { return s.id }
+
+func (s *sequence) reloadTargets() {
+	targets := s.tg.getTargets()
+	if len(targets) > 0 {
+		s.targets = targets
+		s.pos = 0
+	}
+}
+
+// Next returns the next target.
+func (s *sequence) Next() (t string, err error) {
+	if s.pos >= len(s.targets) {
+		s.reloadTargets()
+		if len(s.targets) == 0 {
+			err = errNoTargets
+			return
+		}
+	}
+	t = s.targets[s.pos]
+	s.pos++
+	return
+}
+
+func (s *sequence) Done(t string, err error) {
+	s.tg.setStatus(t, err == nil)
+}
+
+// A shardedGenerator returns a single sharded target to a sequence.
+type shardedGenerator struct {
+	id    uint64
+	addrs []string
+}
+
+func newShardedGenerator(shard, base string, resolver resolver) *shardedGenerator {
+	return &shardedGenerator{
+		id:    rand.Uint64(),
+		addrs: resolver.ResolveIP(fmt.Sprintf("%s.%s", shard, base)),
+	}
+}
+
+func (g *shardedGenerator) getTargets() []string       { return g.addrs }
+func (g *shardedGenerator) setStatus(_ string, _ bool) {}
+
+// Concatenate two URI paths.
+func appendPath(a, b string) string {
+	if strings.HasSuffix(a, "/") && strings.HasPrefix(b, "/") {
+		return a + b[1:]
+	}
+	return a + b
+}
+
+// Some HTTP status codes are treated are temporary errors.
+func isStatusTemporary(code int) bool {
+	switch code {
+	case http.StatusTooManyRequests, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
+		return true
+	default:
+		return false
+	}
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/cpu.prof b/vendor/git.autistici.org/ai3/go-common/clientutil/cpu.prof
new file mode 100644
index 0000000000000000000000000000000000000000..89fe0a7d104f6c1ca9466d218abbfe393d431402
Binary files /dev/null and b/vendor/git.autistici.org/ai3/go-common/clientutil/cpu.prof differ
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/dns.go b/vendor/git.autistici.org/ai3/go-common/clientutil/dns.go
new file mode 100644
index 0000000000000000000000000000000000000000..ed30f87342295aa2594c9302b1b1ecdee8014aee
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/dns.go
@@ -0,0 +1,98 @@
+package clientutil
+
+import (
+	"log"
+	"net"
+	"sync"
+	"time"
+
+	"golang.org/x/sync/singleflight"
+)
+
+type resolver interface {
+	ResolveIP(string) []string
+}
+
+type dnsResolver struct{}
+
+func (r *dnsResolver) ResolveIP(hostport string) []string {
+	var resolved []string
+	host, port, err := net.SplitHostPort(hostport)
+	if err != nil {
+		log.Printf("error parsing %s: %v", hostport, err)
+		return nil
+	}
+	hostIPs, err := net.LookupIP(host)
+	if err != nil {
+		log.Printf("error resolving %s: %v", host, err)
+		return nil
+	}
+	for _, ip := range hostIPs {
+		resolved = append(resolved, net.JoinHostPort(ip.String(), port))
+	}
+	return resolved
+}
+
+var defaultResolver = newDNSCache(&dnsResolver{})
+
+type cacheDatum struct {
+	addrs    []string
+	deadline time.Time
+}
+
+type dnsCache struct {
+	resolver resolver
+	sf       singleflight.Group
+	mx       sync.RWMutex
+	cache    map[string]cacheDatum
+}
+
+func newDNSCache(resolver resolver) *dnsCache {
+	return &dnsCache{
+		resolver: resolver,
+		cache:    make(map[string]cacheDatum),
+	}
+}
+
+func (c *dnsCache) get(host string) ([]string, bool) {
+	d, ok := c.cache[host]
+	if !ok {
+		return nil, false
+	}
+	return d.addrs, d.deadline.After(time.Now())
+}
+
+func (c *dnsCache) update(host string) []string {
+	v, _, _ := c.sf.Do(host, func() (interface{}, error) {
+		addrs := c.resolver.ResolveIP(host)
+		// By uncommenting this, we stop caching negative results.
+		// if len(addrs) == 0 {
+		// 	return nil, nil
+		// }
+		c.mx.Lock()
+		c.cache[host] = cacheDatum{
+			addrs:    addrs,
+			deadline: time.Now().Add(60 * time.Second),
+		}
+		c.mx.Unlock()
+		return addrs, nil
+	})
+	return v.([]string)
+}
+
+func (c *dnsCache) ResolveIP(host string) []string {
+	c.mx.RLock()
+	addrs, ok := c.get(host)
+	c.mx.RUnlock()
+
+	if ok {
+		return addrs
+	}
+
+	if len(addrs) > 0 {
+		go c.update(host)
+		return addrs
+	}
+
+	return c.update(host)
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/doc.go b/vendor/git.autistici.org/ai3/go-common/clientutil/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..421915b66a9818d943c5fcbf80c39cfc2d141a2c
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/doc.go
@@ -0,0 +1,37 @@
+// Package clientutil implements a very simple style of JSON RPC.
+//
+// Requests and responses are both encoded in JSON, and they should
+// have the "application/json" Content-Type.
+//
+// HTTP response statuses other than 200 indicate an error: in this
+// case, the response body may contain (in plain text) further details
+// about the error. Some HTTP status codes are considered temporary
+// errors (incl. 429 for throttling). The client will retry requests,
+// if targets are available, until the context expires - so it's quite
+// important to remember to set a timeout on the context given to the
+// Call() function!
+//
+// The client handles both replicated services and sharded
+// (partitioned) services. Users of this package that want to support
+// sharded deployments are supposed to pass a shard ID to every
+// Call(). At the deployment stage, sharding can be enabled via the
+// configuration.
+//
+// For replicated services, the client will expect the provided
+// hostname to resolve to one or more IP addresses, in which case it
+// will pick a random IP address on every new request, while
+// remembering which addresses have had errors and trying to avoid
+// them. It will however send an occasional request to the failed
+// targets, to see if they've come back.
+//
+// For sharded services, the client makes simple HTTP requests to the
+// specific target identified by the shard. It does this by prepending
+// the shard ID to the backend hostname (so a request to "example.com"
+// with shard ID "1" becomes a request to "1.example.com").
+//
+// The difference with other JSON-RPC implementations is that we use a
+// different URI for every method, and we force the usage of
+// request/response types. This makes it easy for projects to
+// eventually migrate to GRPC.
+//
+package clientutil
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/error.go b/vendor/git.autistici.org/ai3/go-common/clientutil/error.go
new file mode 100644
index 0000000000000000000000000000000000000000..f011e162c39d835952bda45b846b17be3a308336
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/error.go
@@ -0,0 +1,35 @@
+package clientutil
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+)
+
+// RemoteError represents a HTTP error from the server. The status
+// code and response body can be retrieved with the StatusCode() and
+// Body() methods.
+type RemoteError struct {
+	statusCode int
+	body       string
+}
+
+func remoteErrorFromResponse(resp *http.Response) *RemoteError {
+	// Optimistically read the response body, ignoring errors.
+	var body string
+	if data, err := ioutil.ReadAll(resp.Body); err == nil {
+		body = string(data)
+	}
+	return &RemoteError{statusCode: resp.StatusCode, body: body}
+}
+
+// Error implements the error interface.
+func (e *RemoteError) Error() string {
+	return fmt.Sprintf("%d - %s", e.statusCode, e.body)
+}
+
+// StatusCode returns the HTTP status code.
+func (e *RemoteError) StatusCode() int { return e.statusCode }
+
+// Body returns the response body.
+func (e *RemoteError) Body() string { return e.body }
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/json.go b/vendor/git.autistici.org/ai3/go-common/clientutil/json.go
deleted file mode 100644
index 5fc1ab2e4ab75061c44e816c79a874c580c73a73..0000000000000000000000000000000000000000
--- a/vendor/git.autistici.org/ai3/go-common/clientutil/json.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package clientutil
-
-import (
-	"bytes"
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/http"
-)
-
-// DoJSONHTTPRequest makes an HTTP POST request to the specified uri,
-// with a JSON-encoded request body. It will attempt to decode the
-// response body as JSON.
-func DoJSONHTTPRequest(ctx context.Context, client *http.Client, uri string, req, resp interface{}) error {
-	data, err := json.Marshal(req)
-	if err != nil {
-		return err
-	}
-
-	httpReq, err := http.NewRequest("POST", uri, bytes.NewReader(data))
-	if err != nil {
-		return err
-	}
-	httpReq.Header.Set("Content-Type", "application/json")
-	httpReq = httpReq.WithContext(ctx)
-
-	httpResp, err := RetryHTTPDo(client, httpReq, NewExponentialBackOff())
-	if err != nil {
-		return err
-	}
-	defer httpResp.Body.Close()
-
-	if httpResp.StatusCode != 200 {
-		return fmt.Errorf("HTTP status %d", httpResp.StatusCode)
-	}
-	if httpResp.Header.Get("Content-Type") != "application/json" {
-		return errors.New("not a JSON response")
-	}
-
-	if resp == nil {
-		return nil
-	}
-	return json.NewDecoder(httpResp.Body).Decode(resp)
-}
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/retry.go b/vendor/git.autistici.org/ai3/go-common/clientutil/retry.go
deleted file mode 100644
index 3ca7b51a48289a18cd829947cbdbc400392ffc93..0000000000000000000000000000000000000000
--- a/vendor/git.autistici.org/ai3/go-common/clientutil/retry.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package clientutil
-
-import (
-	"errors"
-	"net/http"
-	"time"
-
-	"github.com/cenkalti/backoff"
-)
-
-// NewExponentialBackOff creates a backoff.ExponentialBackOff object
-// with our own default values.
-func NewExponentialBackOff() *backoff.ExponentialBackOff {
-	b := backoff.NewExponentialBackOff()
-	b.InitialInterval = 100 * time.Millisecond
-	//b.Multiplier = 1.4142
-	return b
-}
-
-// A temporary (retriable) error is something that has a Temporary method.
-type tempError interface {
-	Temporary() bool
-}
-
-type tempErrorWrapper struct {
-	error
-}
-
-func (t tempErrorWrapper) Temporary() bool { return true }
-
-// TempError makes a temporary (retriable) error out of a normal error.
-func TempError(err error) error {
-	return tempErrorWrapper{err}
-}
-
-// Retry operation op until it succeeds according to the backoff
-// policy b.
-//
-// Note that this function reverses the error semantics of
-// backoff.Operation: all errors are permanent unless explicitly
-// marked as temporary (i.e. they have a Temporary() method that
-// returns true). This is to better align with the errors returned by
-// the net package.
-func Retry(op backoff.Operation, b backoff.BackOff) error {
-	innerOp := func() error {
-		err := op()
-		if err == nil {
-			return err
-		}
-		if tmpErr, ok := err.(tempError); ok && tmpErr.Temporary() {
-			return err
-		}
-		return backoff.Permanent(err)
-	}
-	return backoff.Retry(innerOp, b)
-}
-
-var errHTTPBackOff = TempError(errors.New("temporary http error"))
-
-func isStatusTemporary(code int) bool {
-	switch code {
-	case http.StatusTooManyRequests, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
-		return true
-	default:
-		return false
-	}
-}
-
-// RetryHTTPDo retries an HTTP request until it succeeds, according to
-// the backoff policy b. It will retry on temporary network errors and
-// upon receiving specific temporary HTTP errors. It will use the
-// context associated with the HTTP request object.
-func RetryHTTPDo(client *http.Client, req *http.Request, b backoff.BackOff) (*http.Response, error) {
-	var resp *http.Response
-	op := func() error {
-		// Clear up previous response if set.
-		if resp != nil {
-			resp.Body.Close()
-		}
-
-		var err error
-		resp, err = client.Do(req)
-		if err == nil && isStatusTemporary(resp.StatusCode) {
-			resp.Body.Close()
-			return errHTTPBackOff
-		}
-		return err
-	}
-
-	err := Retry(op, backoff.WithContext(b, req.Context()))
-	return resp, err
-}
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/track.go b/vendor/git.autistici.org/ai3/go-common/clientutil/track.go
new file mode 100644
index 0000000000000000000000000000000000000000..2db20bbbf4d79ce2377e6eb7781f5c9b65567492
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/track.go
@@ -0,0 +1,123 @@
+package clientutil
+
+import (
+	"math/rand"
+	"sync"
+	"time"
+)
+
+// The backendTracker tracks the state of the targets associated with
+// a backend, and periodically checks DNS for updates.
+type backendTracker struct {
+	log      logger
+	addr     string
+	resolver resolver
+	stopCh   chan struct{}
+
+	mx       sync.Mutex
+	resolved []string
+	failed   map[string]time.Time
+}
+
+func newBackendTracker(addr string, resolver resolver, logger logger) *backendTracker {
+	// Resolve the targets once before returning.
+	b := &backendTracker{
+		addr:     addr,
+		resolver: resolver,
+		resolved: resolver.ResolveIP(addr),
+		failed:   make(map[string]time.Time),
+		stopCh:   make(chan struct{}),
+		log:      logger,
+	}
+	go b.updateProc()
+	return b
+}
+
+func (b *backendTracker) Close() {
+	close(b.stopCh)
+}
+
+// Return the full list of targets in reverse preference order.
+func (b *backendTracker) getTargets() []string {
+	b.mx.Lock()
+	defer b.mx.Unlock()
+
+	var good, bad []string
+	for _, t := range b.resolved {
+		if _, ok := b.failed[t]; ok {
+			bad = append(bad, t)
+		} else {
+			good = append(good, t)
+		}
+	}
+
+	good = shuffle(good)
+	bad = shuffle(bad)
+
+	return append(good, bad...)
+}
+
+func (b *backendTracker) setStatus(addr string, ok bool) {
+	b.mx.Lock()
+
+	_, isFailed := b.failed[addr]
+	if isFailed && ok {
+		b.log.Printf("target %s now ok", addr)
+		delete(b.failed, addr)
+	} else if !isFailed && !ok {
+		b.log.Printf("target %s failed", addr)
+		b.failed[addr] = time.Now()
+	}
+
+	b.mx.Unlock()
+}
+
+var (
+	backendUpdateInterval       = 60 * time.Second
+	backendFailureRetryInterval = 60 * time.Second
+)
+
+func (b *backendTracker) expireFailedTargets() {
+	b.mx.Lock()
+	now := time.Now()
+	for k, v := range b.failed {
+		if now.Sub(v) > backendFailureRetryInterval {
+			delete(b.failed, k)
+		}
+	}
+	b.mx.Unlock()
+}
+
+func (b *backendTracker) updateProc() {
+	tick := time.NewTicker(backendUpdateInterval)
+	defer tick.Stop()
+	for {
+		select {
+		case <-b.stopCh:
+			return
+		case <-tick.C:
+			b.expireFailedTargets()
+			resolved := b.resolver.ResolveIP(b.addr)
+			if len(resolved) > 0 {
+				b.mx.Lock()
+				b.resolved = resolved
+				b.mx.Unlock()
+			}
+		}
+	}
+}
+
+var shuffleSrc = rand.NewSource(time.Now().UnixNano())
+
+// Re-order elements of a slice randomly.
+func shuffle(values []string) []string {
+	if len(values) < 2 {
+		return values
+	}
+	rnd := rand.New(shuffleSrc)
+	for i := len(values) - 1; i > 0; i-- {
+		j := rnd.Intn(i + 1)
+		values[i], values[j] = values[j], values[i]
+	}
+	return values
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/transport.go b/vendor/git.autistici.org/ai3/go-common/clientutil/transport.go
index e4f98e3f60ccbf214ff10db1b2860bb6bb1d8ed0..843a760b1e25eb1c21b2c8552b9c6ad107ea6d34 100644
--- a/vendor/git.autistici.org/ai3/go-common/clientutil/transport.go
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/transport.go
@@ -3,170 +3,63 @@ package clientutil
 import (
 	"context"
 	"crypto/tls"
-	"errors"
-	"log"
 	"net"
 	"net/http"
 	"sync"
 	"time"
 )
 
-var errAllBackendsFailed = errors.New("all backends failed")
-
-type dnsResolver struct{}
-
-func (r *dnsResolver) ResolveIPs(hosts []string) []string {
-	var resolved []string
-	for _, hostport := range hosts {
-		host, port, err := net.SplitHostPort(hostport)
-		if err != nil {
-			log.Printf("error parsing %s: %v", hostport, err)
-			continue
-		}
-		hostIPs, err := net.LookupIP(host)
-		if err != nil {
-			log.Printf("error resolving %s: %v", host, err)
-			continue
-		}
-		for _, ip := range hostIPs {
-			resolved = append(resolved, net.JoinHostPort(ip.String(), port))
-		}
-	}
-	return resolved
-}
-
-var defaultResolver = &dnsResolver{}
-
-type resolver interface {
-	ResolveIPs([]string) []string
-}
-
-// Balancer for HTTP connections. It will round-robin across available
-// backends, trying to avoid ones that are erroring out, until one
-// succeeds or they all fail.
+// The transportCache is just a cache of http transports, each
+// connecting to a specific address.
 //
-// This object should not be used for load balancing of individual
-// HTTP requests: once a new connection is established, requests will
-// be sent over it until it errors out. It's meant to provide a
-// *reliable* connection to a set of equivalent backends for HA
-// purposes.
-type balancer struct {
-	hosts    []string
-	resolver resolver
-	stop     chan bool
+// We use this to control the HTTP Host header and the TLS ServerName
+// independently of the target address.
+type transportCache struct {
+	tlsConfig *tls.Config
 
-	// List of currently valid (or untested) backends, and ones
-	// that errored out at least once.
-	mx    sync.Mutex
-	addrs []string
-	ok    map[string]bool
+	mx         sync.RWMutex
+	transports map[string]http.RoundTripper
 }
 
-var backendUpdateInterval = 60 * time.Second
+func newTransportCache(tlsConfig *tls.Config) *transportCache {
+	return &transportCache{
+		tlsConfig:  tlsConfig,
+		transports: make(map[string]http.RoundTripper),
+	}
+}
 
-// Periodically update the list of available backends.
-func (b *balancer) updateProc() {
-	tick := time.NewTicker(backendUpdateInterval)
-	for {
-		select {
-		case <-b.stop:
-			return
-		case <-tick.C:
-			resolved := b.resolver.ResolveIPs(b.hosts)
-			if len(resolved) > 0 {
-				b.mx.Lock()
-				b.addrs = resolved
-				b.mx.Unlock()
-			}
-		}
+func (m *transportCache) newTransport(addr string) http.RoundTripper {
+	return &http.Transport{
+		TLSClientConfig: m.tlsConfig,
+		DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
+			return netDialContext(ctx, network, addr)
+		},
 	}
 }
 
-// Returns a list of all available backends, split into "good ones"
-// (no errors seen since last successful connection) and "bad ones".
-func (b *balancer) getBackends() ([]string, []string) {
-	b.mx.Lock()
-	defer b.mx.Unlock()
+func (m *transportCache) getTransport(addr string) http.RoundTripper {
+	m.mx.RLock()
+	t, ok := m.transports[addr]
+	m.mx.RUnlock()
 
-	var good, bad []string
-	for _, addr := range b.addrs {
-		if ok := b.ok[addr]; ok {
-			good = append(good, addr)
-		} else {
-			bad = append(bad, addr)
+	if !ok {
+		m.mx.Lock()
+		if t, ok = m.transports[addr]; !ok {
+			t = m.newTransport(addr)
+			m.transports[addr] = t
 		}
+		m.mx.Unlock()
 	}
-	return good, bad
-}
 
-func (b *balancer) notify(addr string, ok bool) {
-	b.mx.Lock()
-	b.ok[addr] = ok
-	b.mx.Unlock()
+	return t
 }
 
+// Go < 1.9 does not have net.DialContext, reimplement it in terms of
+// net.DialTimeout.
 func netDialContext(ctx context.Context, network, addr string) (net.Conn, error) {
-	timeout := 30 * time.Second
-	// Go < 1.9 does not have net.DialContext, reimplement it in
-	// terms of net.DialTimeout.
+	timeout := 60 * time.Second // some arbitrary max timeout
 	if deadline, ok := ctx.Deadline(); ok {
 		timeout = time.Until(deadline)
 	}
 	return net.DialTimeout(network, addr, timeout)
 }
-
-func (b *balancer) dial(ctx context.Context, network, addr string) (net.Conn, error) {
-	// Start by attempting a connection on 'good' targets.
-	good, bad := b.getBackends()
-
-	for _, addr := range good {
-		// Go < 1.9 does not have DialContext, deal with it
-		conn, err := netDialContext(ctx, network, addr)
-		if err == nil {
-			return conn, nil
-		} else if err == context.Canceled {
-			// A timeout might be bad, set the error bit
-			// on the connection.
-			b.notify(addr, false)
-			return nil, err
-		}
-		b.notify(addr, false)
-	}
-
-	for _, addr := range bad {
-		conn, err := netDialContext(ctx, network, addr)
-		if err == nil {
-			b.notify(addr, true)
-			return conn, nil
-		} else if err == context.Canceled {
-			return nil, err
-		}
-	}
-
-	return nil, errAllBackendsFailed
-}
-
-// NewTransport returns a suitably configured http.RoundTripper that
-// talks to a specific backend service. It performs discovery of
-// available backends via DNS (using A or AAAA record lookups), tries
-// to route traffic away from faulty backends.
-//
-// It will periodically attempt to rediscover new backends.
-func NewTransport(backends []string, tlsConf *tls.Config, resolver resolver) http.RoundTripper {
-	if resolver == nil {
-		resolver = defaultResolver
-	}
-	addrs := resolver.ResolveIPs(backends)
-	b := &balancer{
-		hosts:    backends,
-		resolver: resolver,
-		addrs:    addrs,
-		ok:       make(map[string]bool),
-	}
-	go b.updateProc()
-
-	return &http.Transport{
-		DialContext:     b.dial,
-		TLSClientConfig: tlsConf,
-	}
-}
diff --git a/vendor/git.autistici.org/ai3/go-common/pwtool b/vendor/git.autistici.org/ai3/go-common/pwtool
deleted file mode 100755
index 12ae67693b6dd6b345e4517959d0ca9137c48c9d..0000000000000000000000000000000000000000
Binary files a/vendor/git.autistici.org/ai3/go-common/pwtool and /dev/null differ
diff --git a/vendor/git.autistici.org/ai3/replds/client.go b/vendor/git.autistici.org/ai3/replds/client.go
index 331b17544a117b83fc52bb2375ad5573c1aa0332..343dc38698e65b478083d412e3aa4cbb0c18448b 100644
--- a/vendor/git.autistici.org/ai3/replds/client.go
+++ b/vendor/git.autistici.org/ai3/replds/client.go
@@ -31,17 +31,17 @@ func newClient(config *clientutil.BackendConfig) (*client, error) {
 
 func (c *client) internalGetNodes(ctx context.Context, req *internalGetNodesRequest) (*internalGetNodesResponse, error) {
 	var resp internalGetNodesResponse
-	err := clientutil.DoJSONHTTPRequest(ctx, c.be.Client(""), c.be.URL("")+"/api/internal/get_nodes", req, &resp)
+	err := c.be.Call(ctx, "", "/api/internal/get_nodes", req, &resp)
 	return &resp, err
 }
 
 func (c *client) internalUpdateNodes(ctx context.Context, req *internalUpdateNodesRequest) error {
-	return clientutil.DoJSONHTTPRequest(ctx, c.be.Client(""), c.be.URL("")+"/api/internal/update_nodes", req, nil)
+	return c.be.Call(ctx, "", "/api/internal/update_nodes", req, nil)
 }
 
 func (c *client) SetNodes(ctx context.Context, req *SetNodesRequest) (*SetNodesResponse, error) {
 	var resp SetNodesResponse
-	err := clientutil.DoJSONHTTPRequest(ctx, c.be.Client(""), c.be.URL("")+"/api/set_nodes", req, &resp)
+	err := c.be.Call(ctx, "", "/api/set_nodes", req, &resp)
 	return &resp, err
 }
 
diff --git a/vendor/git.autistici.org/ai3/replds/server.go b/vendor/git.autistici.org/ai3/replds/server.go
index f7df02c39b1b267417c1e0fab6fa01a8856ca8c7..e3782ba8ff2972c1558bf586884057625668045d 100644
--- a/vendor/git.autistici.org/ai3/replds/server.go
+++ b/vendor/git.autistici.org/ai3/replds/server.go
@@ -21,7 +21,7 @@ var (
 	pollPeriod = 120 * time.Second
 
 	// Timeout for InternalGetNodes requests.
-	getNodesTimeout = 60 * time.Second
+	getNodesTimeout = 20 * time.Second
 )
 
 // Node is an annotated path/value entry.
diff --git a/vendor/github.com/cenkalti/backoff/README.md b/vendor/github.com/cenkalti/backoff/README.md
index 13b347fb95179f97b99d9f9224211e0159ed1c8c..55ebc98fc25faff08bf95f6a7f9d6a71ea652a35 100644
--- a/vendor/github.com/cenkalti/backoff/README.md
+++ b/vendor/github.com/cenkalti/backoff/README.md
@@ -24,7 +24,7 @@ See https://godoc.org/github.com/cenkalti/backoff#pkg-examples
 [coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
 [coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
 
-[google-http-java-client]: https://github.com/google/google-http-java-client
+[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
 [exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
 
 [advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_
diff --git a/vendor/github.com/cenkalti/backoff/context.go b/vendor/github.com/cenkalti/backoff/context.go
index 5d157092544fdbc8225327191883c46876faab94..d7005522942c3b5c5b2ec45735a4e106add8041b 100644
--- a/vendor/github.com/cenkalti/backoff/context.go
+++ b/vendor/github.com/cenkalti/backoff/context.go
@@ -1,9 +1,8 @@
 package backoff
 
 import (
+	"context"
 	"time"
-
-	"golang.org/x/net/context"
 )
 
 // BackOffContext is a backoff policy that stops retrying after the context
diff --git a/vendor/github.com/cenkalti/backoff/retry.go b/vendor/github.com/cenkalti/backoff/retry.go
index 5dbd825b5c8b5761dcb613d198ea9662b761b1a7..e65cc700de71f561a5939c3577c637074a316444 100644
--- a/vendor/github.com/cenkalti/backoff/retry.go
+++ b/vendor/github.com/cenkalti/backoff/retry.go
@@ -15,7 +15,6 @@ type Notify func(error, time.Duration)
 
 // Retry the operation o until it does not return error or BackOff stops.
 // o is guaranteed to be run at least once.
-// It is the caller's responsibility to reset b after Retry returns.
 //
 // If o returns a *PermanentError, the operation is not retried, and the
 // wrapped error is returned.
diff --git a/vendor/github.com/cenkalti/backoff/ticker.go b/vendor/github.com/cenkalti/backoff/ticker.go
index e742512fd3a83f04e560dd8438e1048366fc9821..e41084b0eff94364e0c40333dede3f1594b46207 100644
--- a/vendor/github.com/cenkalti/backoff/ticker.go
+++ b/vendor/github.com/cenkalti/backoff/ticker.go
@@ -1,7 +1,6 @@
 package backoff
 
 import (
-	"runtime"
 	"sync"
 	"time"
 )
@@ -34,7 +33,6 @@ func NewTicker(b BackOff) *Ticker {
 	}
 	t.b.Reset()
 	go t.run()
-	runtime.SetFinalizer(t, (*Ticker).Stop)
 	return t
 }
 
diff --git a/vendor/github.com/cenkalti/backoff/tries.go b/vendor/github.com/cenkalti/backoff/tries.go
index d2da7308b6aa99813b1a895f0c6f49b1af6764a2..cfeefd9b764c4272f518e7db3331c31a35d84834 100644
--- a/vendor/github.com/cenkalti/backoff/tries.go
+++ b/vendor/github.com/cenkalti/backoff/tries.go
@@ -3,13 +3,13 @@ package backoff
 import "time"
 
 /*
-WithMaxTries creates a wrapper around another BackOff, which will
+WithMaxRetries creates a wrapper around another BackOff, which will
 return Stop if NextBackOff() has been called too many times since
 the last time Reset() was called
 
 Note: Implementation is not thread-safe.
 */
-func WithMaxTries(b BackOff, max uint64) BackOff {
+func WithMaxRetries(b BackOff, max uint64) BackOff {
 	return &backOffTries{delegate: b, maxTries: max}
 }
 
diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e2e0651a934d3ab8fe6393dfd2556bbc4bd0792e
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/Makefile
@@ -0,0 +1,43 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors.  All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+install:
+	go install
+
+test: install generate-test-pbs
+	go test
+
+
+generate-test-pbs:
+	make install
+	make -C testdata
+	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
+	make
diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go
index 3cd3249f706241d57b2b79f36de043bfac488449..e392575b353afa4f22f513d3f22ff64a8f5fdbf1 100644
--- a/vendor/github.com/golang/protobuf/proto/clone.go
+++ b/vendor/github.com/golang/protobuf/proto/clone.go
@@ -35,39 +35,22 @@
 package proto
 
 import (
-	"fmt"
 	"log"
 	"reflect"
 	"strings"
 )
 
 // Clone returns a deep copy of a protocol buffer.
-func Clone(src Message) Message {
-	in := reflect.ValueOf(src)
+func Clone(pb Message) Message {
+	in := reflect.ValueOf(pb)
 	if in.IsNil() {
-		return src
+		return pb
 	}
-	out := reflect.New(in.Type().Elem())
-	dst := out.Interface().(Message)
-	Merge(dst, src)
-	return dst
-}
 
-// Merger is the interface representing objects that can merge messages of the same type.
-type Merger interface {
-	// Merge merges src into this message.
-	// Required and optional fields that are set in src will be set to that value in dst.
-	// Elements of repeated fields will be appended.
-	//
-	// Merge may panic if called with a different argument type than the receiver.
-	Merge(src Message)
-}
-
-// generatedMerger is the custom merge method that generated protos will have.
-// We must add this method since a generate Merge method will conflict with
-// many existing protos that have a Merge data field already defined.
-type generatedMerger interface {
-	XXX_Merge(src Message)
+	out := reflect.New(in.Type().Elem())
+	// out is empty so a merge is a deep copy.
+	mergeStruct(out.Elem(), in.Elem())
+	return out.Interface().(Message)
 }
 
 // Merge merges src into dst.
@@ -75,24 +58,17 @@ type generatedMerger interface {
 // Elements of repeated fields will be appended.
 // Merge panics if src and dst are not the same type, or if dst is nil.
 func Merge(dst, src Message) {
-	if m, ok := dst.(Merger); ok {
-		m.Merge(src)
-		return
-	}
-
 	in := reflect.ValueOf(src)
 	out := reflect.ValueOf(dst)
 	if out.IsNil() {
 		panic("proto: nil destination")
 	}
 	if in.Type() != out.Type() {
-		panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
+		// Explicit test prior to mergeStruct so that mistyped nils will fail
+		panic("proto: type mismatch")
 	}
 	if in.IsNil() {
-		return // Merge from nil src is a noop
-	}
-	if m, ok := dst.(generatedMerger); ok {
-		m.XXX_Merge(src)
+		// Merging nil into non-nil is a quiet no-op
 		return
 	}
 	mergeStruct(out.Elem(), in.Elem())
@@ -108,7 +84,7 @@ func mergeStruct(out, in reflect.Value) {
 		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 	}
 
-	if emIn, err := extendable(in.Addr().Interface()); err == nil {
+	if emIn, ok := extendable(in.Addr().Interface()); ok {
 		emOut, _ := extendable(out.Addr().Interface())
 		mIn, muIn := emIn.extensionsRead()
 		if mIn != nil {
diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go
index d9aa3c42d666ec2503c322d567c035a0a884ee24..aa207298f997665117f3ba88e65646f95c83f08a 100644
--- a/vendor/github.com/golang/protobuf/proto/decode.go
+++ b/vendor/github.com/golang/protobuf/proto/decode.go
@@ -39,6 +39,8 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"os"
+	"reflect"
 )
 
 // errOverflow is returned when an integer is too large to be represented.
@@ -48,6 +50,10 @@ var errOverflow = errors.New("proto: integer overflow")
 // wire type is encountered. It does not get returned to user code.
 var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
 
+// The fundamental decoders that interpret bytes on the wire.
+// Those that take integer types all return uint64 and are
+// therefore of type valueDecoder.
+
 // DecodeVarint reads a varint-encoded integer from the slice.
 // It returns the integer and the number of bytes consumed, or
 // zero if there is not enough.
@@ -261,6 +267,9 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
 	return
 }
 
+// These are not ValueDecoders: they produce an array of bytes or a string.
+// bytes, embedded messages
+
 // DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
 // This is the format used for the bytes protocol buffer
 // type and for embedded messages.
@@ -302,29 +311,81 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
 	return string(buf), nil
 }
 
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+// If the protocol buffer has extensions, and the field matches, add it as an extension.
+// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
+	oi := o.index
+
+	err := o.skip(t, tag, wire)
+	if err != nil {
+		return err
+	}
+
+	if !unrecField.IsValid() {
+		return nil
+	}
+
+	ptr := structPointer_Bytes(base, unrecField)
+
+	// Add the skipped field to struct field
+	obuf := o.buf
+
+	o.buf = *ptr
+	o.EncodeVarint(uint64(tag<<3 | wire))
+	*ptr = append(o.buf, obuf[oi:o.index]...)
+
+	o.buf = obuf
+
+	return nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
+
+	var u uint64
+	var err error
+
+	switch wire {
+	case WireVarint:
+		_, err = o.DecodeVarint()
+	case WireFixed64:
+		_, err = o.DecodeFixed64()
+	case WireBytes:
+		_, err = o.DecodeRawBytes(false)
+	case WireFixed32:
+		_, err = o.DecodeFixed32()
+	case WireStartGroup:
+		for {
+			u, err = o.DecodeVarint()
+			if err != nil {
+				break
+			}
+			fwire := int(u & 0x7)
+			if fwire == WireEndGroup {
+				break
+			}
+			ftag := int(u >> 3)
+			err = o.skip(t, ftag, fwire)
+			if err != nil {
+				break
+			}
+		}
+	default:
+		err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
+	}
+	return err
+}
+
 // Unmarshaler is the interface representing objects that can
-// unmarshal themselves.  The argument points to data that may be
+// unmarshal themselves.  The method should reset the receiver before
+// decoding starts.  The argument points to data that may be
 // overwritten, so implementations should not keep references to the
 // buffer.
-// Unmarshal implementations should not clear the receiver.
-// Any unmarshaled data should be merged into the receiver.
-// Callers of Unmarshal that do not want to retain existing data
-// should Reset the receiver before calling Unmarshal.
 type Unmarshaler interface {
 	Unmarshal([]byte) error
 }
 
-// newUnmarshaler is the interface representing objects that can
-// unmarshal themselves. The semantics are identical to Unmarshaler.
-//
-// This exists to support protoc-gen-go generated messages.
-// The proto package will stop type-asserting to this interface in the future.
-//
-// DO NOT DEPEND ON THIS.
-type newUnmarshaler interface {
-	XXX_Unmarshal([]byte) error
-}
-
 // Unmarshal parses the protocol buffer representation in buf and places the
 // decoded result in pb.  If the struct underlying pb does not match
 // the data in buf, the results can be unpredictable.
@@ -334,13 +395,7 @@ type newUnmarshaler interface {
 // to preserve and append to existing data.
 func Unmarshal(buf []byte, pb Message) error {
 	pb.Reset()
-	if u, ok := pb.(newUnmarshaler); ok {
-		return u.XXX_Unmarshal(buf)
-	}
-	if u, ok := pb.(Unmarshaler); ok {
-		return u.Unmarshal(buf)
-	}
-	return NewBuffer(buf).Unmarshal(pb)
+	return UnmarshalMerge(buf, pb)
 }
 
 // UnmarshalMerge parses the protocol buffer representation in buf and
@@ -350,16 +405,8 @@ func Unmarshal(buf []byte, pb Message) error {
 // UnmarshalMerge merges into existing data in pb.
 // Most code should use Unmarshal instead.
 func UnmarshalMerge(buf []byte, pb Message) error {
-	if u, ok := pb.(newUnmarshaler); ok {
-		return u.XXX_Unmarshal(buf)
-	}
+	// If the object can unmarshal itself, let it.
 	if u, ok := pb.(Unmarshaler); ok {
-		// NOTE: The history of proto have unfortunately been inconsistent
-		// whether Unmarshaler should or should not implicitly clear itself.
-		// Some implementations do, most do not.
-		// Thus, calling this here may or may not do what people want.
-		//
-		// See https://github.com/golang/protobuf/issues/424
 		return u.Unmarshal(buf)
 	}
 	return NewBuffer(buf).Unmarshal(pb)
@@ -375,17 +422,12 @@ func (p *Buffer) DecodeMessage(pb Message) error {
 }
 
 // DecodeGroup reads a tag-delimited group from the Buffer.
-// StartGroup tag is already consumed. This function consumes
-// EndGroup tag.
 func (p *Buffer) DecodeGroup(pb Message) error {
-	b := p.buf[p.index:]
-	x, y := findEndGroup(b)
-	if x < 0 {
-		return io.ErrUnexpectedEOF
+	typ, base, err := getbase(pb)
+	if err != nil {
+		return err
 	}
-	err := Unmarshal(b[:x], pb)
-	p.index += y
-	return err
+	return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
 }
 
 // Unmarshal parses the protocol buffer representation in the
@@ -396,33 +438,533 @@ func (p *Buffer) DecodeGroup(pb Message) error {
 // Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
 func (p *Buffer) Unmarshal(pb Message) error {
 	// If the object can unmarshal itself, let it.
-	if u, ok := pb.(newUnmarshaler); ok {
-		err := u.XXX_Unmarshal(p.buf[p.index:])
-		p.index = len(p.buf)
-		return err
-	}
 	if u, ok := pb.(Unmarshaler); ok {
-		// NOTE: The history of proto have unfortunately been inconsistent
-		// whether Unmarshaler should or should not implicitly clear itself.
-		// Some implementations do, most do not.
-		// Thus, calling this here may or may not do what people want.
-		//
-		// See https://github.com/golang/protobuf/issues/424
 		err := u.Unmarshal(p.buf[p.index:])
 		p.index = len(p.buf)
 		return err
 	}
 
-	// Slow workaround for messages that aren't Unmarshalers.
-	// This includes some hand-coded .pb.go files and
-	// bootstrap protos.
-	// TODO: fix all of those and then add Unmarshal to
-	// the Message interface. Then:
-	// The cast above and code below can be deleted.
-	// The old unmarshaler can be deleted.
-	// Clients can call Unmarshal directly (can already do that, actually).
-	var info InternalMessageInfo
-	err := info.Unmarshal(pb, p.buf[p.index:])
-	p.index = len(p.buf)
+	typ, base, err := getbase(pb)
+	if err != nil {
+		return err
+	}
+
+	err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
+
+	if collectStats {
+		stats.Decode++
+	}
+
+	return err
+}
+
+// unmarshalType does the work of unmarshaling a structure.
+func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
+	var state errorState
+	required, reqFields := prop.reqCount, uint64(0)
+
+	var err error
+	for err == nil && o.index < len(o.buf) {
+		oi := o.index
+		var u uint64
+		u, err = o.DecodeVarint()
+		if err != nil {
+			break
+		}
+		wire := int(u & 0x7)
+		if wire == WireEndGroup {
+			if is_group {
+				if required > 0 {
+					// Not enough information to determine the exact field.
+					// (See below.)
+					return &RequiredNotSetError{"{Unknown}"}
+				}
+				return nil // input is satisfied
+			}
+			return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
+		}
+		tag := int(u >> 3)
+		if tag <= 0 {
+			return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
+		}
+		fieldnum, ok := prop.decoderTags.get(tag)
+		if !ok {
+			// Maybe it's an extension?
+			if prop.extendable {
+				if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
+					if err = o.skip(st, tag, wire); err == nil {
+						extmap := e.extensionsWrite()
+						ext := extmap[int32(tag)] // may be missing
+						ext.enc = append(ext.enc, o.buf[oi:o.index]...)
+						extmap[int32(tag)] = ext
+					}
+					continue
+				}
+			}
+			// Maybe it's a oneof?
+			if prop.oneofUnmarshaler != nil {
+				m := structPointer_Interface(base, st).(Message)
+				// First return value indicates whether tag is a oneof field.
+				ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+				if err == ErrInternalBadWireType {
+					// Map the error to something more descriptive.
+					// Do the formatting here to save generated code space.
+					err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+				}
+				if ok {
+					continue
+				}
+			}
+			err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
+			continue
+		}
+		p := prop.Prop[fieldnum]
+
+		if p.dec == nil {
+			fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
+			continue
+		}
+		dec := p.dec
+		if wire != WireStartGroup && wire != p.WireType {
+			if wire == WireBytes && p.packedDec != nil {
+				// a packable field
+				dec = p.packedDec
+			} else {
+				err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
+				continue
+			}
+		}
+		decErr := dec(o, p, base)
+		if decErr != nil && !state.shouldContinue(decErr, p) {
+			err = decErr
+		}
+		if err == nil && p.Required {
+			// Successfully decoded a required field.
+			if tag <= 64 {
+				// use bitmap for fields 1-64 to catch field reuse.
+				var mask uint64 = 1 << uint64(tag-1)
+				if reqFields&mask == 0 {
+					// new required field
+					reqFields |= mask
+					required--
+				}
+			} else {
+				// This is imprecise. It can be fooled by a required field
+				// with a tag > 64 that is encoded twice; that's very rare.
+				// A fully correct implementation would require allocating
+				// a data structure, which we would like to avoid.
+				required--
+			}
+		}
+	}
+	if err == nil {
+		if is_group {
+			return io.ErrUnexpectedEOF
+		}
+		if state.err != nil {
+			return state.err
+		}
+		if required > 0 {
+			// Not enough information to determine the exact field. If we use extra
+			// CPU, we could determine the field only if the missing required field
+			// has a tag <= 64 and we check reqFields.
+			return &RequiredNotSetError{"{Unknown}"}
+		}
+	}
+	return err
+}
+
+// Individual type decoders
+// For each,
+//	u is the decoded value,
+//	v is a pointer to the field (pointer) in the struct
+
+// Sizes of the pools to allocate inside the Buffer.
+// The goal is modest amortization and allocation
+// on at least 16-byte boundaries.
+const (
+	boolPoolSize   = 16
+	uint32PoolSize = 8
+	uint64PoolSize = 4
+)
+
+// Decode a bool.
+func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	if len(o.bools) == 0 {
+		o.bools = make([]bool, boolPoolSize)
+	}
+	o.bools[0] = u != 0
+	*structPointer_Bool(base, p.field) = &o.bools[0]
+	o.bools = o.bools[1:]
+	return nil
+}
+
+func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	*structPointer_BoolVal(base, p.field) = u != 0
+	return nil
+}
+
+// Decode an int32.
+func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
+	return nil
+}
+
+func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
+	return nil
+}
+
+// Decode an int64.
+func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	word64_Set(structPointer_Word64(base, p.field), o, u)
+	return nil
+}
+
+func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
+	return nil
+}
+
+// Decode a string.
+func (o *Buffer) dec_string(p *Properties, base structPointer) error {
+	s, err := o.DecodeStringBytes()
+	if err != nil {
+		return err
+	}
+	*structPointer_String(base, p.field) = &s
+	return nil
+}
+
+func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
+	s, err := o.DecodeStringBytes()
+	if err != nil {
+		return err
+	}
+	*structPointer_StringVal(base, p.field) = s
+	return nil
+}
+
+// Decode a slice of bytes ([]byte).
+func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
+	b, err := o.DecodeRawBytes(true)
+	if err != nil {
+		return err
+	}
+	*structPointer_Bytes(base, p.field) = b
+	return nil
+}
+
+// Decode a slice of bools ([]bool).
+func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	v := structPointer_BoolSlice(base, p.field)
+	*v = append(*v, u != 0)
+	return nil
+}
+
+// Decode a slice of bools ([]bool) in packed format.
+func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
+	v := structPointer_BoolSlice(base, p.field)
+
+	nn, err := o.DecodeVarint()
+	if err != nil {
+		return err
+	}
+	nb := int(nn) // number of bytes of encoded bools
+	fin := o.index + nb
+	if fin < o.index {
+		return errOverflow
+	}
+
+	y := *v
+	for o.index < fin {
+		u, err := p.valDec(o)
+		if err != nil {
+			return err
+		}
+		y = append(y, u != 0)
+	}
+
+	*v = y
+	return nil
+}
+
+// Decode a slice of int32s ([]int32).
+func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+	structPointer_Word32Slice(base, p.field).Append(uint32(u))
+	return nil
+}
+
+// Decode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
+	v := structPointer_Word32Slice(base, p.field)
+
+	nn, err := o.DecodeVarint()
+	if err != nil {
+		return err
+	}
+	nb := int(nn) // number of bytes of encoded int32s
+
+	fin := o.index + nb
+	if fin < o.index {
+		return errOverflow
+	}
+	for o.index < fin {
+		u, err := p.valDec(o)
+		if err != nil {
+			return err
+		}
+		v.Append(uint32(u))
+	}
+	return nil
+}
+
+// Decode a slice of int64s ([]int64).
+func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
+	u, err := p.valDec(o)
+	if err != nil {
+		return err
+	}
+
+	structPointer_Word64Slice(base, p.field).Append(u)
+	return nil
+}
+
+// Decode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
+	v := structPointer_Word64Slice(base, p.field)
+
+	nn, err := o.DecodeVarint()
+	if err != nil {
+		return err
+	}
+	nb := int(nn) // number of bytes of encoded int64s
+
+	fin := o.index + nb
+	if fin < o.index {
+		return errOverflow
+	}
+	for o.index < fin {
+		u, err := p.valDec(o)
+		if err != nil {
+			return err
+		}
+		v.Append(u)
+	}
+	return nil
+}
+
+// Decode a slice of strings ([]string).
+func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
+	s, err := o.DecodeStringBytes()
+	if err != nil {
+		return err
+	}
+	v := structPointer_StringSlice(base, p.field)
+	*v = append(*v, s)
+	return nil
+}
+
+// Decode a slice of slice of bytes ([][]byte).
+func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
+	b, err := o.DecodeRawBytes(true)
+	if err != nil {
+		return err
+	}
+	v := structPointer_BytesSlice(base, p.field)
+	*v = append(*v, b)
+	return nil
+}
+
+// Decode a map field.
+func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
+	raw, err := o.DecodeRawBytes(false)
+	if err != nil {
+		return err
+	}
+	oi := o.index       // index at the end of this map entry
+	o.index -= len(raw) // move buffer back to start of map entry
+
+	mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
+	if mptr.Elem().IsNil() {
+		mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
+	}
+	v := mptr.Elem() // map[K]V
+
+	// Prepare addressable doubly-indirect placeholders for the key and value types.
+	// See enc_new_map for why.
+	keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
+	keybase := toStructPointer(keyptr.Addr())                  // **K
+
+	var valbase structPointer
+	var valptr reflect.Value
+	switch p.mtype.Elem().Kind() {
+	case reflect.Slice:
+		// []byte
+		var dummy []byte
+		valptr = reflect.ValueOf(&dummy)  // *[]byte
+		valbase = toStructPointer(valptr) // *[]byte
+	case reflect.Ptr:
+		// message; valptr is **Msg; need to allocate the intermediate pointer
+		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+		valptr.Set(reflect.New(valptr.Type().Elem()))
+		valbase = toStructPointer(valptr)
+	default:
+		// everything else
+		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+		valbase = toStructPointer(valptr.Addr())                   // **V
+	}
+
+	// Decode.
+	// This parses a restricted wire format, namely the encoding of a message
+	// with two fields. See enc_new_map for the format.
+	for o.index < oi {
+		// tagcode for key and value properties are always a single byte
+		// because they have tags 1 and 2.
+		tagcode := o.buf[o.index]
+		o.index++
+		switch tagcode {
+		case p.mkeyprop.tagcode[0]:
+			if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
+				return err
+			}
+		case p.mvalprop.tagcode[0]:
+			if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
+				return err
+			}
+		default:
+			// TODO: Should we silently skip this instead?
+			return fmt.Errorf("proto: bad map data tag %d", raw[0])
+		}
+	}
+	keyelem, valelem := keyptr.Elem(), valptr.Elem()
+	if !keyelem.IsValid() {
+		keyelem = reflect.Zero(p.mtype.Key())
+	}
+	if !valelem.IsValid() {
+		valelem = reflect.Zero(p.mtype.Elem())
+	}
+
+	v.SetMapIndex(keyelem, valelem)
+	return nil
+}
+
+// Decode a group.
+func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
+	bas := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(bas) {
+		// allocate new nested message
+		bas = toStructPointer(reflect.New(p.stype))
+		structPointer_SetStructPointer(base, p.field, bas)
+	}
+	return o.unmarshalType(p.stype, p.sprop, true, bas)
+}
+
+// Decode an embedded message.
+func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
+	raw, e := o.DecodeRawBytes(false)
+	if e != nil {
+		return e
+	}
+
+	bas := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(bas) {
+		// allocate new nested message
+		bas = toStructPointer(reflect.New(p.stype))
+		structPointer_SetStructPointer(base, p.field, bas)
+	}
+
+	// If the object can unmarshal itself, let it.
+	if p.isUnmarshaler {
+		iv := structPointer_Interface(bas, p.stype)
+		return iv.(Unmarshaler).Unmarshal(raw)
+	}
+
+	obuf := o.buf
+	oi := o.index
+	o.buf = raw
+	o.index = 0
+
+	err = o.unmarshalType(p.stype, p.sprop, false, bas)
+	o.buf = obuf
+	o.index = oi
+
+	return err
+}
+
+// Decode a slice of embedded messages.
+func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
+	return o.dec_slice_struct(p, false, base)
+}
+
+// Decode a slice of embedded groups.
+func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
+	return o.dec_slice_struct(p, true, base)
+}
+
+// Decode a slice of structs ([]*struct).
+func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
+	v := reflect.New(p.stype)
+	bas := toStructPointer(v)
+	structPointer_StructPointerSlice(base, p.field).Append(bas)
+
+	if is_group {
+		err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
+		return err
+	}
+
+	raw, err := o.DecodeRawBytes(false)
+	if err != nil {
+		return err
+	}
+
+	// If the object can unmarshal itself, let it.
+	if p.isUnmarshaler {
+		iv := v.Interface()
+		return iv.(Unmarshaler).Unmarshal(raw)
+	}
+
+	obuf := o.buf
+	oi := o.index
+	o.buf = raw
+	o.index = 0
+
+	err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
+
+	o.buf = obuf
+	o.index = oi
+
 	return err
 }
diff --git a/vendor/github.com/golang/protobuf/proto/discard.go b/vendor/github.com/golang/protobuf/proto/discard.go
deleted file mode 100644
index dea2617ced346ec98565c75713bbf71a0ffd0254..0000000000000000000000000000000000000000
--- a/vendor/github.com/golang/protobuf/proto/discard.go
+++ /dev/null
@@ -1,350 +0,0 @@
-// Go support for Protocol Buffers - Google's data interchange format
-//
-// Copyright 2017 The Go Authors.  All rights reserved.
-// https://github.com/golang/protobuf
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package proto
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-	"sync"
-	"sync/atomic"
-)
-
-type generatedDiscarder interface {
-	XXX_DiscardUnknown()
-}
-
-// DiscardUnknown recursively discards all unknown fields from this message
-// and all embedded messages.
-//
-// When unmarshaling a message with unrecognized fields, the tags and values
-// of such fields are preserved in the Message. This allows a later call to
-// marshal to be able to produce a message that continues to have those
-// unrecognized fields. To avoid this, DiscardUnknown is used to
-// explicitly clear the unknown fields after unmarshaling.
-//
-// For proto2 messages, the unknown fields of message extensions are only
-// discarded from messages that have been accessed via GetExtension.
-func DiscardUnknown(m Message) {
-	if m, ok := m.(generatedDiscarder); ok {
-		m.XXX_DiscardUnknown()
-		return
-	}
-	// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
-	// but the master branch has no implementation for InternalMessageInfo,
-	// so it would be more work to replicate that approach.
-	discardLegacy(m)
-}
-
-// DiscardUnknown recursively discards all unknown fields.
-func (a *InternalMessageInfo) DiscardUnknown(m Message) {
-	di := atomicLoadDiscardInfo(&a.discard)
-	if di == nil {
-		di = getDiscardInfo(reflect.TypeOf(m).Elem())
-		atomicStoreDiscardInfo(&a.discard, di)
-	}
-	di.discard(toPointer(&m))
-}
-
-type discardInfo struct {
-	typ reflect.Type
-
-	initialized int32 // 0: only typ is valid, 1: everything is valid
-	lock        sync.Mutex
-
-	fields       []discardFieldInfo
-	unrecognized field
-}
-
-type discardFieldInfo struct {
-	field   field // Offset of field, guaranteed to be valid
-	discard func(src pointer)
-}
-
-var (
-	discardInfoMap  = map[reflect.Type]*discardInfo{}
-	discardInfoLock sync.Mutex
-)
-
-func getDiscardInfo(t reflect.Type) *discardInfo {
-	discardInfoLock.Lock()
-	defer discardInfoLock.Unlock()
-	di := discardInfoMap[t]
-	if di == nil {
-		di = &discardInfo{typ: t}
-		discardInfoMap[t] = di
-	}
-	return di
-}
-
-func (di *discardInfo) discard(src pointer) {
-	if src.isNil() {
-		return // Nothing to do.
-	}
-
-	if atomic.LoadInt32(&di.initialized) == 0 {
-		di.computeDiscardInfo()
-	}
-
-	for _, fi := range di.fields {
-		sfp := src.offset(fi.field)
-		fi.discard(sfp)
-	}
-
-	// For proto2 messages, only discard unknown fields in message extensions
-	// that have been accessed via GetExtension.
-	if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
-		// Ignore lock since DiscardUnknown is not concurrency safe.
-		emm, _ := em.extensionsRead()
-		for _, mx := range emm {
-			if m, ok := mx.value.(Message); ok {
-				DiscardUnknown(m)
-			}
-		}
-	}
-
-	if di.unrecognized.IsValid() {
-		*src.offset(di.unrecognized).toBytes() = nil
-	}
-}
-
-func (di *discardInfo) computeDiscardInfo() {
-	di.lock.Lock()
-	defer di.lock.Unlock()
-	if di.initialized != 0 {
-		return
-	}
-	t := di.typ
-	n := t.NumField()
-
-	for i := 0; i < n; i++ {
-		f := t.Field(i)
-		if strings.HasPrefix(f.Name, "XXX_") {
-			continue
-		}
-
-		dfi := discardFieldInfo{field: toField(&f)}
-		tf := f.Type
-
-		// Unwrap tf to get its most basic type.
-		var isPointer, isSlice bool
-		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
-			isSlice = true
-			tf = tf.Elem()
-		}
-		if tf.Kind() == reflect.Ptr {
-			isPointer = true
-			tf = tf.Elem()
-		}
-		if isPointer && isSlice && tf.Kind() != reflect.Struct {
-			panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
-		}
-
-		switch tf.Kind() {
-		case reflect.Struct:
-			switch {
-			case !isPointer:
-				panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
-			case isSlice: // E.g., []*pb.T
-				di := getDiscardInfo(tf)
-				dfi.discard = func(src pointer) {
-					sps := src.getPointerSlice()
-					for _, sp := range sps {
-						if !sp.isNil() {
-							di.discard(sp)
-						}
-					}
-				}
-			default: // E.g., *pb.T
-				di := getDiscardInfo(tf)
-				dfi.discard = func(src pointer) {
-					sp := src.getPointer()
-					if !sp.isNil() {
-						di.discard(sp)
-					}
-				}
-			}
-		case reflect.Map:
-			switch {
-			case isPointer || isSlice:
-				panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
-			default: // E.g., map[K]V
-				if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
-					dfi.discard = func(src pointer) {
-						sm := src.asPointerTo(tf).Elem()
-						if sm.Len() == 0 {
-							return
-						}
-						for _, key := range sm.MapKeys() {
-							val := sm.MapIndex(key)
-							DiscardUnknown(val.Interface().(Message))
-						}
-					}
-				} else {
-					dfi.discard = func(pointer) {} // Noop
-				}
-			}
-		case reflect.Interface:
-			// Must be oneof field.
-			switch {
-			case isPointer || isSlice:
-				panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
-			default: // E.g., interface{}
-				// TODO: Make this faster?
-				dfi.discard = func(src pointer) {
-					su := src.asPointerTo(tf).Elem()
-					if !su.IsNil() {
-						sv := su.Elem().Elem().Field(0)
-						if sv.Kind() == reflect.Ptr && sv.IsNil() {
-							return
-						}
-						switch sv.Type().Kind() {
-						case reflect.Ptr: // Proto struct (e.g., *T)
-							DiscardUnknown(sv.Interface().(Message))
-						}
-					}
-				}
-			}
-		default:
-			continue
-		}
-		di.fields = append(di.fields, dfi)
-	}
-
-	di.unrecognized = invalidField
-	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
-		if f.Type != reflect.TypeOf([]byte{}) {
-			panic("expected XXX_unrecognized to be of type []byte")
-		}
-		di.unrecognized = toField(&f)
-	}
-
-	atomic.StoreInt32(&di.initialized, 1)
-}
-
-func discardLegacy(m Message) {
-	v := reflect.ValueOf(m)
-	if v.Kind() != reflect.Ptr || v.IsNil() {
-		return
-	}
-	v = v.Elem()
-	if v.Kind() != reflect.Struct {
-		return
-	}
-	t := v.Type()
-
-	for i := 0; i < v.NumField(); i++ {
-		f := t.Field(i)
-		if strings.HasPrefix(f.Name, "XXX_") {
-			continue
-		}
-		vf := v.Field(i)
-		tf := f.Type
-
-		// Unwrap tf to get its most basic type.
-		var isPointer, isSlice bool
-		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
-			isSlice = true
-			tf = tf.Elem()
-		}
-		if tf.Kind() == reflect.Ptr {
-			isPointer = true
-			tf = tf.Elem()
-		}
-		if isPointer && isSlice && tf.Kind() != reflect.Struct {
-			panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
-		}
-
-		switch tf.Kind() {
-		case reflect.Struct:
-			switch {
-			case !isPointer:
-				panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
-			case isSlice: // E.g., []*pb.T
-				for j := 0; j < vf.Len(); j++ {
-					discardLegacy(vf.Index(j).Interface().(Message))
-				}
-			default: // E.g., *pb.T
-				discardLegacy(vf.Interface().(Message))
-			}
-		case reflect.Map:
-			switch {
-			case isPointer || isSlice:
-				panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
-			default: // E.g., map[K]V
-				tv := vf.Type().Elem()
-				if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
-					for _, key := range vf.MapKeys() {
-						val := vf.MapIndex(key)
-						discardLegacy(val.Interface().(Message))
-					}
-				}
-			}
-		case reflect.Interface:
-			// Must be oneof field.
-			switch {
-			case isPointer || isSlice:
-				panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
-			default: // E.g., test_proto.isCommunique_Union interface
-				if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
-					vf = vf.Elem() // E.g., *test_proto.Communique_Msg
-					if !vf.IsNil() {
-						vf = vf.Elem()   // E.g., test_proto.Communique_Msg
-						vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
-						if vf.Kind() == reflect.Ptr {
-							discardLegacy(vf.Interface().(Message))
-						}
-					}
-				}
-			}
-		}
-	}
-
-	if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
-		if vf.Type() != reflect.TypeOf([]byte{}) {
-			panic("expected XXX_unrecognized to be of type []byte")
-		}
-		vf.Set(reflect.ValueOf([]byte(nil)))
-	}
-
-	// For proto2 messages, only discard unknown fields in message extensions
-	// that have been accessed via GetExtension.
-	if em, err := extendable(m); err == nil {
-		// Ignore lock since discardLegacy is not concurrency safe.
-		emm, _ := em.extensionsRead()
-		for _, mx := range emm {
-			if m, ok := mx.value.(Message); ok {
-				discardLegacy(m)
-			}
-		}
-	}
-}
diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go
index c27d35f866bb0b6a72bc895de19461146ae44b21..8b84d1b22d4c0933820cb4872e29c918e5429be2 100644
--- a/vendor/github.com/golang/protobuf/proto/encode.go
+++ b/vendor/github.com/golang/protobuf/proto/encode.go
@@ -39,6 +39,7 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
+	"sort"
 )
 
 // RequiredNotSetError is the error returned if Marshal is called with
@@ -81,6 +82,10 @@ var (
 
 const maxVarintBytes = 10 // maximum length of a varint
 
+// maxMarshalSize is the largest allowed size of an encoded protobuf,
+// since C++ and Java use signed int32s for the size.
+const maxMarshalSize = 1<<31 - 1
+
 // EncodeVarint returns the varint encoding of x.
 // This is the format for the
 // int32, int64, uint32, uint64, bool, and enum
@@ -114,27 +119,18 @@ func (p *Buffer) EncodeVarint(x uint64) error {
 
 // SizeVarint returns the varint encoding size of an integer.
 func SizeVarint(x uint64) int {
-	switch {
-	case x < 1<<7:
-		return 1
-	case x < 1<<14:
-		return 2
-	case x < 1<<21:
-		return 3
-	case x < 1<<28:
-		return 4
-	case x < 1<<35:
-		return 5
-	case x < 1<<42:
-		return 6
-	case x < 1<<49:
-		return 7
-	case x < 1<<56:
-		return 8
-	case x < 1<<63:
-		return 9
-	}
-	return 10
+	return sizeVarint(x)
+}
+
+func sizeVarint(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
 }
 
 // EncodeFixed64 writes a 64-bit integer to the Buffer.
@@ -153,6 +149,10 @@ func (p *Buffer) EncodeFixed64(x uint64) error {
 	return nil
 }
 
+func sizeFixed64(x uint64) int {
+	return 8
+}
+
 // EncodeFixed32 writes a 32-bit integer to the Buffer.
 // This is the format for the
 // fixed32, sfixed32, and float protocol buffer types.
@@ -165,12 +165,20 @@ func (p *Buffer) EncodeFixed32(x uint64) error {
 	return nil
 }
 
+func sizeFixed32(x uint64) int {
+	return 4
+}
+
 // EncodeZigzag64 writes a zigzag-encoded 64-bit integer
 // to the Buffer.
 // This is the format used for the sint64 protocol buffer type.
 func (p *Buffer) EncodeZigzag64(x uint64) error {
 	// use signed number to get arithmetic right shift.
-	return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+	return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
+}
+
+func sizeZigzag64(x uint64) int {
+	return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
 }
 
 // EncodeZigzag32 writes a zigzag-encoded 32-bit integer
@@ -181,6 +189,10 @@ func (p *Buffer) EncodeZigzag32(x uint64) error {
 	return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
 }
 
+func sizeZigzag32(x uint64) int {
+	return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
 // EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
 // This is the format used for the bytes protocol buffer
 // type and for embedded messages.
@@ -190,6 +202,11 @@ func (p *Buffer) EncodeRawBytes(b []byte) error {
 	return nil
 }
 
+func sizeRawBytes(b []byte) int {
+	return sizeVarint(uint64(len(b))) +
+		len(b)
+}
+
 // EncodeStringBytes writes an encoded string to the Buffer.
 // This is the format used for the proto2 string type.
 func (p *Buffer) EncodeStringBytes(s string) error {
@@ -198,17 +215,319 @@ func (p *Buffer) EncodeStringBytes(s string) error {
 	return nil
 }
 
+func sizeStringBytes(s string) int {
+	return sizeVarint(uint64(len(s))) +
+		len(s)
+}
+
 // Marshaler is the interface representing objects that can marshal themselves.
 type Marshaler interface {
 	Marshal() ([]byte, error)
 }
 
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, returning the data.
+func Marshal(pb Message) ([]byte, error) {
+	// Can the object marshal itself?
+	if m, ok := pb.(Marshaler); ok {
+		return m.Marshal()
+	}
+	p := NewBuffer(nil)
+	err := p.Marshal(pb)
+	if p.buf == nil && err == nil {
+		// Return a non-nil slice on success.
+		return []byte{}, nil
+	}
+	return p.buf, err
+}
+
 // EncodeMessage writes the protocol buffer to the Buffer,
 // prefixed by a varint-encoded length.
 func (p *Buffer) EncodeMessage(pb Message) error {
-	siz := Size(pb)
-	p.EncodeVarint(uint64(siz))
-	return p.Marshal(pb)
+	t, base, err := getbase(pb)
+	if structPointer_IsNil(base) {
+		return ErrNil
+	}
+	if err == nil {
+		var state errorState
+		err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+	}
+	return err
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+func (p *Buffer) Marshal(pb Message) error {
+	// Can the object marshal itself?
+	if m, ok := pb.(Marshaler); ok {
+		data, err := m.Marshal()
+		p.buf = append(p.buf, data...)
+		return err
+	}
+
+	t, base, err := getbase(pb)
+	if structPointer_IsNil(base) {
+		return ErrNil
+	}
+	if err == nil {
+		err = p.enc_struct(GetProperties(t.Elem()), base)
+	}
+
+	if collectStats {
+		(stats).Encode++ // Parens are to work around a goimports bug.
+	}
+
+	if len(p.buf) > maxMarshalSize {
+		return ErrTooLarge
+	}
+	return err
+}
+
+// Size returns the encoded size of a protocol buffer.
+func Size(pb Message) (n int) {
+	// Can the object marshal itself?  If so, Size is slow.
+	// TODO: add Size to Marshaler, or add a Sizer interface.
+	if m, ok := pb.(Marshaler); ok {
+		b, _ := m.Marshal()
+		return len(b)
+	}
+
+	t, base, err := getbase(pb)
+	if structPointer_IsNil(base) {
+		return 0
+	}
+	if err == nil {
+		n = size_struct(GetProperties(t.Elem()), base)
+	}
+
+	if collectStats {
+		(stats).Size++ // Parens are to work around a goimports bug.
+	}
+
+	return
+}
+
+// Individual type encoders.
+
+// Encode a bool.
+func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
+	v := *structPointer_Bool(base, p.field)
+	if v == nil {
+		return ErrNil
+	}
+	x := 0
+	if *v {
+		x = 1
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, uint64(x))
+	return nil
+}
+
+func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
+	v := *structPointer_BoolVal(base, p.field)
+	if !v {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, 1)
+	return nil
+}
+
+func size_bool(p *Properties, base structPointer) int {
+	v := *structPointer_Bool(base, p.field)
+	if v == nil {
+		return 0
+	}
+	return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+func size_proto3_bool(p *Properties, base structPointer) int {
+	v := *structPointer_BoolVal(base, p.field)
+	if !v && !p.oneof {
+		return 0
+	}
+	return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+// Encode an int32.
+func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
+	v := structPointer_Word32(base, p.field)
+	if word32_IsNil(v) {
+		return ErrNil
+	}
+	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, uint64(x))
+	return nil
+}
+
+func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
+	v := structPointer_Word32Val(base, p.field)
+	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+	if x == 0 {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, uint64(x))
+	return nil
+}
+
+func size_int32(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word32(base, p.field)
+	if word32_IsNil(v) {
+		return 0
+	}
+	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+	n += len(p.tagcode)
+	n += p.valSize(uint64(x))
+	return
+}
+
+func size_proto3_int32(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word32Val(base, p.field)
+	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+	if x == 0 && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += p.valSize(uint64(x))
+	return
+}
+
+// Encode a uint32.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
+	v := structPointer_Word32(base, p.field)
+	if word32_IsNil(v) {
+		return ErrNil
+	}
+	x := word32_Get(v)
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, uint64(x))
+	return nil
+}
+
+func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
+	v := structPointer_Word32Val(base, p.field)
+	x := word32Val_Get(v)
+	if x == 0 {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, uint64(x))
+	return nil
+}
+
+func size_uint32(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word32(base, p.field)
+	if word32_IsNil(v) {
+		return 0
+	}
+	x := word32_Get(v)
+	n += len(p.tagcode)
+	n += p.valSize(uint64(x))
+	return
+}
+
+func size_proto3_uint32(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word32Val(base, p.field)
+	x := word32Val_Get(v)
+	if x == 0 && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += p.valSize(uint64(x))
+	return
+}
+
+// Encode an int64.
+func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
+	v := structPointer_Word64(base, p.field)
+	if word64_IsNil(v) {
+		return ErrNil
+	}
+	x := word64_Get(v)
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, x)
+	return nil
+}
+
+func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
+	v := structPointer_Word64Val(base, p.field)
+	x := word64Val_Get(v)
+	if x == 0 {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	p.valEnc(o, x)
+	return nil
+}
+
+func size_int64(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word64(base, p.field)
+	if word64_IsNil(v) {
+		return 0
+	}
+	x := word64_Get(v)
+	n += len(p.tagcode)
+	n += p.valSize(x)
+	return
+}
+
+func size_proto3_int64(p *Properties, base structPointer) (n int) {
+	v := structPointer_Word64Val(base, p.field)
+	x := word64Val_Get(v)
+	if x == 0 && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += p.valSize(x)
+	return
+}
+
+// Encode a string.
+func (o *Buffer) enc_string(p *Properties, base structPointer) error {
+	v := *structPointer_String(base, p.field)
+	if v == nil {
+		return ErrNil
+	}
+	x := *v
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeStringBytes(x)
+	return nil
+}
+
+func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
+	v := *structPointer_StringVal(base, p.field)
+	if v == "" {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeStringBytes(v)
+	return nil
+}
+
+func size_string(p *Properties, base structPointer) (n int) {
+	v := *structPointer_String(base, p.field)
+	if v == nil {
+		return 0
+	}
+	x := *v
+	n += len(p.tagcode)
+	n += sizeStringBytes(x)
+	return
+}
+
+func size_proto3_string(p *Properties, base structPointer) (n int) {
+	v := *structPointer_StringVal(base, p.field)
+	if v == "" && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += sizeStringBytes(v)
+	return
 }
 
 // All protocol buffer fields are nillable, but be careful.
@@ -219,3 +538,825 @@ func isNil(v reflect.Value) bool {
 	}
 	return false
 }
+
+// Encode a message struct.
+func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
+	var state errorState
+	structp := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(structp) {
+		return ErrNil
+	}
+
+	// Can the object marshal itself?
+	if p.isMarshaler {
+		m := structPointer_Interface(structp, p.stype).(Marshaler)
+		data, err := m.Marshal()
+		if err != nil && !state.shouldContinue(err, nil) {
+			return err
+		}
+		o.buf = append(o.buf, p.tagcode...)
+		o.EncodeRawBytes(data)
+		return state.err
+	}
+
+	o.buf = append(o.buf, p.tagcode...)
+	return o.enc_len_struct(p.sprop, structp, &state)
+}
+
+func size_struct_message(p *Properties, base structPointer) int {
+	structp := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(structp) {
+		return 0
+	}
+
+	// Can the object marshal itself?
+	if p.isMarshaler {
+		m := structPointer_Interface(structp, p.stype).(Marshaler)
+		data, _ := m.Marshal()
+		n0 := len(p.tagcode)
+		n1 := sizeRawBytes(data)
+		return n0 + n1
+	}
+
+	n0 := len(p.tagcode)
+	n1 := size_struct(p.sprop, structp)
+	n2 := sizeVarint(uint64(n1)) // size of encoded length
+	return n0 + n1 + n2
+}
+
+// Encode a group struct.
+func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
+	var state errorState
+	b := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(b) {
+		return ErrNil
+	}
+
+	o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+	err := o.enc_struct(p.sprop, b)
+	if err != nil && !state.shouldContinue(err, nil) {
+		return err
+	}
+	o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+	return state.err
+}
+
+func size_struct_group(p *Properties, base structPointer) (n int) {
+	b := structPointer_GetStructPointer(base, p.field)
+	if structPointer_IsNil(b) {
+		return 0
+	}
+
+	n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
+	n += size_struct(p.sprop, b)
+	n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
+	return
+}
+
+// Encode a slice of bools ([]bool).
+func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
+	s := *structPointer_BoolSlice(base, p.field)
+	l := len(s)
+	if l == 0 {
+		return ErrNil
+	}
+	for _, x := range s {
+		o.buf = append(o.buf, p.tagcode...)
+		v := uint64(0)
+		if x {
+			v = 1
+		}
+		p.valEnc(o, v)
+	}
+	return nil
+}
+
+func size_slice_bool(p *Properties, base structPointer) int {
+	s := *structPointer_BoolSlice(base, p.field)
+	l := len(s)
+	if l == 0 {
+		return 0
+	}
+	return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
+}
+
+// Encode a slice of bools ([]bool) in packed format.
+func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
+	s := *structPointer_BoolSlice(base, p.field)
+	l := len(s)
+	if l == 0 {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
+	for _, x := range s {
+		v := uint64(0)
+		if x {
+			v = 1
+		}
+		p.valEnc(o, v)
+	}
+	return nil
+}
+
+func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
+	s := *structPointer_BoolSlice(base, p.field)
+	l := len(s)
+	if l == 0 {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += sizeVarint(uint64(l))
+	n += l // each bool takes exactly one byte
+	return
+}
+
+// Encode a slice of bytes ([]byte).
+func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
+	s := *structPointer_Bytes(base, p.field)
+	if s == nil {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeRawBytes(s)
+	return nil
+}
+
+func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
+	s := *structPointer_Bytes(base, p.field)
+	if len(s) == 0 {
+		return ErrNil
+	}
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeRawBytes(s)
+	return nil
+}
+
+func size_slice_byte(p *Properties, base structPointer) (n int) {
+	s := *structPointer_Bytes(base, p.field)
+	if s == nil && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += sizeRawBytes(s)
+	return
+}
+
+func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
+	s := *structPointer_Bytes(base, p.field)
+	if len(s) == 0 && !p.oneof {
+		return 0
+	}
+	n += len(p.tagcode)
+	n += sizeRawBytes(s)
+	return
+}
+
+// Encode a slice of int32s ([]int32).
+func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	for i := 0; i < l; i++ {
+		o.buf = append(o.buf, p.tagcode...)
+		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+		p.valEnc(o, uint64(x))
+	}
+	return nil
+}
+
+func size_slice_int32(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	for i := 0; i < l; i++ {
+		n += len(p.tagcode)
+		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+		n += p.valSize(uint64(x))
+	}
+	return
+}
+
+// Encode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	// TODO: Reuse a Buffer.
+	buf := NewBuffer(nil)
+	for i := 0; i < l; i++ {
+		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+		p.valEnc(buf, uint64(x))
+	}
+
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeVarint(uint64(len(buf.buf)))
+	o.buf = append(o.buf, buf.buf...)
+	return nil
+}
+
+func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	var bufSize int
+	for i := 0; i < l; i++ {
+		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+		bufSize += p.valSize(uint64(x))
+	}
+
+	n += len(p.tagcode)
+	n += sizeVarint(uint64(bufSize))
+	n += bufSize
+	return
+}
+
+// Encode a slice of uint32s ([]uint32).
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	for i := 0; i < l; i++ {
+		o.buf = append(o.buf, p.tagcode...)
+		x := s.Index(i)
+		p.valEnc(o, uint64(x))
+	}
+	return nil
+}
+
+func size_slice_uint32(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	for i := 0; i < l; i++ {
+		n += len(p.tagcode)
+		x := s.Index(i)
+		n += p.valSize(uint64(x))
+	}
+	return
+}
+
+// Encode a slice of uint32s ([]uint32) in packed format.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	// TODO: Reuse a Buffer.
+	buf := NewBuffer(nil)
+	for i := 0; i < l; i++ {
+		p.valEnc(buf, uint64(s.Index(i)))
+	}
+
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeVarint(uint64(len(buf.buf)))
+	o.buf = append(o.buf, buf.buf...)
+	return nil
+}
+
+func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word32Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	var bufSize int
+	for i := 0; i < l; i++ {
+		bufSize += p.valSize(uint64(s.Index(i)))
+	}
+
+	n += len(p.tagcode)
+	n += sizeVarint(uint64(bufSize))
+	n += bufSize
+	return
+}
+
+// Encode a slice of int64s ([]int64).
+func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
+	s := structPointer_Word64Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	for i := 0; i < l; i++ {
+		o.buf = append(o.buf, p.tagcode...)
+		p.valEnc(o, s.Index(i))
+	}
+	return nil
+}
+
+func size_slice_int64(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word64Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	for i := 0; i < l; i++ {
+		n += len(p.tagcode)
+		n += p.valSize(s.Index(i))
+	}
+	return
+}
+
+// Encode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
+	s := structPointer_Word64Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return ErrNil
+	}
+	// TODO: Reuse a Buffer.
+	buf := NewBuffer(nil)
+	for i := 0; i < l; i++ {
+		p.valEnc(buf, s.Index(i))
+	}
+
+	o.buf = append(o.buf, p.tagcode...)
+	o.EncodeVarint(uint64(len(buf.buf)))
+	o.buf = append(o.buf, buf.buf...)
+	return nil
+}
+
+func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
+	s := structPointer_Word64Slice(base, p.field)
+	l := s.Len()
+	if l == 0 {
+		return 0
+	}
+	var bufSize int
+	for i := 0; i < l; i++ {
+		bufSize += p.valSize(s.Index(i))
+	}
+
+	n += len(p.tagcode)
+	n += sizeVarint(uint64(bufSize))
+	n += bufSize
+	return
+}
+
+// Encode a slice of slice of bytes ([][]byte).
+func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
+	ss := *structPointer_BytesSlice(base, p.field)
+	l := len(ss)
+	if l == 0 {
+		return ErrNil
+	}
+	for i := 0; i < l; i++ {
+		o.buf = append(o.buf, p.tagcode...)
+		o.EncodeRawBytes(ss[i])
+	}
+	return nil
+}
+
+func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
+	ss := *structPointer_BytesSlice(base, p.field)
+	l := len(ss)
+	if l == 0 {
+		return 0
+	}
+	n += l * len(p.tagcode)
+	for i := 0; i < l; i++ {
+		n += sizeRawBytes(ss[i])
+	}
+	return
+}
+
+// Encode a slice of strings ([]string).
+func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
+	ss := *structPointer_StringSlice(base, p.field)
+	l := len(ss)
+	for i := 0; i < l; i++ {
+		o.buf = append(o.buf, p.tagcode...)
+		o.EncodeStringBytes(ss[i])
+	}
+	return nil
+}
+
+func size_slice_string(p *Properties, base structPointer) (n int) {
+	ss := *structPointer_StringSlice(base, p.field)
+	l := len(ss)
+	n += l * len(p.tagcode)
+	for i := 0; i < l; i++ {
+		n += sizeStringBytes(ss[i])
+	}
+	return
+}
+
+// Encode a slice of message structs ([]*struct).
+func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
+	var state errorState
+	s := structPointer_StructPointerSlice(base, p.field)
+	l := s.Len()
+
+	for i := 0; i < l; i++ {
+		structp := s.Index(i)
+		if structPointer_IsNil(structp) {
+			return errRepeatedHasNil
+		}
+
+		// Can the object marshal itself?
+		if p.isMarshaler {
+			m := structPointer_Interface(structp, p.stype).(Marshaler)
+			data, err := m.Marshal()
+			if err != nil && !state.shouldContinue(err, nil) {
+				return err
+			}
+			o.buf = append(o.buf, p.tagcode...)
+			o.EncodeRawBytes(data)
+			continue
+		}
+
+		o.buf = append(o.buf, p.tagcode...)
+		err := o.enc_len_struct(p.sprop, structp, &state)
+		if err != nil && !state.shouldContinue(err, nil) {
+			if err == ErrNil {
+				return errRepeatedHasNil
+			}
+			return err
+		}
+	}
+	return state.err
+}
+
+func size_slice_struct_message(p *Properties, base structPointer) (n int) {
+	s := structPointer_StructPointerSlice(base, p.field)
+	l := s.Len()
+	n += l * len(p.tagcode)
+	for i := 0; i < l; i++ {
+		structp := s.Index(i)
+		if structPointer_IsNil(structp) {
+			return // return the size up to this point
+		}
+
+		// Can the object marshal itself?
+		if p.isMarshaler {
+			m := structPointer_Interface(structp, p.stype).(Marshaler)
+			data, _ := m.Marshal()
+			n += sizeRawBytes(data)
+			continue
+		}
+
+		n0 := size_struct(p.sprop, structp)
+		n1 := sizeVarint(uint64(n0)) // size of encoded length
+		n += n0 + n1
+	}
+	return
+}
+
+// Encode a slice of group structs ([]*struct).
+func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
+	var state errorState
+	s := structPointer_StructPointerSlice(base, p.field)
+	l := s.Len()
+
+	for i := 0; i < l; i++ {
+		b := s.Index(i)
+		if structPointer_IsNil(b) {
+			return errRepeatedHasNil
+		}
+
+		o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+
+		err := o.enc_struct(p.sprop, b)
+
+		if err != nil && !state.shouldContinue(err, nil) {
+			if err == ErrNil {
+				return errRepeatedHasNil
+			}
+			return err
+		}
+
+		o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+	}
+	return state.err
+}
+
+func size_slice_struct_group(p *Properties, base structPointer) (n int) {
+	s := structPointer_StructPointerSlice(base, p.field)
+	l := s.Len()
+
+	n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
+	n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
+	for i := 0; i < l; i++ {
+		b := s.Index(i)
+		if structPointer_IsNil(b) {
+			return // return size up to this point
+		}
+
+		n += size_struct(p.sprop, b)
+	}
+	return
+}
+
+// Encode an extension map.
+func (o *Buffer) enc_map(p *Properties, base structPointer) error {
+	exts := structPointer_ExtMap(base, p.field)
+	if err := encodeExtensionsMap(*exts); err != nil {
+		return err
+	}
+
+	return o.enc_map_body(*exts)
+}
+
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
+	exts := structPointer_Extensions(base, p.field)
+
+	v, mu := exts.extensionsRead()
+	if v == nil {
+		return nil
+	}
+
+	mu.Lock()
+	defer mu.Unlock()
+	if err := encodeExtensionsMap(v); err != nil {
+		return err
+	}
+
+	return o.enc_map_body(v)
+}
+
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
+	// Fast-path for common cases: zero or one extensions.
+	if len(v) <= 1 {
+		for _, e := range v {
+			o.buf = append(o.buf, e.enc...)
+		}
+		return nil
+	}
+
+	// Sort keys to provide a deterministic encoding.
+	keys := make([]int, 0, len(v))
+	for k := range v {
+		keys = append(keys, int(k))
+	}
+	sort.Ints(keys)
+
+	for _, k := range keys {
+		o.buf = append(o.buf, v[int32(k)].enc...)
+	}
+	return nil
+}
+
+func size_map(p *Properties, base structPointer) int {
+	v := structPointer_ExtMap(base, p.field)
+	return extensionsMapSize(*v)
+}
+
+func size_exts(p *Properties, base structPointer) int {
+	v := structPointer_Extensions(base, p.field)
+	return extensionsSize(v)
+}
+
+// Encode a map field.
+func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
+	var state errorState // XXX: or do we need to plumb this through?
+
+	/*
+		A map defined as
+			map<key_type, value_type> map_field = N;
+		is encoded in the same way as
+			message MapFieldEntry {
+				key_type key = 1;
+				value_type value = 2;
+			}
+			repeated MapFieldEntry map_field = N;
+	*/
+
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+	if v.Len() == 0 {
+		return nil
+	}
+
+	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+	enc := func() error {
+		if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
+			return err
+		}
+		if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
+			return err
+		}
+		return nil
+	}
+
+	// Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+	for _, key := range v.MapKeys() {
+		val := v.MapIndex(key)
+
+		keycopy.Set(key)
+		valcopy.Set(val)
+
+		o.buf = append(o.buf, p.tagcode...)
+		if err := o.enc_len_thing(enc, &state); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func size_new_map(p *Properties, base structPointer) int {
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+
+	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+	n := 0
+	for _, key := range v.MapKeys() {
+		val := v.MapIndex(key)
+		keycopy.Set(key)
+		valcopy.Set(val)
+
+		// Tag codes for key and val are the responsibility of the sub-sizer.
+		keysize := p.mkeyprop.size(p.mkeyprop, keybase)
+		valsize := p.mvalprop.size(p.mvalprop, valbase)
+		entry := keysize + valsize
+		// Add on tag code and length of map entry itself.
+		n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
+	}
+	return n
+}
+
+// mapEncodeScratch returns a new reflect.Value matching the map's value type,
+// and a structPointer suitable for passing to an encoder or sizer.
+func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
+	// Prepare addressable doubly-indirect placeholders for the key and value types.
+	// This is needed because the element-type encoders expect **T, but the map iteration produces T.
+
+	keycopy = reflect.New(mapType.Key()).Elem()                 // addressable K
+	keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
+	keyptr.Set(keycopy.Addr())                                  //
+	keybase = toStructPointer(keyptr.Addr())                    // **K
+
+	// Value types are more varied and require special handling.
+	switch mapType.Elem().Kind() {
+	case reflect.Slice:
+		// []byte
+		var dummy []byte
+		valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
+		valbase = toStructPointer(valcopy.Addr())
+	case reflect.Ptr:
+		// message; the generated field type is map[K]*Msg (so V is *Msg),
+		// so we only need one level of indirection.
+		valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+		valbase = toStructPointer(valcopy.Addr())
+	default:
+		// everything else
+		valcopy = reflect.New(mapType.Elem()).Elem()                // addressable V
+		valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
+		valptr.Set(valcopy.Addr())                                  //
+		valbase = toStructPointer(valptr.Addr())                    // **V
+	}
+	return
+}
+
+// Encode a struct.
+func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
+	var state errorState
+	// Encode fields in tag order so that decoders may use optimizations
+	// that depend on the ordering.
+	// https://developers.google.com/protocol-buffers/docs/encoding#order
+	for _, i := range prop.order {
+		p := prop.Prop[i]
+		if p.enc != nil {
+			err := p.enc(o, p, base)
+			if err != nil {
+				if err == ErrNil {
+					if p.Required && state.err == nil {
+						state.err = &RequiredNotSetError{p.Name}
+					}
+				} else if err == errRepeatedHasNil {
+					// Give more context to nil values in repeated fields.
+					return errors.New("repeated field " + p.OrigName + " has nil element")
+				} else if !state.shouldContinue(err, p) {
+					return err
+				}
+			}
+			if len(o.buf) > maxMarshalSize {
+				return ErrTooLarge
+			}
+		}
+	}
+
+	// Do oneof fields.
+	if prop.oneofMarshaler != nil {
+		m := structPointer_Interface(base, prop.stype).(Message)
+		if err := prop.oneofMarshaler(m, o); err == ErrNil {
+			return errOneofHasNil
+		} else if err != nil {
+			return err
+		}
+	}
+
+	// Add unrecognized fields at the end.
+	if prop.unrecField.IsValid() {
+		v := *structPointer_Bytes(base, prop.unrecField)
+		if len(o.buf)+len(v) > maxMarshalSize {
+			return ErrTooLarge
+		}
+		if len(v) > 0 {
+			o.buf = append(o.buf, v...)
+		}
+	}
+
+	return state.err
+}
+
+func size_struct(prop *StructProperties, base structPointer) (n int) {
+	for _, i := range prop.order {
+		p := prop.Prop[i]
+		if p.size != nil {
+			n += p.size(p, base)
+		}
+	}
+
+	// Add unrecognized fields at the end.
+	if prop.unrecField.IsValid() {
+		v := *structPointer_Bytes(base, prop.unrecField)
+		n += len(v)
+	}
+
+	// Factor in any oneof fields.
+	if prop.oneofSizer != nil {
+		m := structPointer_Interface(base, prop.stype).(Message)
+		n += prop.oneofSizer(m)
+	}
+
+	return
+}
+
+var zeroes [20]byte // longer than any conceivable sizeVarint
+
+// Encode a struct, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
+	return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
+}
+
+// Encode something, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
+	iLen := len(o.buf)
+	o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
+	iMsg := len(o.buf)
+	err := enc()
+	if err != nil && !state.shouldContinue(err, nil) {
+		return err
+	}
+	lMsg := len(o.buf) - iMsg
+	lLen := sizeVarint(uint64(lMsg))
+	switch x := lLen - (iMsg - iLen); {
+	case x > 0: // actual length is x bytes larger than the space we reserved
+		// Move msg x bytes right.
+		o.buf = append(o.buf, zeroes[:x]...)
+		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+	case x < 0: // actual length is x bytes smaller than the space we reserved
+		// Move msg x bytes left.
+		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+		o.buf = o.buf[:len(o.buf)+x] // x is negative
+	}
+	// Encode the length in the reserved space.
+	o.buf = o.buf[:iLen]
+	o.EncodeVarint(uint64(lMsg))
+	o.buf = o.buf[:len(o.buf)+lMsg]
+	return state.err
+}
+
+// errorState maintains the first error that occurs and updates that error
+// with additional context.
+type errorState struct {
+	err error
+}
+
+// shouldContinue reports whether encoding should continue upon encountering the
+// given error. If the error is RequiredNotSetError, shouldContinue returns true
+// and, if this is the first appearance of that error, remembers it for future
+// reporting.
+//
+// If prop is not nil, it may update any error with additional context about the
+// field with the error.
+func (s *errorState) shouldContinue(err error, prop *Properties) bool {
+	// Ignore unset required fields.
+	reqNotSet, ok := err.(*RequiredNotSetError)
+	if !ok {
+		return false
+	}
+	if s.err == nil {
+		if prop != nil {
+			err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
+		}
+		s.err = err
+	}
+	return true
+}
diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go
index d4db5a1c1457776f25424eedc9d9e64f4f4ab736..2ed1cf596664d3dedb372fc051a04b79da040f21 100644
--- a/vendor/github.com/golang/protobuf/proto/equal.go
+++ b/vendor/github.com/golang/protobuf/proto/equal.go
@@ -109,6 +109,15 @@ func equalStruct(v1, v2 reflect.Value) bool {
 				// set/unset mismatch
 				return false
 			}
+			b1, ok := f1.Interface().(raw)
+			if ok {
+				b2 := f2.Interface().(raw)
+				// RawMessage
+				if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
+					return false
+				}
+				continue
+			}
 			f1, f2 = f1.Elem(), f2.Elem()
 		}
 		if !equalAny(f1, f2, sprop.Prop[i]) {
@@ -137,7 +146,11 @@ func equalStruct(v1, v2 reflect.Value) bool {
 
 	u1 := uf.Bytes()
 	u2 := v2.FieldByName("XXX_unrecognized").Bytes()
-	return bytes.Equal(u1, u2)
+	if !bytes.Equal(u1, u2) {
+		return false
+	}
+
+	return true
 }
 
 // v1 and v2 are known to have the same type.
@@ -248,15 +261,6 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 
 		m1, m2 := e1.value, e2.value
 
-		if m1 == nil && m2 == nil {
-			// Both have only encoded form.
-			if bytes.Equal(e1.enc, e2.enc) {
-				continue
-			}
-			// The bytes are different, but the extensions might still be
-			// equal. We need to decode them to compare.
-		}
-
 		if m1 != nil && m2 != nil {
 			// Both are unencoded.
 			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
@@ -272,12 +276,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 			desc = m[extNum]
 		}
 		if desc == nil {
-			// If both have only encoded form and the bytes are the same,
-			// it is handled above. We get here when the bytes are different.
-			// We don't know how to decode it, so just compare them as byte
-			// slices.
 			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
-			return false
+			continue
 		}
 		var err error
 		if m1 == nil {
diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go
index 816a3b9d6c09faf075c20d839f6eddc0221ffae4..eaad21831263eecc5add3fa980847857d2123bf2 100644
--- a/vendor/github.com/golang/protobuf/proto/extensions.go
+++ b/vendor/github.com/golang/protobuf/proto/extensions.go
@@ -38,7 +38,6 @@ package proto
 import (
 	"errors"
 	"fmt"
-	"io"
 	"reflect"
 	"strconv"
 	"sync"
@@ -92,29 +91,14 @@ func (n notLocker) Unlock() {}
 // extendable returns the extendableProto interface for the given generated proto message.
 // If the proto message has the old extension format, it returns a wrapper that implements
 // the extendableProto interface.
-func extendable(p interface{}) (extendableProto, error) {
-	switch p := p.(type) {
-	case extendableProto:
-		if isNilPtr(p) {
-			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
-		}
-		return p, nil
-	case extendableProtoV1:
-		if isNilPtr(p) {
-			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
-		}
-		return extensionAdapter{p}, nil
+func extendable(p interface{}) (extendableProto, bool) {
+	if ep, ok := p.(extendableProto); ok {
+		return ep, ok
 	}
-	// Don't allocate a specific error containing %T:
-	// this is the hot path for Clone and MarshalText.
-	return nil, errNotExtendable
-}
-
-var errNotExtendable = errors.New("proto: not an extendable proto.Message")
-
-func isNilPtr(x interface{}) bool {
-	v := reflect.ValueOf(x)
-	return v.Kind() == reflect.Ptr && v.IsNil()
+	if ep, ok := p.(extendableProtoV1); ok {
+		return extensionAdapter{ep}, ok
+	}
+	return nil, false
 }
 
 // XXX_InternalExtensions is an internal representation of proto extensions.
@@ -159,6 +143,9 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
 	return e.p.extensionMap, &e.p.mu
 }
 
+var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
+
 // ExtensionDesc represents an extension specification.
 // Used in generated code from the protocol compiler.
 type ExtensionDesc struct {
@@ -192,8 +179,8 @@ type Extension struct {
 
 // SetRawExtension is for testing only.
 func SetRawExtension(base Message, id int32, b []byte) {
-	epb, err := extendable(base)
-	if err != nil {
+	epb, ok := extendable(base)
+	if !ok {
 		return
 	}
 	extmap := epb.extensionsWrite()
@@ -218,7 +205,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
 		pbi = ea.extendableProtoV1
 	}
 	if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
-		return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
+		return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
 	}
 	// Check the range.
 	if !isExtensionField(pb, extension.Field) {
@@ -263,11 +250,85 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
 	return prop
 }
 
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensions(e *XXX_InternalExtensions) error {
+	m, mu := e.extensionsRead()
+	if m == nil {
+		return nil // fast path
+	}
+	mu.Lock()
+	defer mu.Unlock()
+	return encodeExtensionsMap(m)
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensionsMap(m map[int32]Extension) error {
+	for k, e := range m {
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		et := reflect.TypeOf(e.desc.ExtensionType)
+		props := extensionProperties(e.desc)
+
+		p := NewBuffer(nil)
+		// If e.value has type T, the encoder expects a *struct{ X T }.
+		// Pass a *T with a zero field and hope it all works out.
+		x := reflect.New(et)
+		x.Elem().Set(reflect.ValueOf(e.value))
+		if err := props.enc(p, props, toStructPointer(x)); err != nil {
+			return err
+		}
+		e.enc = p.buf
+		m[k] = e
+	}
+	return nil
+}
+
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
+	m, mu := e.extensionsRead()
+	if m == nil {
+		return 0
+	}
+	mu.Lock()
+	defer mu.Unlock()
+	return extensionsMapSize(m)
+}
+
+func extensionsMapSize(m map[int32]Extension) (n int) {
+	for _, e := range m {
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			n += len(e.enc)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		et := reflect.TypeOf(e.desc.ExtensionType)
+		props := extensionProperties(e.desc)
+
+		// If e.value has type T, the encoder expects a *struct{ X T }.
+		// Pass a *T with a zero field and hope it all works out.
+		x := reflect.New(et)
+		x.Elem().Set(reflect.ValueOf(e.value))
+		n += props.size(props, toStructPointer(x))
+	}
+	return
+}
+
 // HasExtension returns whether the given extension is present in pb.
 func HasExtension(pb Message, extension *ExtensionDesc) bool {
 	// TODO: Check types, field numbers, etc.?
-	epb, err := extendable(pb)
-	if err != nil {
+	epb, ok := extendable(pb)
+	if !ok {
 		return false
 	}
 	extmap, mu := epb.extensionsRead()
@@ -275,15 +336,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
 		return false
 	}
 	mu.Lock()
-	_, ok := extmap[extension.Field]
+	_, ok = extmap[extension.Field]
 	mu.Unlock()
 	return ok
 }
 
 // ClearExtension removes the given extension from pb.
 func ClearExtension(pb Message, extension *ExtensionDesc) {
-	epb, err := extendable(pb)
-	if err != nil {
+	epb, ok := extendable(pb)
+	if !ok {
 		return
 	}
 	// TODO: Check types, field numbers, etc.?
@@ -291,26 +352,16 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
 	delete(extmap, extension.Field)
 }
 
-// GetExtension retrieves a proto2 extended field from pb.
-//
-// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
-// then GetExtension parses the encoded field and returns a Go value of the specified type.
-// If the field is not present, then the default value is returned (if one is specified),
-// otherwise ErrMissingExtension is reported.
-//
-// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
-// then GetExtension returns the raw encoded bytes of the field extension.
+// GetExtension parses and returns the given extension of pb.
+// If the extension is not present and has no default value it returns ErrMissingExtension.
 func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
-	epb, err := extendable(pb)
-	if err != nil {
-		return nil, err
+	epb, ok := extendable(pb)
+	if !ok {
+		return nil, errors.New("proto: not an extendable proto")
 	}
 
-	if extension.ExtendedType != nil {
-		// can only check type if this is a complete descriptor
-		if err := checkExtensionTypes(epb, extension); err != nil {
-			return nil, err
-		}
+	if err := checkExtensionTypes(epb, extension); err != nil {
+		return nil, err
 	}
 
 	emap, mu := epb.extensionsRead()
@@ -337,11 +388,6 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 		return e.value, nil
 	}
 
-	if extension.ExtensionType == nil {
-		// incomplete descriptor
-		return e.enc, nil
-	}
-
 	v, err := decodeExtension(e.enc, extension)
 	if err != nil {
 		return nil, err
@@ -359,11 +405,6 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 // defaultExtensionValue returns the default value for extension.
 // If no default for an extension is defined ErrMissingExtension is returned.
 func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
-	if extension.ExtensionType == nil {
-		// incomplete descriptor, so no default
-		return nil, ErrMissingExtension
-	}
-
 	t := reflect.TypeOf(extension.ExtensionType)
 	props := extensionProperties(extension)
 
@@ -398,28 +439,31 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
 
 // decodeExtension decodes an extension encoded in b.
 func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
+	o := NewBuffer(b)
+
 	t := reflect.TypeOf(extension.ExtensionType)
-	unmarshal := typeUnmarshaler(t, extension.Tag)
+
+	props := extensionProperties(extension)
 
 	// t is a pointer to a struct, pointer to basic type or a slice.
-	// Allocate space to store the pointer/slice.
+	// Allocate a "field" to store the pointer/slice itself; the
+	// pointer/slice will be stored here. We pass
+	// the address of this field to props.dec.
+	// This passes a zero field and a *t and lets props.dec
+	// interpret it as a *struct{ x t }.
 	value := reflect.New(t).Elem()
 
-	var err error
 	for {
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
+		// Discard wire type and field number varint. It isn't needed.
+		if _, err := o.DecodeVarint(); err != nil {
+			return nil, err
 		}
-		b = b[n:]
-		wire := int(x) & 7
 
-		b, err = unmarshal(b, valToPointer(value.Addr()), wire)
-		if err != nil {
+		if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
 			return nil, err
 		}
 
-		if len(b) == 0 {
+		if o.index >= len(o.buf) {
 			break
 		}
 	}
@@ -429,9 +473,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 // GetExtensions returns a slice of the extensions present in pb that are also listed in es.
 // The returned slice has the same length as es; missing extensions will appear as nil elements.
 func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
-	epb, err := extendable(pb)
-	if err != nil {
-		return nil, err
+	epb, ok := extendable(pb)
+	if !ok {
+		return nil, errors.New("proto: not an extendable proto")
 	}
 	extensions = make([]interface{}, len(es))
 	for i, e := range es {
@@ -450,9 +494,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
 // For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
 // just the Field field, which defines the extension's field number.
 func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
-	epb, err := extendable(pb)
-	if err != nil {
-		return nil, err
+	epb, ok := extendable(pb)
+	if !ok {
+		return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
 	}
 	registeredExtensions := RegisteredExtensions(pb)
 
@@ -479,9 +523,9 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
 
 // SetExtension sets the specified extension of pb to the specified value.
 func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
-	epb, err := extendable(pb)
-	if err != nil {
-		return err
+	epb, ok := extendable(pb)
+	if !ok {
+		return errors.New("proto: not an extendable proto")
 	}
 	if err := checkExtensionTypes(epb, extension); err != nil {
 		return err
@@ -506,8 +550,8 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
 
 // ClearAllExtensions clears all extensions from pb.
 func ClearAllExtensions(pb Message) {
-	epb, err := extendable(pb)
-	if err != nil {
+	epb, ok := extendable(pb)
+	if !ok {
 		return
 	}
 	m := epb.extensionsWrite()
diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go
index 0e2191b8ada36129be8a0be7b9a84bcd79a21add..1c225504a013c5da68f5b46caa5c110dd32db6cf 100644
--- a/vendor/github.com/golang/protobuf/proto/lib.go
+++ b/vendor/github.com/golang/protobuf/proto/lib.go
@@ -265,7 +265,6 @@ package proto
 
 import (
 	"encoding/json"
-	"errors"
 	"fmt"
 	"log"
 	"reflect"
@@ -274,8 +273,6 @@ import (
 	"sync"
 )
 
-var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
-
 // Message is implemented by generated protocol buffer messages.
 type Message interface {
 	Reset()
@@ -312,7 +309,16 @@ type Buffer struct {
 	buf   []byte // encode/decode byte stream
 	index int    // read point
 
-	deterministic bool
+	// pools of basic types to amortize allocation.
+	bools   []bool
+	uint32s []uint32
+	uint64s []uint64
+
+	// extra pools, only used with pointer_reflect.go
+	int32s   []int32
+	int64s   []int64
+	float32s []float32
+	float64s []float64
 }
 
 // NewBuffer allocates a new Buffer and initializes its internal data to
@@ -337,30 +343,6 @@ func (p *Buffer) SetBuf(s []byte) {
 // Bytes returns the contents of the Buffer.
 func (p *Buffer) Bytes() []byte { return p.buf }
 
-// SetDeterministic sets whether to use deterministic serialization.
-//
-// Deterministic serialization guarantees that for a given binary, equal
-// messages will always be serialized to the same bytes. This implies:
-//
-//   - Repeated serialization of a message will return the same bytes.
-//   - Different processes of the same binary (which may be executing on
-//     different machines) will serialize equal messages to the same bytes.
-//
-// Note that the deterministic serialization is NOT canonical across
-// languages. It is not guaranteed to remain stable over time. It is unstable
-// across different builds with schema changes due to unknown fields.
-// Users who need canonical serialization (e.g., persistent storage in a
-// canonical form, fingerprinting, etc.) should define their own
-// canonicalization specification and implement their own serializer rather
-// than relying on this API.
-//
-// If deterministic serialization is requested, map entries will be sorted
-// by keys in lexographical order. This is an implementation detail and
-// subject to change.
-func (p *Buffer) SetDeterministic(deterministic bool) {
-	p.deterministic = deterministic
-}
-
 /*
  * Helper routines for simplifying the creation of optional fields of basic type.
  */
@@ -849,12 +831,22 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
 	return sf, false, nil
 }
 
-// mapKeys returns a sort.Interface to be used for sorting the map keys.
 // Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+
 func mapKeys(vs []reflect.Value) sort.Interface {
-	s := mapKeySorter{vs: vs}
+	s := mapKeySorter{
+		vs: vs,
+		// default Less function: textual comparison
+		less: func(a, b reflect.Value) bool {
+			return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+		},
+	}
 
-	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
+	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+	// numeric keys are sorted numerically.
 	if len(vs) == 0 {
 		return s
 	}
@@ -863,12 +855,6 @@ func mapKeys(vs []reflect.Value) sort.Interface {
 		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
 	case reflect.Uint32, reflect.Uint64:
 		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
-	case reflect.Bool:
-		s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
-	case reflect.String:
-		s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
-	default:
-		panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
 	}
 
 	return s
@@ -909,13 +895,3 @@ const ProtoPackageIsVersion2 = true
 // ProtoPackageIsVersion1 is referenced from generated protocol buffer files
 // to assert that that code is compatible with this version of the proto package.
 const ProtoPackageIsVersion1 = true
-
-// InternalMessageInfo is a type used internally by generated .pb.go files.
-// This type is not intended to be used by non-generated code.
-// This type is not subject to any compatibility guarantee.
-type InternalMessageInfo struct {
-	marshal   *marshalInfo
-	unmarshal *unmarshalInfo
-	merge     *mergeInfo
-	discard   *discardInfo
-}
diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go
index 3b6ca41d5e5543dddafc5831203d3b8dcb109ba5..fd982decd66e4846031a72a785470be20afe99a5 100644
--- a/vendor/github.com/golang/protobuf/proto/message_set.go
+++ b/vendor/github.com/golang/protobuf/proto/message_set.go
@@ -42,7 +42,6 @@ import (
 	"fmt"
 	"reflect"
 	"sort"
-	"sync"
 )
 
 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@@ -95,7 +94,10 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 }
 
 func (ms *messageSet) Has(pb Message) bool {
-	return ms.find(pb) != nil
+	if ms.find(pb) != nil {
+		return true
+	}
+	return false
 }
 
 func (ms *messageSet) Unmarshal(pb Message) error {
@@ -148,42 +150,46 @@ func skipVarint(buf []byte) []byte {
 // MarshalMessageSet encodes the extension map represented by m in the message set wire format.
 // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
 func MarshalMessageSet(exts interface{}) ([]byte, error) {
-	return marshalMessageSet(exts, false)
-}
-
-// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
-func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
+	var m map[int32]Extension
 	switch exts := exts.(type) {
 	case *XXX_InternalExtensions:
-		var u marshalInfo
-		siz := u.sizeMessageSet(exts)
-		b := make([]byte, 0, siz)
-		return u.appendMessageSet(b, exts, deterministic)
-
+		if err := encodeExtensions(exts); err != nil {
+			return nil, err
+		}
+		m, _ = exts.extensionsRead()
 	case map[int32]Extension:
-		// This is an old-style extension map.
-		// Wrap it in a new-style XXX_InternalExtensions.
-		ie := XXX_InternalExtensions{
-			p: &struct {
-				mu           sync.Mutex
-				extensionMap map[int32]Extension
-			}{
-				extensionMap: exts,
-			},
+		if err := encodeExtensionsMap(exts); err != nil {
+			return nil, err
 		}
-
-		var u marshalInfo
-		siz := u.sizeMessageSet(&ie)
-		b := make([]byte, 0, siz)
-		return u.appendMessageSet(b, &ie, deterministic)
-
+		m = exts
 	default:
 		return nil, errors.New("proto: not an extension map")
 	}
+
+	// Sort extension IDs to provide a deterministic encoding.
+	// See also enc_map in encode.go.
+	ids := make([]int, 0, len(m))
+	for id := range m {
+		ids = append(ids, int(id))
+	}
+	sort.Ints(ids)
+
+	ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+	for _, id := range ids {
+		e := m[int32(id)]
+		// Remove the wire type and field number varint, as well as the length varint.
+		msg := skipVarint(skipVarint(e.enc))
+
+		ms.Item = append(ms.Item, &_MessageSet_Item{
+			TypeId:  Int32(int32(id)),
+			Message: msg,
+		})
+	}
+	return Marshal(ms)
 }
 
 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
-// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 func UnmarshalMessageSet(buf []byte, exts interface{}) error {
 	var m map[int32]Extension
 	switch exts := exts.(type) {
@@ -229,15 +235,7 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
 	var m map[int32]Extension
 	switch exts := exts.(type) {
 	case *XXX_InternalExtensions:
-		var mu sync.Locker
-		m, mu = exts.extensionsRead()
-		if m != nil {
-			// Keep the extensions map locked until we're done marshaling to prevent
-			// races between marshaling and unmarshaling the lazily-{en,de}coded
-			// values.
-			mu.Lock()
-			defer mu.Unlock()
-		}
+		m, _ = exts.extensionsRead()
 	case map[int32]Extension:
 		m = exts
 	default:
@@ -255,16 +253,15 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
 
 	for i, id := range ids {
 		ext := m[id]
+		if i > 0 {
+			b.WriteByte(',')
+		}
+
 		msd, ok := messageSetMap[id]
 		if !ok {
 			// Unknown type; we can't render it, so skip it.
 			continue
 		}
-
-		if i > 0 && b.Len() > 1 {
-			b.WriteByte(',')
-		}
-
 		fmt.Fprintf(&b, `"[%s]":`, msd.name)
 
 		x := ext.value
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
index b6cad90834b31a7e1ce445486d849285e9454573..fb512e2e16dce05683722f810c279367bdc68fe9 100644
--- a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
+++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
@@ -29,7 +29,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// +build purego appengine js
+// +build appengine js
 
 // This file contains an implementation of proto field accesses using package reflect.
 // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
@@ -38,13 +38,32 @@
 package proto
 
 import (
+	"math"
 	"reflect"
-	"sync"
 )
 
-const unsafeAllowed = false
+// A structPointer is a pointer to a struct.
+type structPointer struct {
+	v reflect.Value
+}
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+// The reflect value must itself be a pointer to a struct.
+func toStructPointer(v reflect.Value) structPointer {
+	return structPointer{v}
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+	return p.v.IsNil()
+}
 
-// A field identifies a field in a struct, accessible from a pointer.
+// Interface returns the struct pointer as an interface value.
+func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
+	return p.v.Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
 // In this implementation, a field is identified by the sequence of field indices
 // passed to reflect's FieldByIndex.
 type field []int
@@ -57,301 +76,409 @@ func toField(f *reflect.StructField) field {
 // invalidField is an invalid field identifier.
 var invalidField = field(nil)
 
-// zeroField is a noop when calling pointer.offset.
-var zeroField = field([]int{})
-
 // IsValid reports whether the field identifier is valid.
 func (f field) IsValid() bool { return f != nil }
 
-// The pointer type is for the table-driven decoder.
-// The implementation here uses a reflect.Value of pointer type to
-// create a generic pointer. In pointer_unsafe.go we use unsafe
-// instead of reflect to implement the same (but faster) interface.
-type pointer struct {
-	v reflect.Value
-}
+// field returns the given field in the struct as a reflect value.
+func structPointer_field(p structPointer, f field) reflect.Value {
+	// Special case: an extension map entry with a value of type T
+	// passes a *T to the struct-handling code with a zero field,
+	// expecting that it will be treated as equivalent to *struct{ X T },
+	// which has the same memory layout. We have to handle that case
+	// specially, because reflect will panic if we call FieldByIndex on a
+	// non-struct.
+	if f == nil {
+		return p.v.Elem()
+	}
 
-// toPointer converts an interface of pointer type to a pointer
-// that points to the same target.
-func toPointer(i *Message) pointer {
-	return pointer{v: reflect.ValueOf(*i)}
+	return p.v.Elem().FieldByIndex(f)
 }
 
-// toAddrPointer converts an interface to a pointer that points to
-// the interface data.
-func toAddrPointer(i *interface{}, isptr bool) pointer {
-	v := reflect.ValueOf(*i)
-	u := reflect.New(v.Type())
-	u.Elem().Set(v)
-	return pointer{v: u}
+// ifield returns the given field in the struct as an interface value.
+func structPointer_ifield(p structPointer, f field) interface{} {
+	return structPointer_field(p, f).Addr().Interface()
 }
 
-// valToPointer converts v to a pointer.  v must be of pointer type.
-func valToPointer(v reflect.Value) pointer {
-	return pointer{v: v}
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+	return structPointer_ifield(p, f).(*[]byte)
 }
 
-// offset converts from a pointer to a structure to a pointer to
-// one of its fields.
-func (p pointer) offset(f field) pointer {
-	return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+	return structPointer_ifield(p, f).(*[][]byte)
 }
 
-func (p pointer) isNil() bool {
-	return p.v.IsNil()
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+	return structPointer_ifield(p, f).(**bool)
 }
 
-// grow updates the slice s in place to make it one element longer.
-// s must be addressable.
-// Returns the (addressable) new element.
-func grow(s reflect.Value) reflect.Value {
-	n, m := s.Len(), s.Cap()
-	if n < m {
-		s.SetLen(n + 1)
-	} else {
-		s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
-	}
-	return s.Index(n)
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+	return structPointer_ifield(p, f).(*bool)
 }
 
-func (p pointer) toInt64() *int64 {
-	return p.v.Interface().(*int64)
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+	return structPointer_ifield(p, f).(*[]bool)
 }
-func (p pointer) toInt64Ptr() **int64 {
-	return p.v.Interface().(**int64)
-}
-func (p pointer) toInt64Slice() *[]int64 {
-	return p.v.Interface().(*[]int64)
-}
-
-var int32ptr = reflect.TypeOf((*int32)(nil))
 
-func (p pointer) toInt32() *int32 {
-	return p.v.Convert(int32ptr).Interface().(*int32)
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+	return structPointer_ifield(p, f).(**string)
 }
 
-// The toInt32Ptr/Slice methods don't work because of enums.
-// Instead, we must use set/get methods for the int32ptr/slice case.
-/*
-	func (p pointer) toInt32Ptr() **int32 {
-		return p.v.Interface().(**int32)
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+	return structPointer_ifield(p, f).(*string)
 }
-	func (p pointer) toInt32Slice() *[]int32 {
-		return p.v.Interface().(*[]int32)
-}
-*/
-func (p pointer) getInt32Ptr() *int32 {
-	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
-		// raw int32 type
-		return p.v.Elem().Interface().(*int32)
-	}
-	// an enum
-	return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
-}
-func (p pointer) setInt32Ptr(v int32) {
-	// Allocate value in a *int32. Possibly convert that to a *enum.
-	// Then assign it to a **int32 or **enum.
-	// Note: we can convert *int32 to *enum, but we can't convert
-	// **int32 to **enum!
-	p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
-}
-
-// getInt32Slice copies []int32 from p as a new slice.
-// This behavior differs from the implementation in pointer_unsafe.go.
-func (p pointer) getInt32Slice() []int32 {
-	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
-		// raw int32 type
-		return p.v.Elem().Interface().([]int32)
-	}
-	// an enum
-	// Allocate a []int32, then assign []enum's values into it.
-	// Note: we can't convert []enum to []int32.
-	slice := p.v.Elem()
-	s := make([]int32, slice.Len())
-	for i := 0; i < slice.Len(); i++ {
-		s[i] = int32(slice.Index(i).Int())
-	}
-	return s
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+	return structPointer_ifield(p, f).(*[]string)
 }
 
-// setInt32Slice copies []int32 into p as a new slice.
-// This behavior differs from the implementation in pointer_unsafe.go.
-func (p pointer) setInt32Slice(v []int32) {
-	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
-		// raw int32 type
-		p.v.Elem().Set(reflect.ValueOf(v))
-		return
-	}
-	// an enum
-	// Allocate a []enum, then assign []int32's values into it.
-	// Note: we can't convert []enum to []int32.
-	slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
-	for i, x := range v {
-		slice.Index(i).SetInt(int64(x))
-	}
-	p.v.Elem().Set(slice)
+// Extensions returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+	return structPointer_ifield(p, f).(*XXX_InternalExtensions)
 }
-func (p pointer) appendInt32Slice(v int32) {
-	grow(p.v.Elem()).SetInt(int64(v))
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+	return structPointer_ifield(p, f).(*map[int32]Extension)
 }
 
-func (p pointer) toUint64() *uint64 {
-	return p.v.Interface().(*uint64)
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+	return structPointer_field(p, f).Addr()
 }
-func (p pointer) toUint64Ptr() **uint64 {
-	return p.v.Interface().(**uint64)
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+	structPointer_field(p, f).Set(q.v)
 }
-func (p pointer) toUint64Slice() *[]uint64 {
-	return p.v.Interface().(*[]uint64)
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+	return structPointer{structPointer_field(p, f)}
 }
-func (p pointer) toUint32() *uint32 {
-	return p.v.Interface().(*uint32)
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
+	return structPointerSlice{structPointer_field(p, f)}
 }
-func (p pointer) toUint32Ptr() **uint32 {
-	return p.v.Interface().(**uint32)
+
+// A structPointerSlice represents the address of a slice of pointers to structs
+// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
+type structPointerSlice struct {
+	v reflect.Value
 }
-func (p pointer) toUint32Slice() *[]uint32 {
-	return p.v.Interface().(*[]uint32)
+
+func (p structPointerSlice) Len() int                  { return p.v.Len() }
+func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
+func (p structPointerSlice) Append(q structPointer) {
+	p.v.Set(reflect.Append(p.v, q.v))
 }
-func (p pointer) toBool() *bool {
-	return p.v.Interface().(*bool)
+
+var (
+	int32Type   = reflect.TypeOf(int32(0))
+	uint32Type  = reflect.TypeOf(uint32(0))
+	float32Type = reflect.TypeOf(float32(0))
+	int64Type   = reflect.TypeOf(int64(0))
+	uint64Type  = reflect.TypeOf(uint64(0))
+	float64Type = reflect.TypeOf(float64(0))
+)
+
+// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
+// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
+type word32 struct {
+	v reflect.Value
 }
-func (p pointer) toBoolPtr() **bool {
-	return p.v.Interface().(**bool)
+
+// IsNil reports whether p is nil.
+func word32_IsNil(p word32) bool {
+	return p.v.IsNil()
 }
-func (p pointer) toBoolSlice() *[]bool {
-	return p.v.Interface().(*[]bool)
+
+// Set sets p to point at a newly allocated word with bits set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+	t := p.v.Type().Elem()
+	switch t {
+	case int32Type:
+		if len(o.int32s) == 0 {
+			o.int32s = make([]int32, uint32PoolSize)
+		}
+		o.int32s[0] = int32(x)
+		p.v.Set(reflect.ValueOf(&o.int32s[0]))
+		o.int32s = o.int32s[1:]
+		return
+	case uint32Type:
+		if len(o.uint32s) == 0 {
+			o.uint32s = make([]uint32, uint32PoolSize)
+		}
+		o.uint32s[0] = x
+		p.v.Set(reflect.ValueOf(&o.uint32s[0]))
+		o.uint32s = o.uint32s[1:]
+		return
+	case float32Type:
+		if len(o.float32s) == 0 {
+			o.float32s = make([]float32, uint32PoolSize)
+		}
+		o.float32s[0] = math.Float32frombits(x)
+		p.v.Set(reflect.ValueOf(&o.float32s[0]))
+		o.float32s = o.float32s[1:]
+		return
+	}
+
+	// must be enum
+	p.v.Set(reflect.New(t))
+	p.v.Elem().SetInt(int64(int32(x)))
 }
-func (p pointer) toFloat64() *float64 {
-	return p.v.Interface().(*float64)
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32_Get(p word32) uint32 {
+	elem := p.v.Elem()
+	switch elem.Kind() {
+	case reflect.Int32:
+		return uint32(elem.Int())
+	case reflect.Uint32:
+		return uint32(elem.Uint())
+	case reflect.Float32:
+		return math.Float32bits(float32(elem.Float()))
+	}
+	panic("unreachable")
 }
-func (p pointer) toFloat64Ptr() **float64 {
-	return p.v.Interface().(**float64)
+
+// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+	return word32{structPointer_field(p, f)}
 }
-func (p pointer) toFloat64Slice() *[]float64 {
-	return p.v.Interface().(*[]float64)
+
+// A word32Val represents a field of type int32, uint32, float32, or enum.
+// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
+type word32Val struct {
+	v reflect.Value
 }
-func (p pointer) toFloat32() *float32 {
-	return p.v.Interface().(*float32)
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+	switch p.v.Type() {
+	case int32Type:
+		p.v.SetInt(int64(x))
+		return
+	case uint32Type:
+		p.v.SetUint(uint64(x))
+		return
+	case float32Type:
+		p.v.SetFloat(float64(math.Float32frombits(x)))
+		return
+	}
+
+	// must be enum
+	p.v.SetInt(int64(int32(x)))
 }
-func (p pointer) toFloat32Ptr() **float32 {
-	return p.v.Interface().(**float32)
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32Val_Get(p word32Val) uint32 {
+	elem := p.v
+	switch elem.Kind() {
+	case reflect.Int32:
+		return uint32(elem.Int())
+	case reflect.Uint32:
+		return uint32(elem.Uint())
+	case reflect.Float32:
+		return math.Float32bits(float32(elem.Float()))
+	}
+	panic("unreachable")
 }
-func (p pointer) toFloat32Slice() *[]float32 {
-	return p.v.Interface().(*[]float32)
+
+// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+	return word32Val{structPointer_field(p, f)}
 }
-func (p pointer) toString() *string {
-	return p.v.Interface().(*string)
+
+// A word32Slice is a slice of 32-bit values.
+// That is, v.Type() is []int32, []uint32, []float32, or []enum.
+type word32Slice struct {
+	v reflect.Value
 }
-func (p pointer) toStringPtr() **string {
-	return p.v.Interface().(**string)
+
+func (p word32Slice) Append(x uint32) {
+	n, m := p.v.Len(), p.v.Cap()
+	if n < m {
+		p.v.SetLen(n + 1)
+	} else {
+		t := p.v.Type().Elem()
+		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+	}
+	elem := p.v.Index(n)
+	switch elem.Kind() {
+	case reflect.Int32:
+		elem.SetInt(int64(int32(x)))
+	case reflect.Uint32:
+		elem.SetUint(uint64(x))
+	case reflect.Float32:
+		elem.SetFloat(float64(math.Float32frombits(x)))
+	}
 }
-func (p pointer) toStringSlice() *[]string {
-	return p.v.Interface().(*[]string)
+
+func (p word32Slice) Len() int {
+	return p.v.Len()
 }
-func (p pointer) toBytes() *[]byte {
-	return p.v.Interface().(*[]byte)
+
+func (p word32Slice) Index(i int) uint32 {
+	elem := p.v.Index(i)
+	switch elem.Kind() {
+	case reflect.Int32:
+		return uint32(elem.Int())
+	case reflect.Uint32:
+		return uint32(elem.Uint())
+	case reflect.Float32:
+		return math.Float32bits(float32(elem.Float()))
+	}
+	panic("unreachable")
 }
-func (p pointer) toBytesSlice() *[][]byte {
-	return p.v.Interface().(*[][]byte)
+
+// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) word32Slice {
+	return word32Slice{structPointer_field(p, f)}
 }
-func (p pointer) toExtensions() *XXX_InternalExtensions {
-	return p.v.Interface().(*XXX_InternalExtensions)
+
+// word64 is like word32 but for 64-bit values.
+type word64 struct {
+	v reflect.Value
 }
-func (p pointer) toOldExtensions() *map[int32]Extension {
-	return p.v.Interface().(*map[int32]Extension)
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+	t := p.v.Type().Elem()
+	switch t {
+	case int64Type:
+		if len(o.int64s) == 0 {
+			o.int64s = make([]int64, uint64PoolSize)
+		}
+		o.int64s[0] = int64(x)
+		p.v.Set(reflect.ValueOf(&o.int64s[0]))
+		o.int64s = o.int64s[1:]
+		return
+	case uint64Type:
+		if len(o.uint64s) == 0 {
+			o.uint64s = make([]uint64, uint64PoolSize)
+		}
+		o.uint64s[0] = x
+		p.v.Set(reflect.ValueOf(&o.uint64s[0]))
+		o.uint64s = o.uint64s[1:]
+		return
+	case float64Type:
+		if len(o.float64s) == 0 {
+			o.float64s = make([]float64, uint64PoolSize)
+		}
+		o.float64s[0] = math.Float64frombits(x)
+		p.v.Set(reflect.ValueOf(&o.float64s[0]))
+		o.float64s = o.float64s[1:]
+		return
+	}
+	panic("unreachable")
 }
-func (p pointer) getPointer() pointer {
-	return pointer{v: p.v.Elem()}
+
+func word64_IsNil(p word64) bool {
+	return p.v.IsNil()
 }
-func (p pointer) setPointer(q pointer) {
-	p.v.Elem().Set(q.v)
+
+func word64_Get(p word64) uint64 {
+	elem := p.v.Elem()
+	switch elem.Kind() {
+	case reflect.Int64:
+		return uint64(elem.Int())
+	case reflect.Uint64:
+		return elem.Uint()
+	case reflect.Float64:
+		return math.Float64bits(elem.Float())
+	}
+	panic("unreachable")
 }
-func (p pointer) appendPointer(q pointer) {
-	grow(p.v.Elem()).Set(q.v)
+
+func structPointer_Word64(p structPointer, f field) word64 {
+	return word64{structPointer_field(p, f)}
 }
 
-// getPointerSlice copies []*T from p as a new []pointer.
-// This behavior differs from the implementation in pointer_unsafe.go.
-func (p pointer) getPointerSlice() []pointer {
-	if p.v.IsNil() {
-		return nil
-	}
-	n := p.v.Elem().Len()
-	s := make([]pointer, n)
-	for i := 0; i < n; i++ {
-		s[i] = pointer{v: p.v.Elem().Index(i)}
-	}
-	return s
+// word64Val is like word32Val but for 64-bit values.
+type word64Val struct {
+	v reflect.Value
 }
 
-// setPointerSlice copies []pointer into p as a new []*T.
-// This behavior differs from the implementation in pointer_unsafe.go.
-func (p pointer) setPointerSlice(v []pointer) {
-	if v == nil {
-		p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+	switch p.v.Type() {
+	case int64Type:
+		p.v.SetInt(int64(x))
+		return
+	case uint64Type:
+		p.v.SetUint(x)
+		return
+	case float64Type:
+		p.v.SetFloat(math.Float64frombits(x))
 		return
 	}
-	s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
-	for _, p := range v {
-		s = reflect.Append(s, p.v)
-	}
-	p.v.Elem().Set(s)
+	panic("unreachable")
 }
 
-// getInterfacePointer returns a pointer that points to the
-// interface data of the interface pointed by p.
-func (p pointer) getInterfacePointer() pointer {
-	if p.v.Elem().IsNil() {
-		return pointer{v: p.v.Elem()}
+func word64Val_Get(p word64Val) uint64 {
+	elem := p.v
+	switch elem.Kind() {
+	case reflect.Int64:
+		return uint64(elem.Int())
+	case reflect.Uint64:
+		return elem.Uint()
+	case reflect.Float64:
+		return math.Float64bits(elem.Float())
 	}
-	return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
+	panic("unreachable")
 }
 
-func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
-	// TODO: check that p.v.Type().Elem() == t?
-	return p.v
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+	return word64Val{structPointer_field(p, f)}
 }
 
-func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	return *p
-}
-func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	*p = v
-}
-func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	return *p
-}
-func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	*p = v
-}
-func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	return *p
+type word64Slice struct {
+	v reflect.Value
 }
-func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	*p = v
+
+func (p word64Slice) Append(x uint64) {
+	n, m := p.v.Len(), p.v.Cap()
+	if n < m {
+		p.v.SetLen(n + 1)
+	} else {
+		t := p.v.Type().Elem()
+		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+	}
+	elem := p.v.Index(n)
+	switch elem.Kind() {
+	case reflect.Int64:
+		elem.SetInt(int64(int64(x)))
+	case reflect.Uint64:
+		elem.SetUint(uint64(x))
+	case reflect.Float64:
+		elem.SetFloat(float64(math.Float64frombits(x)))
+	}
 }
-func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	return *p
+
+func (p word64Slice) Len() int {
+	return p.v.Len()
 }
-func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
-	atomicLock.Lock()
-	defer atomicLock.Unlock()
-	*p = v
+
+func (p word64Slice) Index(i int) uint64 {
+	elem := p.v.Index(i)
+	switch elem.Kind() {
+	case reflect.Int64:
+		return uint64(elem.Int())
+	case reflect.Uint64:
+		return uint64(elem.Uint())
+	case reflect.Float64:
+		return math.Float64bits(float64(elem.Float()))
+	}
+	panic("unreachable")
 }
 
-var atomicLock sync.Mutex
+func structPointer_Word64Slice(p structPointer, f field) word64Slice {
+	return word64Slice{structPointer_field(p, f)}
+}
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
index d55a335d9453204ae01c7c21d474efdbefa7d120..6b5567d47cd396b25370f8c06bad3b851776658f 100644
--- a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
+++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
@@ -29,7 +29,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// +build !purego,!appengine,!js
+// +build !appengine,!js
 
 // This file contains the implementation of the proto field accesses using package unsafe.
 
@@ -37,13 +37,38 @@ package proto
 
 import (
 	"reflect"
-	"sync/atomic"
 	"unsafe"
 )
 
-const unsafeAllowed = true
+// NOTE: These type_Foo functions would more idiomatically be methods,
+// but Go does not allow methods on pointer types, and we must preserve
+// some pointer type for the garbage collector. We use these
+// funcs with clunky names as our poor approximation to methods.
+//
+// An alternative would be
+//	type structPointer struct { p unsafe.Pointer }
+// but that does not registerize as well.
+
+// A structPointer is a pointer to a struct.
+type structPointer unsafe.Pointer
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+func toStructPointer(v reflect.Value) structPointer {
+	return structPointer(unsafe.Pointer(v.Pointer()))
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+	return p == nil
+}
+
+// Interface returns the struct pointer, assumed to have element type t,
+// as an interface value.
+func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
+	return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
+}
 
-// A field identifies a field in a struct, accessible from a pointer.
+// A field identifies a field in a struct, accessible from a structPointer.
 // In this implementation, a field is identified by its byte offset from the start of the struct.
 type field uintptr
 
@@ -55,254 +80,191 @@ func toField(f *reflect.StructField) field {
 // invalidField is an invalid field identifier.
 const invalidField = ^field(0)
 
-// zeroField is a noop when calling pointer.offset.
-const zeroField = field(0)
-
 // IsValid reports whether the field identifier is valid.
 func (f field) IsValid() bool {
-	return f != invalidField
+	return f != ^field(0)
 }
 
-// The pointer type below is for the new table-driven encoder/decoder.
-// The implementation here uses unsafe.Pointer to create a generic pointer.
-// In pointer_reflect.go we use reflect instead of unsafe to implement
-// the same (but slower) interface.
-type pointer struct {
-	p unsafe.Pointer
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+	return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// size of pointer
-var ptrSize = unsafe.Sizeof(uintptr(0))
-
-// toPointer converts an interface of pointer type to a pointer
-// that points to the same target.
-func toPointer(i *Message) pointer {
-	// Super-tricky - read pointer out of data word of interface value.
-	// Saves ~25ns over the equivalent:
-	// return valToPointer(reflect.ValueOf(*i))
-	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+	return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// toAddrPointer converts an interface to a pointer that points to
-// the interface data.
-func toAddrPointer(i *interface{}, isptr bool) pointer {
-	// Super-tricky - read or get the address of data word of interface value.
-	if isptr {
-		// The interface is of pointer type, thus it is a direct interface.
-		// The data word is the pointer data itself. We take its address.
-		return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
-	}
-	// The interface is not of pointer type. The data word is the pointer
-	// to the data.
-	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+	return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// valToPointer converts v to a pointer. v must be of pointer type.
-func valToPointer(v reflect.Value) pointer {
-	return pointer{p: unsafe.Pointer(v.Pointer())}
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+	return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// offset converts from a pointer to a structure to a pointer to
-// one of its fields.
-func (p pointer) offset(f field) pointer {
-	// For safety, we should panic if !f.IsValid, however calling panic causes
-	// this to no longer be inlineable, which is a serious performance cost.
-	/*
-		if !f.IsValid() {
-			panic("invalid field")
-		}
-	*/
-	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+	return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-func (p pointer) isNil() bool {
-	return p.p == nil
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+	return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-func (p pointer) toInt64() *int64 {
-	return (*int64)(p.p)
-}
-func (p pointer) toInt64Ptr() **int64 {
-	return (**int64)(p.p)
-}
-func (p pointer) toInt64Slice() *[]int64 {
-	return (*[]int64)(p.p)
-}
-func (p pointer) toInt32() *int32 {
-	return (*int32)(p.p)
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+	return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
-/*
-	func (p pointer) toInt32Ptr() **int32 {
-		return (**int32)(p.p)
-	}
-	func (p pointer) toInt32Slice() *[]int32 {
-		return (*[]int32)(p.p)
-	}
-*/
-func (p pointer) getInt32Ptr() *int32 {
-	return *(**int32)(p.p)
-}
-func (p pointer) setInt32Ptr(v int32) {
-	*(**int32)(p.p) = &v
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+	return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// getInt32Slice loads a []int32 from p.
-// The value returned is aliased with the original slice.
-// This behavior differs from the implementation in pointer_reflect.go.
-func (p pointer) getInt32Slice() []int32 {
-	return *(*[]int32)(p.p)
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+	return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// setInt32Slice stores a []int32 to p.
-// The value set is aliased with the input slice.
-// This behavior differs from the implementation in pointer_reflect.go.
-func (p pointer) setInt32Slice(v []int32) {
-	*(*[]int32)(p.p) = v
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+	return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
-func (p pointer) appendInt32Slice(v int32) {
-	s := (*[]int32)(p.p)
-	*s = append(*s, v)
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+	return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
 }
 
-func (p pointer) toUint64() *uint64 {
-	return (*uint64)(p.p)
-}
-func (p pointer) toUint64Ptr() **uint64 {
-	return (**uint64)(p.p)
-}
-func (p pointer) toUint64Slice() *[]uint64 {
-	return (*[]uint64)(p.p)
-}
-func (p pointer) toUint32() *uint32 {
-	return (*uint32)(p.p)
-}
-func (p pointer) toUint32Ptr() **uint32 {
-	return (**uint32)(p.p)
-}
-func (p pointer) toUint32Slice() *[]uint32 {
-	return (*[]uint32)(p.p)
-}
-func (p pointer) toBool() *bool {
-	return (*bool)(p.p)
-}
-func (p pointer) toBoolPtr() **bool {
-	return (**bool)(p.p)
-}
-func (p pointer) toBoolSlice() *[]bool {
-	return (*[]bool)(p.p)
-}
-func (p pointer) toFloat64() *float64 {
-	return (*float64)(p.p)
-}
-func (p pointer) toFloat64Ptr() **float64 {
-	return (**float64)(p.p)
-}
-func (p pointer) toFloat64Slice() *[]float64 {
-	return (*[]float64)(p.p)
-}
-func (p pointer) toFloat32() *float32 {
-	return (*float32)(p.p)
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+	*(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
 }
-func (p pointer) toFloat32Ptr() **float32 {
-	return (**float32)(p.p)
-}
-func (p pointer) toFloat32Slice() *[]float32 {
-	return (*[]float32)(p.p)
-}
-func (p pointer) toString() *string {
-	return (*string)(p.p)
-}
-func (p pointer) toStringPtr() **string {
-	return (**string)(p.p)
-}
-func (p pointer) toStringSlice() *[]string {
-	return (*[]string)(p.p)
-}
-func (p pointer) toBytes() *[]byte {
-	return (*[]byte)(p.p)
-}
-func (p pointer) toBytesSlice() *[][]byte {
-	return (*[][]byte)(p.p)
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+	return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
-func (p pointer) toExtensions() *XXX_InternalExtensions {
-	return (*XXX_InternalExtensions)(p.p)
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
+	return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
-func (p pointer) toOldExtensions() *map[int32]Extension {
-	return (*map[int32]Extension)(p.p)
+
+// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
+type structPointerSlice []structPointer
+
+func (v *structPointerSlice) Len() int                  { return len(*v) }
+func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
+func (v *structPointerSlice) Append(p structPointer)    { *v = append(*v, p) }
+
+// A word32 is the address of a "pointer to 32-bit value" field.
+type word32 **uint32
+
+// IsNil reports whether *v is nil.
+func word32_IsNil(p word32) bool {
+	return *p == nil
 }
 
-// getPointerSlice loads []*T from p as a []pointer.
-// The value returned is aliased with the original slice.
-// This behavior differs from the implementation in pointer_reflect.go.
-func (p pointer) getPointerSlice() []pointer {
-	// Super-tricky - p should point to a []*T where T is a
-	// message type. We load it as []pointer.
-	return *(*[]pointer)(p.p)
+// Set sets *v to point at a newly allocated word set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+	if len(o.uint32s) == 0 {
+		o.uint32s = make([]uint32, uint32PoolSize)
+	}
+	o.uint32s[0] = x
+	*p = &o.uint32s[0]
+	o.uint32s = o.uint32s[1:]
 }
 
-// setPointerSlice stores []pointer into p as a []*T.
-// The value set is aliased with the input slice.
-// This behavior differs from the implementation in pointer_reflect.go.
-func (p pointer) setPointerSlice(v []pointer) {
-	// Super-tricky - p should point to a []*T where T is a
-	// message type. We store it as []pointer.
-	*(*[]pointer)(p.p) = v
+// Get gets the value pointed at by *v.
+func word32_Get(p word32) uint32 {
+	return **p
 }
 
-// getPointer loads the pointer at p and returns it.
-func (p pointer) getPointer() pointer {
-	return pointer{p: *(*unsafe.Pointer)(p.p)}
+// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+	return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 }
 
-// setPointer stores the pointer q at p.
-func (p pointer) setPointer(q pointer) {
-	*(*unsafe.Pointer)(p.p) = q.p
+// A word32Val is the address of a 32-bit value field.
+type word32Val *uint32
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+	*p = x
 }
 
-// append q to the slice pointed to by p.
-func (p pointer) appendPointer(q pointer) {
-	s := (*[]unsafe.Pointer)(p.p)
-	*s = append(*s, q.p)
+// Get gets the value pointed at by p.
+func word32Val_Get(p word32Val) uint32 {
+	return *p
 }
 
-// getInterfacePointer returns a pointer that points to the
-// interface data of the interface pointed by p.
-func (p pointer) getInterfacePointer() pointer {
-	// Super-tricky - read pointer out of data word of interface value.
-	return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
+// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+	return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 }
 
-// asPointerTo returns a reflect.Value that is a pointer to an
-// object of type t stored at p.
-func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
-	return reflect.NewAt(t, p.p)
+// A word32Slice is a slice of 32-bit values.
+type word32Slice []uint32
+
+func (v *word32Slice) Append(x uint32)    { *v = append(*v, x) }
+func (v *word32Slice) Len() int           { return len(*v) }
+func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
+
+// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
+	return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
-	return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+// word64 is like word32 but for 64-bit values.
+type word64 **uint64
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+	if len(o.uint64s) == 0 {
+		o.uint64s = make([]uint64, uint64PoolSize)
+	}
+	o.uint64s[0] = x
+	*p = &o.uint64s[0]
+	o.uint64s = o.uint64s[1:]
 }
-func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
-	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+
+func word64_IsNil(p word64) bool {
+	return *p == nil
 }
-func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
-	return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+
+func word64_Get(p word64) uint64 {
+	return **p
 }
-func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
-	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+
+func structPointer_Word64(p structPointer, f field) word64 {
+	return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 }
-func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
-	return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val *uint64
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+	*p = x
 }
-func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
-	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+
+func word64Val_Get(p word64Val) uint64 {
+	return *p
 }
-func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
-	return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+	return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 }
-func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
-	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+
+// word64Slice is like word32Slice but for 64-bit values.
+type word64Slice []uint64
+
+func (v *word64Slice) Append(x uint64)    { *v = append(*v, x) }
+func (v *word64Slice) Len() int           { return len(*v) }
+func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+
+func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
+	return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go
index f710adab09246898d8c8dbee14a7268b27476246..ec2289c0058e47e3d20fa2bef7a3979529aa7512 100644
--- a/vendor/github.com/golang/protobuf/proto/properties.go
+++ b/vendor/github.com/golang/protobuf/proto/properties.go
@@ -58,6 +58,42 @@ const (
 	WireFixed32    = 5
 )
 
+const startSize = 10 // initial slice/string sizes
+
+// Encoders are defined in encode.go
+// An encoder outputs the full representation of a field, including its
+// tag and encoder type.
+type encoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueEncoder encodes a single integer in a particular encoding.
+type valueEncoder func(o *Buffer, x uint64) error
+
+// Sizers are defined in encode.go
+// A sizer returns the encoded size of a field, including its tag and encoder
+// type.
+type sizer func(prop *Properties, base structPointer) int
+
+// A valueSizer returns the encoded size of a single integer in a particular
+// encoding.
+type valueSizer func(x uint64) int
+
+// Decoders are defined in decode.go
+// A decoder creates a value from its wire representation.
+// Unrecognized subelements are saved in unrec.
+type decoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueDecoder decodes a single integer in a particular encoding.
+type valueDecoder func(o *Buffer) (x uint64, err error)
+
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
+// A oneofSizer does the sizing for all oneof fields in a message.
+type oneofSizer func(Message) int
+
 // tagMap is an optimization over map[int]int for typical protocol buffer
 // use-cases. Encoded protocol buffers are often in tag order with small tag
 // numbers.
@@ -104,6 +140,13 @@ type StructProperties struct {
 	decoderTags      tagMap         // map from proto tag to struct field number
 	decoderOrigNames map[string]int // map from original name to struct field number
 	order            []int          // list of struct field numbers in tag order
+	unrecField       field          // field id of the XXX_unrecognized []byte field
+	extendable       bool           // is this an extendable proto
+
+	oneofMarshaler   oneofMarshaler
+	oneofUnmarshaler oneofUnmarshaler
+	oneofSizer       oneofSizer
+	stype            reflect.Type
 
 	// OneofTypes contains information about the oneof fields in this message.
 	// It is keyed by the original name of a field.
@@ -144,19 +187,36 @@ type Properties struct {
 
 	Default    string // default value
 	HasDefault bool   // whether an explicit default was provided
-
-	stype reflect.Type      // set for struct types only
-	sprop *StructProperties // set for struct types only
+	def_uint64 uint64
+
+	enc           encoder
+	valEnc        valueEncoder // set for bool and numeric types only
+	field         field
+	tagcode       []byte // encoding of EncodeVarint((Tag<<3)|WireType)
+	tagbuf        [8]byte
+	stype         reflect.Type      // set for struct types only
+	sprop         *StructProperties // set for struct types only
+	isMarshaler   bool
+	isUnmarshaler bool
 
 	mtype    reflect.Type // set for map types only
 	mkeyprop *Properties  // set for map types only
 	mvalprop *Properties  // set for map types only
+
+	size    sizer
+	valSize valueSizer // set for bool and numeric types only
+
+	dec    decoder
+	valDec valueDecoder // set for bool and numeric types only
+
+	// If this is a packable field, this will be the decoder for the packed version of the field.
+	packedDec decoder
 }
 
 // String formats the properties in the protobuf struct field tag style.
 func (p *Properties) String() string {
 	s := p.Wire
-	s += ","
+	s = ","
 	s += strconv.Itoa(p.Tag)
 	if p.Required {
 		s += ",req"
@@ -202,14 +262,29 @@ func (p *Properties) Parse(s string) {
 	switch p.Wire {
 	case "varint":
 		p.WireType = WireVarint
+		p.valEnc = (*Buffer).EncodeVarint
+		p.valDec = (*Buffer).DecodeVarint
+		p.valSize = sizeVarint
 	case "fixed32":
 		p.WireType = WireFixed32
+		p.valEnc = (*Buffer).EncodeFixed32
+		p.valDec = (*Buffer).DecodeFixed32
+		p.valSize = sizeFixed32
 	case "fixed64":
 		p.WireType = WireFixed64
+		p.valEnc = (*Buffer).EncodeFixed64
+		p.valDec = (*Buffer).DecodeFixed64
+		p.valSize = sizeFixed64
 	case "zigzag32":
 		p.WireType = WireVarint
+		p.valEnc = (*Buffer).EncodeZigzag32
+		p.valDec = (*Buffer).DecodeZigzag32
+		p.valSize = sizeZigzag32
 	case "zigzag64":
 		p.WireType = WireVarint
+		p.valEnc = (*Buffer).EncodeZigzag64
+		p.valDec = (*Buffer).DecodeZigzag64
+		p.valSize = sizeZigzag64
 	case "bytes", "group":
 		p.WireType = WireBytes
 		// no numeric converter for non-numeric types
@@ -224,7 +299,6 @@ func (p *Properties) Parse(s string) {
 		return
 	}
 
-outer:
 	for i := 2; i < len(fields); i++ {
 		f := fields[i]
 		switch {
@@ -252,28 +326,229 @@ outer:
 			if i+1 < len(fields) {
 				// Commas aren't escaped, and def is always last.
 				p.Default += "," + strings.Join(fields[i+1:], ",")
-				break outer
+				break
 			}
 		}
 	}
 }
 
+func logNoSliceEnc(t1, t2 reflect.Type) {
+	fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
+}
+
 var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
 
-// setFieldProps initializes the field properties for submessages and maps.
-func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
+// Initialize the fields for encoding and decoding.
+func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
+	p.enc = nil
+	p.dec = nil
+	p.size = nil
+
 	switch t1 := typ; t1.Kind() {
+	default:
+		fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
+
+	// proto3 scalar types
+
+	case reflect.Bool:
+		p.enc = (*Buffer).enc_proto3_bool
+		p.dec = (*Buffer).dec_proto3_bool
+		p.size = size_proto3_bool
+	case reflect.Int32:
+		p.enc = (*Buffer).enc_proto3_int32
+		p.dec = (*Buffer).dec_proto3_int32
+		p.size = size_proto3_int32
+	case reflect.Uint32:
+		p.enc = (*Buffer).enc_proto3_uint32
+		p.dec = (*Buffer).dec_proto3_int32 // can reuse
+		p.size = size_proto3_uint32
+	case reflect.Int64, reflect.Uint64:
+		p.enc = (*Buffer).enc_proto3_int64
+		p.dec = (*Buffer).dec_proto3_int64
+		p.size = size_proto3_int64
+	case reflect.Float32:
+		p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
+		p.dec = (*Buffer).dec_proto3_int32
+		p.size = size_proto3_uint32
+	case reflect.Float64:
+		p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
+		p.dec = (*Buffer).dec_proto3_int64
+		p.size = size_proto3_int64
+	case reflect.String:
+		p.enc = (*Buffer).enc_proto3_string
+		p.dec = (*Buffer).dec_proto3_string
+		p.size = size_proto3_string
+
 	case reflect.Ptr:
-		if t1.Elem().Kind() == reflect.Struct {
+		switch t2 := t1.Elem(); t2.Kind() {
+		default:
+			fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
+			break
+		case reflect.Bool:
+			p.enc = (*Buffer).enc_bool
+			p.dec = (*Buffer).dec_bool
+			p.size = size_bool
+		case reflect.Int32:
+			p.enc = (*Buffer).enc_int32
+			p.dec = (*Buffer).dec_int32
+			p.size = size_int32
+		case reflect.Uint32:
+			p.enc = (*Buffer).enc_uint32
+			p.dec = (*Buffer).dec_int32 // can reuse
+			p.size = size_uint32
+		case reflect.Int64, reflect.Uint64:
+			p.enc = (*Buffer).enc_int64
+			p.dec = (*Buffer).dec_int64
+			p.size = size_int64
+		case reflect.Float32:
+			p.enc = (*Buffer).enc_uint32 // can just treat them as bits
+			p.dec = (*Buffer).dec_int32
+			p.size = size_uint32
+		case reflect.Float64:
+			p.enc = (*Buffer).enc_int64 // can just treat them as bits
+			p.dec = (*Buffer).dec_int64
+			p.size = size_int64
+		case reflect.String:
+			p.enc = (*Buffer).enc_string
+			p.dec = (*Buffer).dec_string
+			p.size = size_string
+		case reflect.Struct:
 			p.stype = t1.Elem()
+			p.isMarshaler = isMarshaler(t1)
+			p.isUnmarshaler = isUnmarshaler(t1)
+			if p.Wire == "bytes" {
+				p.enc = (*Buffer).enc_struct_message
+				p.dec = (*Buffer).dec_struct_message
+				p.size = size_struct_message
+			} else {
+				p.enc = (*Buffer).enc_struct_group
+				p.dec = (*Buffer).dec_struct_group
+				p.size = size_struct_group
+			}
 		}
 
 	case reflect.Slice:
-		if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
-			p.stype = t2.Elem()
+		switch t2 := t1.Elem(); t2.Kind() {
+		default:
+			logNoSliceEnc(t1, t2)
+			break
+		case reflect.Bool:
+			if p.Packed {
+				p.enc = (*Buffer).enc_slice_packed_bool
+				p.size = size_slice_packed_bool
+			} else {
+				p.enc = (*Buffer).enc_slice_bool
+				p.size = size_slice_bool
+			}
+			p.dec = (*Buffer).dec_slice_bool
+			p.packedDec = (*Buffer).dec_slice_packed_bool
+		case reflect.Int32:
+			if p.Packed {
+				p.enc = (*Buffer).enc_slice_packed_int32
+				p.size = size_slice_packed_int32
+			} else {
+				p.enc = (*Buffer).enc_slice_int32
+				p.size = size_slice_int32
+			}
+			p.dec = (*Buffer).dec_slice_int32
+			p.packedDec = (*Buffer).dec_slice_packed_int32
+		case reflect.Uint32:
+			if p.Packed {
+				p.enc = (*Buffer).enc_slice_packed_uint32
+				p.size = size_slice_packed_uint32
+			} else {
+				p.enc = (*Buffer).enc_slice_uint32
+				p.size = size_slice_uint32
+			}
+			p.dec = (*Buffer).dec_slice_int32
+			p.packedDec = (*Buffer).dec_slice_packed_int32
+		case reflect.Int64, reflect.Uint64:
+			if p.Packed {
+				p.enc = (*Buffer).enc_slice_packed_int64
+				p.size = size_slice_packed_int64
+			} else {
+				p.enc = (*Buffer).enc_slice_int64
+				p.size = size_slice_int64
+			}
+			p.dec = (*Buffer).dec_slice_int64
+			p.packedDec = (*Buffer).dec_slice_packed_int64
+		case reflect.Uint8:
+			p.dec = (*Buffer).dec_slice_byte
+			if p.proto3 {
+				p.enc = (*Buffer).enc_proto3_slice_byte
+				p.size = size_proto3_slice_byte
+			} else {
+				p.enc = (*Buffer).enc_slice_byte
+				p.size = size_slice_byte
+			}
+		case reflect.Float32, reflect.Float64:
+			switch t2.Bits() {
+			case 32:
+				// can just treat them as bits
+				if p.Packed {
+					p.enc = (*Buffer).enc_slice_packed_uint32
+					p.size = size_slice_packed_uint32
+				} else {
+					p.enc = (*Buffer).enc_slice_uint32
+					p.size = size_slice_uint32
+				}
+				p.dec = (*Buffer).dec_slice_int32
+				p.packedDec = (*Buffer).dec_slice_packed_int32
+			case 64:
+				// can just treat them as bits
+				if p.Packed {
+					p.enc = (*Buffer).enc_slice_packed_int64
+					p.size = size_slice_packed_int64
+				} else {
+					p.enc = (*Buffer).enc_slice_int64
+					p.size = size_slice_int64
+				}
+				p.dec = (*Buffer).dec_slice_int64
+				p.packedDec = (*Buffer).dec_slice_packed_int64
+			default:
+				logNoSliceEnc(t1, t2)
+				break
+			}
+		case reflect.String:
+			p.enc = (*Buffer).enc_slice_string
+			p.dec = (*Buffer).dec_slice_string
+			p.size = size_slice_string
+		case reflect.Ptr:
+			switch t3 := t2.Elem(); t3.Kind() {
+			default:
+				fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
+				break
+			case reflect.Struct:
+				p.stype = t2.Elem()
+				p.isMarshaler = isMarshaler(t2)
+				p.isUnmarshaler = isUnmarshaler(t2)
+				if p.Wire == "bytes" {
+					p.enc = (*Buffer).enc_slice_struct_message
+					p.dec = (*Buffer).dec_slice_struct_message
+					p.size = size_slice_struct_message
+				} else {
+					p.enc = (*Buffer).enc_slice_struct_group
+					p.dec = (*Buffer).dec_slice_struct_group
+					p.size = size_slice_struct_group
+				}
+			}
+		case reflect.Slice:
+			switch t2.Elem().Kind() {
+			default:
+				fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
+				break
+			case reflect.Uint8:
+				p.enc = (*Buffer).enc_slice_slice_byte
+				p.dec = (*Buffer).dec_slice_slice_byte
+				p.size = size_slice_slice_byte
+			}
 		}
 
 	case reflect.Map:
+		p.enc = (*Buffer).enc_new_map
+		p.dec = (*Buffer).dec_new_map
+		p.size = size_new_map
+
 		p.mtype = t1
 		p.mkeyprop = &Properties{}
 		p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
@@ -287,6 +562,20 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
 		p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
 	}
 
+	// precalculate tag code
+	wire := p.WireType
+	if p.Packed {
+		wire = WireBytes
+	}
+	x := uint32(p.Tag)<<3 | uint32(wire)
+	i := 0
+	for i = 0; x > 127; i++ {
+		p.tagbuf[i] = 0x80 | uint8(x&0x7F)
+		x >>= 7
+	}
+	p.tagbuf[i] = uint8(x)
+	p.tagcode = p.tagbuf[0 : i+1]
+
 	if p.stype != nil {
 		if lockGetProp {
 			p.sprop = GetProperties(p.stype)
@@ -297,9 +586,32 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
 }
 
 var (
-	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+	marshalerType   = reflect.TypeOf((*Marshaler)(nil)).Elem()
+	unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
 )
 
+// isMarshaler reports whether type t implements Marshaler.
+func isMarshaler(t reflect.Type) bool {
+	// We're checking for (likely) pointer-receiver methods
+	// so if t is not a pointer, something is very wrong.
+	// The calls above only invoke isMarshaler on pointer types.
+	if t.Kind() != reflect.Ptr {
+		panic("proto: misuse of isMarshaler")
+	}
+	return t.Implements(marshalerType)
+}
+
+// isUnmarshaler reports whether type t implements Unmarshaler.
+func isUnmarshaler(t reflect.Type) bool {
+	// We're checking for (likely) pointer-receiver methods
+	// so if t is not a pointer, something is very wrong.
+	// The calls above only invoke isUnmarshaler on pointer types.
+	if t.Kind() != reflect.Ptr {
+		panic("proto: misuse of isUnmarshaler")
+	}
+	return t.Implements(unmarshalerType)
+}
+
 // Init populates the properties from a protocol buffer struct tag.
 func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
 	p.init(typ, name, tag, f, true)
@@ -309,11 +621,14 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
 	// "bytes,49,opt,def=hello!"
 	p.Name = name
 	p.OrigName = name
+	if f != nil {
+		p.field = toField(f)
+	}
 	if tag == "" {
 		return
 	}
 	p.Parse(tag)
-	p.setFieldProps(typ, f, lockGetProp)
+	p.setEncAndDec(typ, f, lockGetProp)
 }
 
 var (
@@ -363,6 +678,9 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	propertiesMap[t] = prop
 
 	// build properties
+	prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
+		reflect.PtrTo(t).Implements(extendableProtoV1Type)
+	prop.unrecField = invalidField
 	prop.Prop = make([]*Properties, t.NumField())
 	prop.order = make([]int, t.NumField())
 
@@ -372,6 +690,17 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 		name := f.Name
 		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
 
+		if f.Name == "XXX_InternalExtensions" { // special case
+			p.enc = (*Buffer).enc_exts
+			p.dec = nil // not needed
+			p.size = size_exts
+		} else if f.Name == "XXX_extensions" { // special case
+			p.enc = (*Buffer).enc_map
+			p.dec = nil // not needed
+			p.size = size_map
+		} else if f.Name == "XXX_unrecognized" { // special case
+			prop.unrecField = toField(&f)
+		}
 		oneof := f.Tag.Get("protobuf_oneof") // special case
 		if oneof != "" {
 			// Oneof fields don't use the traditional protobuf tag.
@@ -386,6 +715,9 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 			}
 			print("\n")
 		}
+		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
+			fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
+		}
 	}
 
 	// Re-order prop.order.
@@ -396,7 +728,8 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	}
 	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
 		var oots []interface{}
-		_, _, _, oots = om.XXX_OneofFuncs()
+		prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
+		prop.stype = t
 
 		// Interpret oneof metadata.
 		prop.OneofTypes = make(map[string]*OneofProperties)
@@ -446,6 +779,30 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	return prop
 }
 
+// Return the Properties object for the x[0]'th field of the structure.
+func propByIndex(t reflect.Type, x []int) *Properties {
+	if len(x) != 1 {
+		fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
+		return nil
+	}
+	prop := GetProperties(t)
+	return prop.Prop[x[0]]
+}
+
+// Get the address and type of a pointer to a struct from an interface.
+func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
+	if pb == nil {
+		err = ErrNil
+		return
+	}
+	// get the reflect type of the pointer to the struct.
+	t = reflect.TypeOf(pb)
+	// get the address of the struct.
+	value := reflect.ValueOf(pb)
+	b = toStructPointer(value)
+	return
+}
+
 // A global registry of enum types.
 // The generated code will register the generated maps by calling RegisterEnum.
 
@@ -469,42 +826,20 @@ func EnumValueMap(enumType string) map[string]int32 {
 // A registry of all linked message types.
 // The string is a fully-qualified proto name ("pkg.Message").
 var (
-	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers
-	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types
-	revProtoTypes  = make(map[reflect.Type]string)
+	protoTypes    = make(map[string]reflect.Type)
+	revProtoTypes = make(map[reflect.Type]string)
 )
 
 // RegisterType is called from generated code and maps from the fully qualified
 // proto name to the type (pointer to struct) of the protocol buffer.
 func RegisterType(x Message, name string) {
-	if _, ok := protoTypedNils[name]; ok {
+	if _, ok := protoTypes[name]; ok {
 		// TODO: Some day, make this a panic.
 		log.Printf("proto: duplicate proto type registered: %s", name)
 		return
 	}
 	t := reflect.TypeOf(x)
-	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
-		// Generated code always calls RegisterType with nil x.
-		// This check is just for extra safety.
-		protoTypedNils[name] = x
-	} else {
-		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
-	}
-	revProtoTypes[t] = name
-}
-
-// RegisterMapType is called from generated code and maps from the fully qualified
-// proto name to the native map type of the proto map definition.
-func RegisterMapType(x interface{}, name string) {
-	if reflect.TypeOf(x).Kind() != reflect.Map {
-		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
-	}
-	if _, ok := protoMapTypes[name]; ok {
-		log.Printf("proto: duplicate proto type registered: %s", name)
-		return
-	}
-	t := reflect.TypeOf(x)
-	protoMapTypes[name] = t
+	protoTypes[name] = t
 	revProtoTypes[t] = name
 }
 
@@ -520,14 +855,7 @@ func MessageName(x Message) string {
 }
 
 // MessageType returns the message type (pointer to struct) for a named message.
-// The type is not guaranteed to implement proto.Message if the name refers to a
-// map entry.
-func MessageType(name string) reflect.Type {
-	if t, ok := protoTypedNils[name]; ok {
-		return reflect.TypeOf(t)
-	}
-	return protoMapTypes[name]
-}
+func MessageType(name string) reflect.Type { return protoTypes[name] }
 
 // A registry of all linked proto files.
 var (
diff --git a/vendor/github.com/golang/protobuf/proto/table_marshal.go b/vendor/github.com/golang/protobuf/proto/table_marshal.go
deleted file mode 100644
index 0f212b3029d2dca7c363da64de4db6853fe51159..0000000000000000000000000000000000000000
--- a/vendor/github.com/golang/protobuf/proto/table_marshal.go
+++ /dev/null
@@ -1,2681 +0,0 @@
-// Go support for Protocol Buffers - Google's data interchange format
-//
-// Copyright 2016 The Go Authors.  All rights reserved.
-// https://github.com/golang/protobuf
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package proto
-
-import (
-	"errors"
-	"fmt"
-	"math"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"unicode/utf8"
-)
-
-// a sizer takes a pointer to a field and the size of its tag, computes the size of
-// the encoded data.
-type sizer func(pointer, int) int
-
-// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format),
-// marshals the field to the end of the slice, returns the slice and error (if any).
-type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error)
-
-// marshalInfo is the information used for marshaling a message.
-type marshalInfo struct {
-	typ          reflect.Type
-	fields       []*marshalFieldInfo
-	unrecognized field                      // offset of XXX_unrecognized
-	extensions   field                      // offset of XXX_InternalExtensions
-	v1extensions field                      // offset of XXX_extensions
-	sizecache    field                      // offset of XXX_sizecache
-	initialized  int32                      // 0 -- only typ is set, 1 -- fully initialized
-	messageset   bool                       // uses message set wire format
-	hasmarshaler bool                       // has custom marshaler
-	sync.RWMutex                            // protect extElems map, also for initialization
-	extElems     map[int32]*marshalElemInfo // info of extension elements
-}
-
-// marshalFieldInfo is the information used for marshaling a field of a message.
-type marshalFieldInfo struct {
-	field      field
-	wiretag    uint64 // tag in wire format
-	tagsize    int    // size of tag in wire format
-	sizer      sizer
-	marshaler  marshaler
-	isPointer  bool
-	required   bool                              // field is required
-	name       string                            // name of the field, for error reporting
-	oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements
-}
-
-// marshalElemInfo is the information used for marshaling an extension or oneof element.
-type marshalElemInfo struct {
-	wiretag   uint64 // tag in wire format
-	tagsize   int    // size of tag in wire format
-	sizer     sizer
-	marshaler marshaler
-	isptr     bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
-}
-
-var (
-	marshalInfoMap  = map[reflect.Type]*marshalInfo{}
-	marshalInfoLock sync.Mutex
-)
-
-// getMarshalInfo returns the information to marshal a given type of message.
-// The info it returns may not necessarily initialized.
-// t is the type of the message (NOT the pointer to it).
-func getMarshalInfo(t reflect.Type) *marshalInfo {
-	marshalInfoLock.Lock()
-	u, ok := marshalInfoMap[t]
-	if !ok {
-		u = &marshalInfo{typ: t}
-		marshalInfoMap[t] = u
-	}
-	marshalInfoLock.Unlock()
-	return u
-}
-
-// Size is the entry point from generated code,
-// and should be ONLY called by generated code.
-// It computes the size of encoded data of msg.
-// a is a pointer to a place to store cached marshal info.
-func (a *InternalMessageInfo) Size(msg Message) int {
-	u := getMessageMarshalInfo(msg, a)
-	ptr := toPointer(&msg)
-	if ptr.isNil() {
-		// We get here if msg is a typed nil ((*SomeMessage)(nil)),
-		// so it satisfies the interface, and msg == nil wouldn't
-		// catch it. We don't want crash in this case.
-		return 0
-	}
-	return u.size(ptr)
-}
-
-// Marshal is the entry point from generated code,
-// and should be ONLY called by generated code.
-// It marshals msg to the end of b.
-// a is a pointer to a place to store cached marshal info.
-func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) {
-	u := getMessageMarshalInfo(msg, a)
-	ptr := toPointer(&msg)
-	if ptr.isNil() {
-		// We get here if msg is a typed nil ((*SomeMessage)(nil)),
-		// so it satisfies the interface, and msg == nil wouldn't
-		// catch it. We don't want crash in this case.
-		return b, ErrNil
-	}
-	return u.marshal(b, ptr, deterministic)
-}
-
-func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo {
-	// u := a.marshal, but atomically.
-	// We use an atomic here to ensure memory consistency.
-	u := atomicLoadMarshalInfo(&a.marshal)
-	if u == nil {
-		// Get marshal information from type of message.
-		t := reflect.ValueOf(msg).Type()
-		if t.Kind() != reflect.Ptr {
-			panic(fmt.Sprintf("cannot handle non-pointer message type %v", t))
-		}
-		u = getMarshalInfo(t.Elem())
-		// Store it in the cache for later users.
-		// a.marshal = u, but atomically.
-		atomicStoreMarshalInfo(&a.marshal, u)
-	}
-	return u
-}
-
-// size is the main function to compute the size of the encoded data of a message.
-// ptr is the pointer to the message.
-func (u *marshalInfo) size(ptr pointer) int {
-	if atomic.LoadInt32(&u.initialized) == 0 {
-		u.computeMarshalInfo()
-	}
-
-	// If the message can marshal itself, let it do it, for compatibility.
-	// NOTE: This is not efficient.
-	if u.hasmarshaler {
-		m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
-		b, _ := m.Marshal()
-		return len(b)
-	}
-
-	n := 0
-	for _, f := range u.fields {
-		if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
-			// nil pointer always marshals to nothing
-			continue
-		}
-		n += f.sizer(ptr.offset(f.field), f.tagsize)
-	}
-	if u.extensions.IsValid() {
-		e := ptr.offset(u.extensions).toExtensions()
-		if u.messageset {
-			n += u.sizeMessageSet(e)
-		} else {
-			n += u.sizeExtensions(e)
-		}
-	}
-	if u.v1extensions.IsValid() {
-		m := *ptr.offset(u.v1extensions).toOldExtensions()
-		n += u.sizeV1Extensions(m)
-	}
-	if u.unrecognized.IsValid() {
-		s := *ptr.offset(u.unrecognized).toBytes()
-		n += len(s)
-	}
-	// cache the result for use in marshal
-	if u.sizecache.IsValid() {
-		atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n))
-	}
-	return n
-}
-
-// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated),
-// fall back to compute the size.
-func (u *marshalInfo) cachedsize(ptr pointer) int {
-	if u.sizecache.IsValid() {
-		return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32()))
-	}
-	return u.size(ptr)
-}
-
-// marshal is the main function to marshal a message. It takes a byte slice and appends
-// the encoded data to the end of the slice, returns the slice and error (if any).
-// ptr is the pointer to the message.
-// If deterministic is true, map is marshaled in deterministic order.
-func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) {
-	if atomic.LoadInt32(&u.initialized) == 0 {
-		u.computeMarshalInfo()
-	}
-
-	// If the message can marshal itself, let it do it, for compatibility.
-	// NOTE: This is not efficient.
-	if u.hasmarshaler {
-		m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
-		b1, err := m.Marshal()
-		b = append(b, b1...)
-		return b, err
-	}
-
-	var err, errreq error
-	// The old marshaler encodes extensions at beginning.
-	if u.extensions.IsValid() {
-		e := ptr.offset(u.extensions).toExtensions()
-		if u.messageset {
-			b, err = u.appendMessageSet(b, e, deterministic)
-		} else {
-			b, err = u.appendExtensions(b, e, deterministic)
-		}
-		if err != nil {
-			return b, err
-		}
-	}
-	if u.v1extensions.IsValid() {
-		m := *ptr.offset(u.v1extensions).toOldExtensions()
-		b, err = u.appendV1Extensions(b, m, deterministic)
-		if err != nil {
-			return b, err
-		}
-	}
-	for _, f := range u.fields {
-		if f.required && errreq == nil {
-			if ptr.offset(f.field).getPointer().isNil() {
-				// Required field is not set.
-				// We record the error but keep going, to give a complete marshaling.
-				errreq = &RequiredNotSetError{f.name}
-				continue
-			}
-		}
-		if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
-			// nil pointer always marshals to nothing
-			continue
-		}
-		b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic)
-		if err != nil {
-			if err1, ok := err.(*RequiredNotSetError); ok {
-				// Required field in submessage is not set.
-				// We record the error but keep going, to give a complete marshaling.
-				if errreq == nil {
-					errreq = &RequiredNotSetError{f.name + "." + err1.field}
-				}
-				continue
-			}
-			if err == errRepeatedHasNil {
-				err = errors.New("proto: repeated field " + f.name + " has nil element")
-			}
-			return b, err
-		}
-	}
-	if u.unrecognized.IsValid() {
-		s := *ptr.offset(u.unrecognized).toBytes()
-		b = append(b, s...)
-	}
-	return b, errreq
-}
-
-// computeMarshalInfo initializes the marshal info.
-func (u *marshalInfo) computeMarshalInfo() {
-	u.Lock()
-	defer u.Unlock()
-	if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock
-		return
-	}
-
-	t := u.typ
-	u.unrecognized = invalidField
-	u.extensions = invalidField
-	u.v1extensions = invalidField
-	u.sizecache = invalidField
-
-	// If the message can marshal itself, let it do it, for compatibility.
-	// NOTE: This is not efficient.
-	if reflect.PtrTo(t).Implements(marshalerType) {
-		u.hasmarshaler = true
-		atomic.StoreInt32(&u.initialized, 1)
-		return
-	}
-
-	// get oneof implementers
-	var oneofImplementers []interface{}
-	if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
-		_, _, _, oneofImplementers = m.XXX_OneofFuncs()
-	}
-
-	n := t.NumField()
-
-	// deal with XXX fields first
-	for i := 0; i < t.NumField(); i++ {
-		f := t.Field(i)
-		if !strings.HasPrefix(f.Name, "XXX_") {
-			continue
-		}
-		switch f.Name {
-		case "XXX_sizecache":
-			u.sizecache = toField(&f)
-		case "XXX_unrecognized":
-			u.unrecognized = toField(&f)
-		case "XXX_InternalExtensions":
-			u.extensions = toField(&f)
-			u.messageset = f.Tag.Get("protobuf_messageset") == "1"
-		case "XXX_extensions":
-			u.v1extensions = toField(&f)
-		case "XXX_NoUnkeyedLiteral":
-			// nothing to do
-		default:
-			panic("unknown XXX field: " + f.Name)
-		}
-		n--
-	}
-
-	// normal fields
-	fields := make([]marshalFieldInfo, n) // batch allocation
-	u.fields = make([]*marshalFieldInfo, 0, n)
-	for i, j := 0, 0; i < t.NumField(); i++ {
-		f := t.Field(i)
-
-		if strings.HasPrefix(f.Name, "XXX_") {
-			continue
-		}
-		field := &fields[j]
-		j++
-		field.name = f.Name
-		u.fields = append(u.fields, field)
-		if f.Tag.Get("protobuf_oneof") != "" {
-			field.computeOneofFieldInfo(&f, oneofImplementers)
-			continue
-		}
-		if f.Tag.Get("protobuf") == "" {
-			// field has no tag (not in generated message), ignore it
-			u.fields = u.fields[:len(u.fields)-1]
-			j--
-			continue
-		}
-		field.computeMarshalFieldInfo(&f)
-	}
-
-	// fields are marshaled in tag order on the wire.
-	sort.Sort(byTag(u.fields))
-
-	atomic.StoreInt32(&u.initialized, 1)
-}
-
-// helper for sorting fields by tag
-type byTag []*marshalFieldInfo
-
-func (a byTag) Len() int           { return len(a) }
-func (a byTag) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag }
-
-// getExtElemInfo returns the information to marshal an extension element.
-// The info it returns is initialized.
-func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
-	// get from cache first
-	u.RLock()
-	e, ok := u.extElems[desc.Field]
-	u.RUnlock()
-	if ok {
-		return e
-	}
-
-	t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct
-	tags := strings.Split(desc.Tag, ",")
-	tag, err := strconv.Atoi(tags[1])
-	if err != nil {
-		panic("tag is not an integer")
-	}
-	wt := wiretype(tags[0])
-	sizer, marshaler := typeMarshaler(t, tags, false, false)
-	e = &marshalElemInfo{
-		wiretag:   uint64(tag)<<3 | wt,
-		tagsize:   SizeVarint(uint64(tag) << 3),
-		sizer:     sizer,
-		marshaler: marshaler,
-		isptr:     t.Kind() == reflect.Ptr,
-	}
-
-	// update cache
-	u.Lock()
-	if u.extElems == nil {
-		u.extElems = make(map[int32]*marshalElemInfo)
-	}
-	u.extElems[desc.Field] = e
-	u.Unlock()
-	return e
-}
-
-// computeMarshalFieldInfo fills up the information to marshal a field.
-func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
-	// parse protobuf tag of the field.
-	// tag has format of "bytes,49,opt,name=foo,def=hello!"
-	tags := strings.Split(f.Tag.Get("protobuf"), ",")
-	if tags[0] == "" {
-		return
-	}
-	tag, err := strconv.Atoi(tags[1])
-	if err != nil {
-		panic("tag is not an integer")
-	}
-	wt := wiretype(tags[0])
-	if tags[2] == "req" {
-		fi.required = true
-	}
-	fi.setTag(f, tag, wt)
-	fi.setMarshaler(f, tags)
-}
-
-func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
-	fi.field = toField(f)
-	fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
-	fi.isPointer = true
-	fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
-	fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
-
-	ityp := f.Type // interface type
-	for _, o := range oneofImplementers {
-		t := reflect.TypeOf(o)
-		if !t.Implements(ityp) {
-			continue
-		}
-		sf := t.Elem().Field(0) // oneof implementer is a struct with a single field
-		tags := strings.Split(sf.Tag.Get("protobuf"), ",")
-		tag, err := strconv.Atoi(tags[1])
-		if err != nil {
-			panic("tag is not an integer")
-		}
-		wt := wiretype(tags[0])
-		sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value
-		fi.oneofElems[t.Elem()] = &marshalElemInfo{
-			wiretag:   uint64(tag)<<3 | wt,
-			tagsize:   SizeVarint(uint64(tag) << 3),
-			sizer:     sizer,
-			marshaler: marshaler,
-		}
-	}
-}
-
-type oneofMessage interface {
-	XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
-}
-
-// wiretype returns the wire encoding of the type.
-func wiretype(encoding string) uint64 {
-	switch encoding {
-	case "fixed32":
-		return WireFixed32
-	case "fixed64":
-		return WireFixed64
-	case "varint", "zigzag32", "zigzag64":
-		return WireVarint
-	case "bytes":
-		return WireBytes
-	case "group":
-		return WireStartGroup
-	}
-	panic("unknown wire type " + encoding)
-}
-
-// setTag fills up the tag (in wire format) and its size in the info of a field.
-func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) {
-	fi.field = toField(f)
-	fi.wiretag = uint64(tag)<<3 | wt
-	fi.tagsize = SizeVarint(uint64(tag) << 3)
-}
-
-// setMarshaler fills up the sizer and marshaler in the info of a field.
-func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) {
-	switch f.Type.Kind() {
-	case reflect.Map:
-		// map field
-		fi.isPointer = true
-		fi.sizer, fi.marshaler = makeMapMarshaler(f)
-		return
-	case reflect.Ptr, reflect.Slice:
-		fi.isPointer = true
-	}
-	fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false)
-}
-
-// typeMarshaler returns the sizer and marshaler of a given field.
-// t is the type of the field.
-// tags is the generated "protobuf" tag of the field.
-// If nozero is true, zero value is not marshaled to the wire.
-// If oneof is true, it is a oneof field.
-func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) {
-	encoding := tags[0]
-
-	pointer := false
-	slice := false
-	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
-		slice = true
-		t = t.Elem()
-	}
-	if t.Kind() == reflect.Ptr {
-		pointer = true
-		t = t.Elem()
-	}
-
-	packed := false
-	proto3 := false
-	for i := 2; i < len(tags); i++ {
-		if tags[i] == "packed" {
-			packed = true
-		}
-		if tags[i] == "proto3" {
-			proto3 = true
-		}
-	}
-
-	switch t.Kind() {
-	case reflect.Bool:
-		if pointer {
-			return sizeBoolPtr, appendBoolPtr
-		}
-		if slice {
-			if packed {
-				return sizeBoolPackedSlice, appendBoolPackedSlice
-			}
-			return sizeBoolSlice, appendBoolSlice
-		}
-		if nozero {
-			return sizeBoolValueNoZero, appendBoolValueNoZero
-		}
-		return sizeBoolValue, appendBoolValue
-	case reflect.Uint32:
-		switch encoding {
-		case "fixed32":
-			if pointer {
-				return sizeFixed32Ptr, appendFixed32Ptr
-			}
-			if slice {
-				if packed {
-					return sizeFixed32PackedSlice, appendFixed32PackedSlice
-				}
-				return sizeFixed32Slice, appendFixed32Slice
-			}
-			if nozero {
-				return sizeFixed32ValueNoZero, appendFixed32ValueNoZero
-			}
-			return sizeFixed32Value, appendFixed32Value
-		case "varint":
-			if pointer {
-				return sizeVarint32Ptr, appendVarint32Ptr
-			}
-			if slice {
-				if packed {
-					return sizeVarint32PackedSlice, appendVarint32PackedSlice
-				}
-				return sizeVarint32Slice, appendVarint32Slice
-			}
-			if nozero {
-				return sizeVarint32ValueNoZero, appendVarint32ValueNoZero
-			}
-			return sizeVarint32Value, appendVarint32Value
-		}
-	case reflect.Int32:
-		switch encoding {
-		case "fixed32":
-			if pointer {
-				return sizeFixedS32Ptr, appendFixedS32Ptr
-			}
-			if slice {
-				if packed {
-					return sizeFixedS32PackedSlice, appendFixedS32PackedSlice
-				}
-				return sizeFixedS32Slice, appendFixedS32Slice
-			}
-			if nozero {
-				return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero
-			}
-			return sizeFixedS32Value, appendFixedS32Value
-		case "varint":
-			if pointer {
-				return sizeVarintS32Ptr, appendVarintS32Ptr
-			}
-			if slice {
-				if packed {
-					return sizeVarintS32PackedSlice, appendVarintS32PackedSlice
-				}
-				return sizeVarintS32Slice, appendVarintS32Slice
-			}
-			if nozero {
-				return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero
-			}
-			return sizeVarintS32Value, appendVarintS32Value
-		case "zigzag32":
-			if pointer {
-				return sizeZigzag32Ptr, appendZigzag32Ptr
-			}
-			if slice {
-				if packed {
-					return sizeZigzag32PackedSlice, appendZigzag32PackedSlice
-				}
-				return sizeZigzag32Slice, appendZigzag32Slice
-			}
-			if nozero {
-				return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero
-			}
-			return sizeZigzag32Value, appendZigzag32Value
-		}
-	case reflect.Uint64:
-		switch encoding {
-		case "fixed64":
-			if pointer {
-				return sizeFixed64Ptr, appendFixed64Ptr
-			}
-			if slice {
-				if packed {
-					return sizeFixed64PackedSlice, appendFixed64PackedSlice
-				}
-				return sizeFixed64Slice, appendFixed64Slice
-			}
-			if nozero {
-				return sizeFixed64ValueNoZero, appendFixed64ValueNoZero
-			}
-			return sizeFixed64Value, appendFixed64Value
-		case "varint":
-			if pointer {
-				return sizeVarint64Ptr, appendVarint64Ptr
-			}
-			if slice {
-				if packed {
-					return sizeVarint64PackedSlice, appendVarint64PackedSlice
-				}
-				return sizeVarint64Slice, appendVarint64Slice
-			}
-			if nozero {
-				return sizeVarint64ValueNoZero, appendVarint64ValueNoZero
-			}
-			return sizeVarint64Value, appendVarint64Value
-		}
-	case reflect.Int64:
-		switch encoding {
-		case "fixed64":
-			if pointer {
-				return sizeFixedS64Ptr, appendFixedS64Ptr
-			}
-			if slice {
-				if packed {
-					return sizeFixedS64PackedSlice, appendFixedS64PackedSlice
-				}
-				return sizeFixedS64Slice, appendFixedS64Slice
-			}
-			if nozero {
-				return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero
-			}
-			return sizeFixedS64Value, appendFixedS64Value
-		case "varint":
-			if pointer {
-				return sizeVarintS64Ptr, appendVarintS64Ptr
-			}
-			if slice {
-				if packed {
-					return sizeVarintS64PackedSlice, appendVarintS64PackedSlice
-				}
-				return sizeVarintS64Slice, appendVarintS64Slice
-			}
-			if nozero {
-				return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero
-			}
-			return sizeVarintS64Value, appendVarintS64Value
-		case "zigzag64":
-			if pointer {
-				return sizeZigzag64Ptr, appendZigzag64Ptr
-			}
-			if slice {
-				if packed {
-					return sizeZigzag64PackedSlice, appendZigzag64PackedSlice
-				}
-				return sizeZigzag64Slice, appendZigzag64Slice
-			}
-			if nozero {
-				return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero
-			}
-			return sizeZigzag64Value, appendZigzag64Value
-		}
-	case reflect.Float32:
-		if pointer {
-			return sizeFloat32Ptr, appendFloat32Ptr
-		}
-		if slice {
-			if packed {
-				return sizeFloat32PackedSlice, appendFloat32PackedSlice
-			}
-			return sizeFloat32Slice, appendFloat32Slice
-		}
-		if nozero {
-			return sizeFloat32ValueNoZero, appendFloat32ValueNoZero
-		}
-		return sizeFloat32Value, appendFloat32Value
-	case reflect.Float64:
-		if pointer {
-			return sizeFloat64Ptr, appendFloat64Ptr
-		}
-		if slice {
-			if packed {
-				return sizeFloat64PackedSlice, appendFloat64PackedSlice
-			}
-			return sizeFloat64Slice, appendFloat64Slice
-		}
-		if nozero {
-			return sizeFloat64ValueNoZero, appendFloat64ValueNoZero
-		}
-		return sizeFloat64Value, appendFloat64Value
-	case reflect.String:
-		if pointer {
-			return sizeStringPtr, appendStringPtr
-		}
-		if slice {
-			return sizeStringSlice, appendStringSlice
-		}
-		if nozero {
-			return sizeStringValueNoZero, appendStringValueNoZero
-		}
-		return sizeStringValue, appendStringValue
-	case reflect.Slice:
-		if slice {
-			return sizeBytesSlice, appendBytesSlice
-		}
-		if oneof {
-			// Oneof bytes field may also have "proto3" tag.
-			// We want to marshal it as a oneof field. Do this
-			// check before the proto3 check.
-			return sizeBytesOneof, appendBytesOneof
-		}
-		if proto3 {
-			return sizeBytes3, appendBytes3
-		}
-		return sizeBytes, appendBytes
-	case reflect.Struct:
-		switch encoding {
-		case "group":
-			if slice {
-				return makeGroupSliceMarshaler(getMarshalInfo(t))
-			}
-			return makeGroupMarshaler(getMarshalInfo(t))
-		case "bytes":
-			if slice {
-				return makeMessageSliceMarshaler(getMarshalInfo(t))
-			}
-			return makeMessageMarshaler(getMarshalInfo(t))
-		}
-	}
-	panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding))
-}
-
-// Below are functions to size/marshal a specific type of a field.
-// They are stored in the field's info, and called by function pointers.
-// They have type sizer or marshaler.
-
-func sizeFixed32Value(_ pointer, tagsize int) int {
-	return 4 + tagsize
-}
-func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toUint32()
-	if v == 0 {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFixed32Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toUint32Ptr()
-	if p == nil {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFixed32Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint32Slice()
-	return (4 + tagsize) * len(s)
-}
-func sizeFixed32PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
-}
-func sizeFixedS32Value(_ pointer, tagsize int) int {
-	return 4 + tagsize
-}
-func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFixedS32Ptr(ptr pointer, tagsize int) int {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFixedS32Slice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	return (4 + tagsize) * len(s)
-}
-func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
-}
-func sizeFloat32Value(_ pointer, tagsize int) int {
-	return 4 + tagsize
-}
-func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int {
-	v := math.Float32bits(*ptr.toFloat32())
-	if v == 0 {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFloat32Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toFloat32Ptr()
-	if p == nil {
-		return 0
-	}
-	return 4 + tagsize
-}
-func sizeFloat32Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toFloat32Slice()
-	return (4 + tagsize) * len(s)
-}
-func sizeFloat32PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toFloat32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
-}
-func sizeFixed64Value(_ pointer, tagsize int) int {
-	return 8 + tagsize
-}
-func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toUint64()
-	if v == 0 {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFixed64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toUint64Ptr()
-	if p == nil {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFixed64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint64Slice()
-	return (8 + tagsize) * len(s)
-}
-func sizeFixed64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
-}
-func sizeFixedS64Value(_ pointer, tagsize int) int {
-	return 8 + tagsize
-}
-func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFixedS64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFixedS64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	return (8 + tagsize) * len(s)
-}
-func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
-}
-func sizeFloat64Value(_ pointer, tagsize int) int {
-	return 8 + tagsize
-}
-func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int {
-	v := math.Float64bits(*ptr.toFloat64())
-	if v == 0 {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFloat64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toFloat64Ptr()
-	if p == nil {
-		return 0
-	}
-	return 8 + tagsize
-}
-func sizeFloat64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toFloat64Slice()
-	return (8 + tagsize) * len(s)
-}
-func sizeFloat64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toFloat64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
-}
-func sizeVarint32Value(ptr pointer, tagsize int) int {
-	v := *ptr.toUint32()
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toUint32()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarint32Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toUint32Ptr()
-	if p == nil {
-		return 0
-	}
-	return SizeVarint(uint64(*p)) + tagsize
-}
-func sizeVarint32Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint32Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v)) + tagsize
-	}
-	return n
-}
-func sizeVarint32PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeVarintS32Value(ptr pointer, tagsize int) int {
-	v := *ptr.toInt32()
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarintS32Ptr(ptr pointer, tagsize int) int {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return 0
-	}
-	return SizeVarint(uint64(*p)) + tagsize
-}
-func sizeVarintS32Slice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v)) + tagsize
-	}
-	return n
-}
-func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeVarint64Value(ptr pointer, tagsize int) int {
-	v := *ptr.toUint64()
-	return SizeVarint(v) + tagsize
-}
-func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toUint64()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(v) + tagsize
-}
-func sizeVarint64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toUint64Ptr()
-	if p == nil {
-		return 0
-	}
-	return SizeVarint(*p) + tagsize
-}
-func sizeVarint64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint64Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(v) + tagsize
-	}
-	return n
-}
-func sizeVarint64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toUint64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(v)
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeVarintS64Value(ptr pointer, tagsize int) int {
-	v := *ptr.toInt64()
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(uint64(v)) + tagsize
-}
-func sizeVarintS64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return 0
-	}
-	return SizeVarint(uint64(*p)) + tagsize
-}
-func sizeVarintS64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v)) + tagsize
-	}
-	return n
-}
-func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeZigzag32Value(ptr pointer, tagsize int) int {
-	v := *ptr.toInt32()
-	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
-}
-func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
-}
-func sizeZigzag32Ptr(ptr pointer, tagsize int) int {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return 0
-	}
-	v := *p
-	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
-}
-func sizeZigzag32Slice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
-	}
-	return n
-}
-func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeZigzag64Value(ptr pointer, tagsize int) int {
-	v := *ptr.toInt64()
-	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
-}
-func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return 0
-	}
-	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
-}
-func sizeZigzag64Ptr(ptr pointer, tagsize int) int {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return 0
-	}
-	v := *p
-	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
-}
-func sizeZigzag64Slice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
-	}
-	return n
-}
-func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return 0
-	}
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
-	}
-	return n + SizeVarint(uint64(n)) + tagsize
-}
-func sizeBoolValue(_ pointer, tagsize int) int {
-	return 1 + tagsize
-}
-func sizeBoolValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toBool()
-	if !v {
-		return 0
-	}
-	return 1 + tagsize
-}
-func sizeBoolPtr(ptr pointer, tagsize int) int {
-	p := *ptr.toBoolPtr()
-	if p == nil {
-		return 0
-	}
-	return 1 + tagsize
-}
-func sizeBoolSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toBoolSlice()
-	return (1 + tagsize) * len(s)
-}
-func sizeBoolPackedSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toBoolSlice()
-	if len(s) == 0 {
-		return 0
-	}
-	return len(s) + SizeVarint(uint64(len(s))) + tagsize
-}
-func sizeStringValue(ptr pointer, tagsize int) int {
-	v := *ptr.toString()
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeStringValueNoZero(ptr pointer, tagsize int) int {
-	v := *ptr.toString()
-	if v == "" {
-		return 0
-	}
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeStringPtr(ptr pointer, tagsize int) int {
-	p := *ptr.toStringPtr()
-	if p == nil {
-		return 0
-	}
-	v := *p
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeStringSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toStringSlice()
-	n := 0
-	for _, v := range s {
-		n += len(v) + SizeVarint(uint64(len(v))) + tagsize
-	}
-	return n
-}
-func sizeBytes(ptr pointer, tagsize int) int {
-	v := *ptr.toBytes()
-	if v == nil {
-		return 0
-	}
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeBytes3(ptr pointer, tagsize int) int {
-	v := *ptr.toBytes()
-	if len(v) == 0 {
-		return 0
-	}
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeBytesOneof(ptr pointer, tagsize int) int {
-	v := *ptr.toBytes()
-	return len(v) + SizeVarint(uint64(len(v))) + tagsize
-}
-func sizeBytesSlice(ptr pointer, tagsize int) int {
-	s := *ptr.toBytesSlice()
-	n := 0
-	for _, v := range s {
-		n += len(v) + SizeVarint(uint64(len(v))) + tagsize
-	}
-	return n
-}
-
-// appendFixed32 appends an encoded fixed32 to b.
-func appendFixed32(b []byte, v uint32) []byte {
-	b = append(b,
-		byte(v),
-		byte(v>>8),
-		byte(v>>16),
-		byte(v>>24))
-	return b
-}
-
-// appendFixed64 appends an encoded fixed64 to b.
-func appendFixed64(b []byte, v uint64) []byte {
-	b = append(b,
-		byte(v),
-		byte(v>>8),
-		byte(v>>16),
-		byte(v>>24),
-		byte(v>>32),
-		byte(v>>40),
-		byte(v>>48),
-		byte(v>>56))
-	return b
-}
-
-// appendVarint appends an encoded varint to b.
-func appendVarint(b []byte, v uint64) []byte {
-	// TODO: make 1-byte (maybe 2-byte) case inline-able, once we
-	// have non-leaf inliner.
-	switch {
-	case v < 1<<7:
-		b = append(b, byte(v))
-	case v < 1<<14:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte(v>>7))
-	case v < 1<<21:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte(v>>14))
-	case v < 1<<28:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte(v>>21))
-	case v < 1<<35:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte(v>>28))
-	case v < 1<<42:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte((v>>28)&0x7f|0x80),
-			byte(v>>35))
-	case v < 1<<49:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte((v>>28)&0x7f|0x80),
-			byte((v>>35)&0x7f|0x80),
-			byte(v>>42))
-	case v < 1<<56:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte((v>>28)&0x7f|0x80),
-			byte((v>>35)&0x7f|0x80),
-			byte((v>>42)&0x7f|0x80),
-			byte(v>>49))
-	case v < 1<<63:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte((v>>28)&0x7f|0x80),
-			byte((v>>35)&0x7f|0x80),
-			byte((v>>42)&0x7f|0x80),
-			byte((v>>49)&0x7f|0x80),
-			byte(v>>56))
-	default:
-		b = append(b,
-			byte(v&0x7f|0x80),
-			byte((v>>7)&0x7f|0x80),
-			byte((v>>14)&0x7f|0x80),
-			byte((v>>21)&0x7f|0x80),
-			byte((v>>28)&0x7f|0x80),
-			byte((v>>35)&0x7f|0x80),
-			byte((v>>42)&0x7f|0x80),
-			byte((v>>49)&0x7f|0x80),
-			byte((v>>56)&0x7f|0x80),
-			1)
-	}
-	return b
-}
-
-func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint32()
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, v)
-	return b, nil
-}
-func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint32()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, v)
-	return b, nil
-}
-func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toUint32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, *p)
-	return b, nil
-}
-func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed32(b, v)
-	}
-	return b, nil
-}
-func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(4*len(s)))
-	for _, v := range s {
-		b = appendFixed32(b, v)
-	}
-	return b, nil
-}
-func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, uint32(v))
-	return b, nil
-}
-func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, uint32(v))
-	return b, nil
-}
-func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, uint32(*p))
-	return b, nil
-}
-func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed32(b, uint32(v))
-	}
-	return b, nil
-}
-func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(4*len(s)))
-	for _, v := range s {
-		b = appendFixed32(b, uint32(v))
-	}
-	return b, nil
-}
-func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := math.Float32bits(*ptr.toFloat32())
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, v)
-	return b, nil
-}
-func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := math.Float32bits(*ptr.toFloat32())
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, v)
-	return b, nil
-}
-func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toFloat32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed32(b, math.Float32bits(*p))
-	return b, nil
-}
-func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toFloat32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed32(b, math.Float32bits(v))
-	}
-	return b, nil
-}
-func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toFloat32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(4*len(s)))
-	for _, v := range s {
-		b = appendFixed32(b, math.Float32bits(v))
-	}
-	return b, nil
-}
-func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint64()
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, v)
-	return b, nil
-}
-func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint64()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, v)
-	return b, nil
-}
-func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toUint64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, *p)
-	return b, nil
-}
-func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed64(b, v)
-	}
-	return b, nil
-}
-func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(8*len(s)))
-	for _, v := range s {
-		b = appendFixed64(b, v)
-	}
-	return b, nil
-}
-func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, uint64(v))
-	return b, nil
-}
-func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, uint64(v))
-	return b, nil
-}
-func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, uint64(*p))
-	return b, nil
-}
-func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed64(b, uint64(v))
-	}
-	return b, nil
-}
-func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(8*len(s)))
-	for _, v := range s {
-		b = appendFixed64(b, uint64(v))
-	}
-	return b, nil
-}
-func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := math.Float64bits(*ptr.toFloat64())
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, v)
-	return b, nil
-}
-func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := math.Float64bits(*ptr.toFloat64())
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, v)
-	return b, nil
-}
-func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toFloat64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendFixed64(b, math.Float64bits(*p))
-	return b, nil
-}
-func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toFloat64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendFixed64(b, math.Float64bits(v))
-	}
-	return b, nil
-}
-func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toFloat64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(8*len(s)))
-	for _, v := range s {
-		b = appendFixed64(b, math.Float64bits(v))
-	}
-	return b, nil
-}
-func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint32()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint32()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toUint32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(*p))
-	return b, nil
-}
-func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(*p))
-	return b, nil
-}
-func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint64()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, v)
-	return b, nil
-}
-func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toUint64()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, v)
-	return b, nil
-}
-func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toUint64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, *p)
-	return b, nil
-}
-func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, v)
-	}
-	return b, nil
-}
-func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toUint64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(v)
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, v)
-	}
-	return b, nil
-}
-func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v))
-	return b, nil
-}
-func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(*p))
-	return b, nil
-}
-func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v))
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, uint64(v))
-	}
-	return b, nil
-}
-func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
-	return b, nil
-}
-func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt32()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
-	return b, nil
-}
-func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := ptr.getInt32Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	v := *p
-	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
-	return b, nil
-}
-func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
-	}
-	return b, nil
-}
-func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := ptr.getInt32Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
-	}
-	return b, nil
-}
-func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
-	return b, nil
-}
-func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toInt64()
-	if v == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
-	return b, nil
-}
-func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toInt64Ptr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	v := *p
-	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
-	return b, nil
-}
-func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
-	}
-	return b, nil
-}
-func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toInt64Slice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	// compute size
-	n := 0
-	for _, v := range s {
-		n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
-	}
-	b = appendVarint(b, uint64(n))
-	for _, v := range s {
-		b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
-	}
-	return b, nil
-}
-func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toBool()
-	b = appendVarint(b, wiretag)
-	if v {
-		b = append(b, 1)
-	} else {
-		b = append(b, 0)
-	}
-	return b, nil
-}
-func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toBool()
-	if !v {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = append(b, 1)
-	return b, nil
-}
-
-func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toBoolPtr()
-	if p == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	if *p {
-		b = append(b, 1)
-	} else {
-		b = append(b, 0)
-	}
-	return b, nil
-}
-func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toBoolSlice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		if v {
-			b = append(b, 1)
-		} else {
-			b = append(b, 0)
-		}
-	}
-	return b, nil
-}
-func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toBoolSlice()
-	if len(s) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag&^7|WireBytes)
-	b = appendVarint(b, uint64(len(s)))
-	for _, v := range s {
-		if v {
-			b = append(b, 1)
-		} else {
-			b = append(b, 0)
-		}
-	}
-	return b, nil
-}
-func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toString()
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toString()
-	if v == "" {
-		return b, nil
-	}
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	p := *ptr.toStringPtr()
-	if p == nil {
-		return b, nil
-	}
-	v := *p
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toStringSlice()
-	for _, v := range s {
-		if !utf8.ValidString(v) {
-			return nil, errInvalidUTF8
-		}
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(len(v)))
-		b = append(b, v...)
-	}
-	return b, nil
-}
-func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toBytes()
-	if v == nil {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toBytes()
-	if len(v) == 0 {
-		return b, nil
-	}
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	v := *ptr.toBytes()
-	b = appendVarint(b, wiretag)
-	b = appendVarint(b, uint64(len(v)))
-	b = append(b, v...)
-	return b, nil
-}
-func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
-	s := *ptr.toBytesSlice()
-	for _, v := range s {
-		b = appendVarint(b, wiretag)
-		b = appendVarint(b, uint64(len(v)))
-		b = append(b, v...)
-	}
-	return b, nil
-}
-
-// makeGroupMarshaler returns the sizer and marshaler for a group.
-// u is the marshal info of the underlying message.
-func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) {
-	return func(ptr pointer, tagsize int) int {
-			p := ptr.getPointer()
-			if p.isNil() {
-				return 0
-			}
-			return u.size(p) + 2*tagsize
-		},
-		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
-			p := ptr.getPointer()
-			if p.isNil() {
-				return b, nil
-			}
-			var err error
-			b = appendVarint(b, wiretag) // start group
-			b, err = u.marshal(b, p, deterministic)
-			b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
-			return b, err
-		}
-}
-
-// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice.
-// u is the marshal info of the underlying message.
-func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
-	return func(ptr pointer, tagsize int) int {
-			s := ptr.getPointerSlice()
-			n := 0
-			for _, v := range s {
-				if v.isNil() {
-					continue
-				}
-				n += u.size(v) + 2*tagsize
-			}
-			return n
-		},
-		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
-			s := ptr.getPointerSlice()
-			var err, errreq error
-			for _, v := range s {
-				if v.isNil() {
-					return b, errRepeatedHasNil
-				}
-				b = appendVarint(b, wiretag) // start group
-				b, err = u.marshal(b, v, deterministic)
-				b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
-				if err != nil {
-					if _, ok := err.(*RequiredNotSetError); ok {
-						// Required field in submessage is not set.
-						// We record the error but keep going, to give a complete marshaling.
-						if errreq == nil {
-							errreq = err
-						}
-						continue
-					}
-					if err == ErrNil {
-						err = errRepeatedHasNil
-					}
-					return b, err
-				}
-			}
-			return b, errreq
-		}
-}
-
-// makeMessageMarshaler returns the sizer and marshaler for a message field.
-// u is the marshal info of the message.
-func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) {
-	return func(ptr pointer, tagsize int) int {
-			p := ptr.getPointer()
-			if p.isNil() {
-				return 0
-			}
-			siz := u.size(p)
-			return siz + SizeVarint(uint64(siz)) + tagsize
-		},
-		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
-			p := ptr.getPointer()
-			if p.isNil() {
-				return b, nil
-			}
-			b = appendVarint(b, wiretag)
-			siz := u.cachedsize(p)
-			b = appendVarint(b, uint64(siz))
-			return u.marshal(b, p, deterministic)
-		}
-}
-
-// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice.
-// u is the marshal info of the message.
-func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
-	return func(ptr pointer, tagsize int) int {
-			s := ptr.getPointerSlice()
-			n := 0
-			for _, v := range s {
-				if v.isNil() {
-					continue
-				}
-				siz := u.size(v)
-				n += siz + SizeVarint(uint64(siz)) + tagsize
-			}
-			return n
-		},
-		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
-			s := ptr.getPointerSlice()
-			var err, errreq error
-			for _, v := range s {
-				if v.isNil() {
-					return b, errRepeatedHasNil
-				}
-				b = appendVarint(b, wiretag)
-				siz := u.cachedsize(v)
-				b = appendVarint(b, uint64(siz))
-				b, err = u.marshal(b, v, deterministic)
-
-				if err != nil {
-					if _, ok := err.(*RequiredNotSetError); ok {
-						// Required field in submessage is not set.
-						// We record the error but keep going, to give a complete marshaling.
-						if errreq == nil {
-							errreq = err
-						}
-						continue
-					}
-					if err == ErrNil {
-						err = errRepeatedHasNil
-					}
-					return b, err
-				}
-			}
-			return b, errreq
-		}
-}
-
-// makeMapMarshaler returns the sizer and marshaler for a map field.
-// f is the pointer to the reflect data structure of the field.
-func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
-	// figure out key and value type
-	t := f.Type
-	keyType := t.Key()
-	valType := t.Elem()
-	keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
-	valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
-	keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
-	valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map
-	keyWireTag := 1<<3 | wiretype(keyTags[0])
-	valWireTag := 2<<3 | wiretype(valTags[0])
-
-	// We create an interface to get the addresses of the map key and value.
-	// If value is pointer-typed, the interface is a direct interface, the
-	// idata itself is the value. Otherwise, the idata is the pointer to the
-	// value.
-	// Key cannot be pointer-typed.
-	valIsPtr := valType.Kind() == reflect.Ptr
-	return func(ptr pointer, tagsize int) int {
-			m := ptr.asPointerTo(t).Elem() // the map
-			n := 0
-			for _, k := range m.MapKeys() {
-				ki := k.Interface()
-				vi := m.MapIndex(k).Interface()
-				kaddr := toAddrPointer(&ki, false)             // pointer to key
-				vaddr := toAddrPointer(&vi, valIsPtr)          // pointer to value
-				siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
-				n += siz + SizeVarint(uint64(siz)) + tagsize
-			}
-			return n
-		},
-		func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) {
-			m := ptr.asPointerTo(t).Elem() // the map
-			var err error
-			keys := m.MapKeys()
-			if len(keys) > 1 && deterministic {
-				sort.Sort(mapKeys(keys))
-			}
-			for _, k := range keys {
-				ki := k.Interface()
-				vi := m.MapIndex(k).Interface()
-				kaddr := toAddrPointer(&ki, false)    // pointer to key
-				vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
-				b = appendVarint(b, tag)
-				siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
-				b = appendVarint(b, uint64(siz))
-				b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
-				if err != nil {
-					return b, err
-				}
-				b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
-				if err != nil && err != ErrNil { // allow nil value in map
-					return b, err
-				}
-			}
-			return b, nil
-		}
-}
-
-// makeOneOfMarshaler returns the sizer and marshaler for a oneof field.
-// fi is the marshal info of the field.
-// f is the pointer to the reflect data structure of the field.
-func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) {
-	// Oneof field is an interface. We need to get the actual data type on the fly.
-	t := f.Type
-	return func(ptr pointer, _ int) int {
-			p := ptr.getInterfacePointer()
-			if p.isNil() {
-				return 0
-			}
-			v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
-			telem := v.Type()
-			e := fi.oneofElems[telem]
-			return e.sizer(p, e.tagsize)
-		},
-		func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) {
-			p := ptr.getInterfacePointer()
-			if p.isNil() {
-				return b, nil
-			}
-			v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
-			telem := v.Type()
-			if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() {
-				return b, errOneofHasNil
-			}
-			e := fi.oneofElems[telem]
-			return e.marshaler(b, p, e.wiretag, deterministic)
-		}
-}
-
-// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field.
-func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
-	m, mu := ext.extensionsRead()
-	if m == nil {
-		return 0
-	}
-	mu.Lock()
-
-	n := 0
-	for _, e := range m {
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			n += len(e.enc)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		n += ei.sizer(p, ei.tagsize)
-	}
-	mu.Unlock()
-	return n
-}
-
-// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b.
-func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
-	m, mu := ext.extensionsRead()
-	if m == nil {
-		return b, nil
-	}
-	mu.Lock()
-	defer mu.Unlock()
-
-	var err error
-
-	// Fast-path for common cases: zero or one extensions.
-	// Don't bother sorting the keys.
-	if len(m) <= 1 {
-		for _, e := range m {
-			if e.value == nil || e.desc == nil {
-				// Extension is only in its encoded form.
-				b = append(b, e.enc...)
-				continue
-			}
-
-			// We don't skip extensions that have an encoded form set,
-			// because the extension value may have been mutated after
-			// the last time this function was called.
-
-			ei := u.getExtElemInfo(e.desc)
-			v := e.value
-			p := toAddrPointer(&v, ei.isptr)
-			b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
-			if err != nil {
-				return b, err
-			}
-		}
-		return b, nil
-	}
-
-	// Sort the keys to provide a deterministic encoding.
-	// Not sure this is required, but the old code does it.
-	keys := make([]int, 0, len(m))
-	for k := range m {
-		keys = append(keys, int(k))
-	}
-	sort.Ints(keys)
-
-	for _, k := range keys {
-		e := m[int32(k)]
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			b = append(b, e.enc...)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
-		if err != nil {
-			return b, err
-		}
-	}
-	return b, nil
-}
-
-// message set format is:
-//   message MessageSet {
-//     repeated group Item = 1 {
-//       required int32 type_id = 2;
-//       required string message = 3;
-//     };
-//   }
-
-// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field
-// in message set format (above).
-func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
-	m, mu := ext.extensionsRead()
-	if m == nil {
-		return 0
-	}
-	mu.Lock()
-
-	n := 0
-	for id, e := range m {
-		n += 2                          // start group, end group. tag = 1 (size=1)
-		n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1)
-
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
-			siz := len(msgWithLen)
-			n += siz + 1 // message, tag = 3 (size=1)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		n += ei.sizer(p, 1) // message, tag = 3 (size=1)
-	}
-	mu.Unlock()
-	return n
-}
-
-// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above)
-// to the end of byte slice b.
-func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
-	m, mu := ext.extensionsRead()
-	if m == nil {
-		return b, nil
-	}
-	mu.Lock()
-	defer mu.Unlock()
-
-	var err error
-
-	// Fast-path for common cases: zero or one extensions.
-	// Don't bother sorting the keys.
-	if len(m) <= 1 {
-		for id, e := range m {
-			b = append(b, 1<<3|WireStartGroup)
-			b = append(b, 2<<3|WireVarint)
-			b = appendVarint(b, uint64(id))
-
-			if e.value == nil || e.desc == nil {
-				// Extension is only in its encoded form.
-				msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
-				b = append(b, 3<<3|WireBytes)
-				b = append(b, msgWithLen...)
-				b = append(b, 1<<3|WireEndGroup)
-				continue
-			}
-
-			// We don't skip extensions that have an encoded form set,
-			// because the extension value may have been mutated after
-			// the last time this function was called.
-
-			ei := u.getExtElemInfo(e.desc)
-			v := e.value
-			p := toAddrPointer(&v, ei.isptr)
-			b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
-			if err != nil {
-				return b, err
-			}
-			b = append(b, 1<<3|WireEndGroup)
-		}
-		return b, nil
-	}
-
-	// Sort the keys to provide a deterministic encoding.
-	keys := make([]int, 0, len(m))
-	for k := range m {
-		keys = append(keys, int(k))
-	}
-	sort.Ints(keys)
-
-	for _, id := range keys {
-		e := m[int32(id)]
-		b = append(b, 1<<3|WireStartGroup)
-		b = append(b, 2<<3|WireVarint)
-		b = appendVarint(b, uint64(id))
-
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
-			b = append(b, 3<<3|WireBytes)
-			b = append(b, msgWithLen...)
-			b = append(b, 1<<3|WireEndGroup)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
-		b = append(b, 1<<3|WireEndGroup)
-		if err != nil {
-			return b, err
-		}
-	}
-	return b, nil
-}
-
-// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
-func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
-	if m == nil {
-		return 0
-	}
-
-	n := 0
-	for _, e := range m {
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			n += len(e.enc)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		n += ei.sizer(p, ei.tagsize)
-	}
-	return n
-}
-
-// appendV1Extensions marshals a V1-API extension field to the end of byte slice b.
-func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) {
-	if m == nil {
-		return b, nil
-	}
-
-	// Sort the keys to provide a deterministic encoding.
-	keys := make([]int, 0, len(m))
-	for k := range m {
-		keys = append(keys, int(k))
-	}
-	sort.Ints(keys)
-
-	var err error
-	for _, k := range keys {
-		e := m[int32(k)]
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			b = append(b, e.enc...)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		ei := u.getExtElemInfo(e.desc)
-		v := e.value
-		p := toAddrPointer(&v, ei.isptr)
-		b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
-		if err != nil {
-			return b, err
-		}
-	}
-	return b, nil
-}
-
-// newMarshaler is the interface representing objects that can marshal themselves.
-//
-// This exists to support protoc-gen-go generated messages.
-// The proto package will stop type-asserting to this interface in the future.
-//
-// DO NOT DEPEND ON THIS.
-type newMarshaler interface {
-	XXX_Size() int
-	XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
-}
-
-// Size returns the encoded size of a protocol buffer message.
-// This is the main entry point.
-func Size(pb Message) int {
-	if m, ok := pb.(newMarshaler); ok {
-		return m.XXX_Size()
-	}
-	if m, ok := pb.(Marshaler); ok {
-		// If the message can marshal itself, let it do it, for compatibility.
-		// NOTE: This is not efficient.
-		b, _ := m.Marshal()
-		return len(b)
-	}
-	// in case somehow we didn't generate the wrapper
-	if pb == nil {
-		return 0
-	}
-	var info InternalMessageInfo
-	return info.Size(pb)
-}
-
-// Marshal takes a protocol buffer message
-// and encodes it into the wire format, returning the data.
-// This is the main entry point.
-func Marshal(pb Message) ([]byte, error) {
-	if m, ok := pb.(newMarshaler); ok {
-		siz := m.XXX_Size()
-		b := make([]byte, 0, siz)
-		return m.XXX_Marshal(b, false)
-	}
-	if m, ok := pb.(Marshaler); ok {
-		// If the message can marshal itself, let it do it, for compatibility.
-		// NOTE: This is not efficient.
-		return m.Marshal()
-	}
-	// in case somehow we didn't generate the wrapper
-	if pb == nil {
-		return nil, ErrNil
-	}
-	var info InternalMessageInfo
-	siz := info.Size(pb)
-	b := make([]byte, 0, siz)
-	return info.Marshal(b, pb, false)
-}
-
-// Marshal takes a protocol buffer message
-// and encodes it into the wire format, writing the result to the
-// Buffer.
-// This is an alternative entry point. It is not necessary to use
-// a Buffer for most applications.
-func (p *Buffer) Marshal(pb Message) error {
-	var err error
-	if m, ok := pb.(newMarshaler); ok {
-		siz := m.XXX_Size()
-		p.grow(siz) // make sure buf has enough capacity
-		p.buf, err = m.XXX_Marshal(p.buf, p.deterministic)
-		return err
-	}
-	if m, ok := pb.(Marshaler); ok {
-		// If the message can marshal itself, let it do it, for compatibility.
-		// NOTE: This is not efficient.
-		b, err := m.Marshal()
-		p.buf = append(p.buf, b...)
-		return err
-	}
-	// in case somehow we didn't generate the wrapper
-	if pb == nil {
-		return ErrNil
-	}
-	var info InternalMessageInfo
-	siz := info.Size(pb)
-	p.grow(siz) // make sure buf has enough capacity
-	p.buf, err = info.Marshal(p.buf, pb, p.deterministic)
-	return err
-}
-
-// grow grows the buffer's capacity, if necessary, to guarantee space for
-// another n bytes. After grow(n), at least n bytes can be written to the
-// buffer without another allocation.
-func (p *Buffer) grow(n int) {
-	need := len(p.buf) + n
-	if need <= cap(p.buf) {
-		return
-	}
-	newCap := len(p.buf) * 2
-	if newCap < need {
-		newCap = need
-	}
-	p.buf = append(make([]byte, 0, newCap), p.buf...)
-}
diff --git a/vendor/github.com/golang/protobuf/proto/table_merge.go b/vendor/github.com/golang/protobuf/proto/table_merge.go
deleted file mode 100644
index 5525def6a5da89fee6a0528924cefdbc5ef987e1..0000000000000000000000000000000000000000
--- a/vendor/github.com/golang/protobuf/proto/table_merge.go
+++ /dev/null
@@ -1,654 +0,0 @@
-// Go support for Protocol Buffers - Google's data interchange format
-//
-// Copyright 2016 The Go Authors.  All rights reserved.
-// https://github.com/golang/protobuf
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package proto
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-	"sync"
-	"sync/atomic"
-)
-
-// Merge merges the src message into dst.
-// This assumes that dst and src of the same type and are non-nil.
-func (a *InternalMessageInfo) Merge(dst, src Message) {
-	mi := atomicLoadMergeInfo(&a.merge)
-	if mi == nil {
-		mi = getMergeInfo(reflect.TypeOf(dst).Elem())
-		atomicStoreMergeInfo(&a.merge, mi)
-	}
-	mi.merge(toPointer(&dst), toPointer(&src))
-}
-
-type mergeInfo struct {
-	typ reflect.Type
-
-	initialized int32 // 0: only typ is valid, 1: everything is valid
-	lock        sync.Mutex
-
-	fields       []mergeFieldInfo
-	unrecognized field // Offset of XXX_unrecognized
-}
-
-type mergeFieldInfo struct {
-	field field // Offset of field, guaranteed to be valid
-
-	// isPointer reports whether the value in the field is a pointer.
-	// This is true for the following situations:
-	//	* Pointer to struct
-	//	* Pointer to basic type (proto2 only)
-	//	* Slice (first value in slice header is a pointer)
-	//	* String (first value in string header is a pointer)
-	isPointer bool
-
-	// basicWidth reports the width of the field assuming that it is directly
-	// embedded in the struct (as is the case for basic types in proto3).
-	// The possible values are:
-	// 	0: invalid
-	//	1: bool
-	//	4: int32, uint32, float32
-	//	8: int64, uint64, float64
-	basicWidth int
-
-	// Where dst and src are pointers to the types being merged.
-	merge func(dst, src pointer)
-}
-
-var (
-	mergeInfoMap  = map[reflect.Type]*mergeInfo{}
-	mergeInfoLock sync.Mutex
-)
-
-func getMergeInfo(t reflect.Type) *mergeInfo {
-	mergeInfoLock.Lock()
-	defer mergeInfoLock.Unlock()
-	mi := mergeInfoMap[t]
-	if mi == nil {
-		mi = &mergeInfo{typ: t}
-		mergeInfoMap[t] = mi
-	}
-	return mi
-}
-
-// merge merges src into dst assuming they are both of type *mi.typ.
-func (mi *mergeInfo) merge(dst, src pointer) {
-	if dst.isNil() {
-		panic("proto: nil destination")
-	}
-	if src.isNil() {
-		return // Nothing to do.
-	}
-
-	if atomic.LoadInt32(&mi.initialized) == 0 {
-		mi.computeMergeInfo()
-	}
-
-	for _, fi := range mi.fields {
-		sfp := src.offset(fi.field)
-
-		// As an optimization, we can avoid the merge function call cost
-		// if we know for sure that the source will have no effect
-		// by checking if it is the zero value.
-		if unsafeAllowed {
-			if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
-				continue
-			}
-			if fi.basicWidth > 0 {
-				switch {
-				case fi.basicWidth == 1 && !*sfp.toBool():
-					continue
-				case fi.basicWidth == 4 && *sfp.toUint32() == 0:
-					continue
-				case fi.basicWidth == 8 && *sfp.toUint64() == 0:
-					continue
-				}
-			}
-		}
-
-		dfp := dst.offset(fi.field)
-		fi.merge(dfp, sfp)
-	}
-
-	// TODO: Make this faster?
-	out := dst.asPointerTo(mi.typ).Elem()
-	in := src.asPointerTo(mi.typ).Elem()
-	if emIn, err := extendable(in.Addr().Interface()); err == nil {
-		emOut, _ := extendable(out.Addr().Interface())
-		mIn, muIn := emIn.extensionsRead()
-		if mIn != nil {
-			mOut := emOut.extensionsWrite()
-			muIn.Lock()
-			mergeExtension(mOut, mIn)
-			muIn.Unlock()
-		}
-	}
-
-	if mi.unrecognized.IsValid() {
-		if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
-			*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
-		}
-	}
-}
-
-func (mi *mergeInfo) computeMergeInfo() {
-	mi.lock.Lock()
-	defer mi.lock.Unlock()
-	if mi.initialized != 0 {
-		return
-	}
-	t := mi.typ
-	n := t.NumField()
-
-	props := GetProperties(t)
-	for i := 0; i < n; i++ {
-		f := t.Field(i)
-		if strings.HasPrefix(f.Name, "XXX_") {
-			continue
-		}
-
-		mfi := mergeFieldInfo{field: toField(&f)}
-		tf := f.Type
-
-		// As an optimization, we can avoid the merge function call cost
-		// if we know for sure that the source will have no effect
-		// by checking if it is the zero value.
-		if unsafeAllowed {
-			switch tf.Kind() {
-			case reflect.Ptr, reflect.Slice, reflect.String:
-				// As a special case, we assume slices and strings are pointers
-				// since we know that the first field in the SliceSlice or
-				// StringHeader is a data pointer.
-				mfi.isPointer = true
-			case reflect.Bool:
-				mfi.basicWidth = 1
-			case reflect.Int32, reflect.Uint32, reflect.Float32:
-				mfi.basicWidth = 4
-			case reflect.Int64, reflect.Uint64, reflect.Float64:
-				mfi.basicWidth = 8
-			}
-		}
-
-		// Unwrap tf to get at its most basic type.
-		var isPointer, isSlice bool
-		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
-			isSlice = true
-			tf = tf.Elem()
-		}
-		if tf.Kind() == reflect.Ptr {
-			isPointer = true
-			tf = tf.Elem()
-		}
-		if isPointer && isSlice && tf.Kind() != reflect.Struct {
-			panic("both pointer and slice for basic type in " + tf.Name())
-		}
-
-		switch tf.Kind() {
-		case reflect.Int32:
-			switch {
-			case isSlice: // E.g., []int32
-				mfi.merge = func(dst, src pointer) {
-					// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
-					/*
-						sfsp := src.toInt32Slice()
-						if *sfsp != nil {
-							dfsp := dst.toInt32Slice()
-							*dfsp = append(*dfsp, *sfsp...)
-							if *dfsp == nil {
-								*dfsp = []int64{}
-							}
-						}
-					*/
-					sfs := src.getInt32Slice()
-					if sfs != nil {
-						dfs := dst.getInt32Slice()
-						dfs = append(dfs, sfs...)
-						if dfs == nil {
-							dfs = []int32{}
-						}
-						dst.setInt32Slice(dfs)
-					}
-				}
-			case isPointer: // E.g., *int32
-				mfi.merge = func(dst, src pointer) {
-					// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
-					/*
-						sfpp := src.toInt32Ptr()
-						if *sfpp != nil {
-							dfpp := dst.toInt32Ptr()
-							if *dfpp == nil {
-								*dfpp = Int32(**sfpp)
-							} else {
-								**dfpp = **sfpp
-							}
-						}
-					*/
-					sfp := src.getInt32Ptr()
-					if sfp != nil {
-						dfp := dst.getInt32Ptr()
-						if dfp == nil {
-							dst.setInt32Ptr(*sfp)
-						} else {
-							*dfp = *sfp
-						}
-					}
-				}
-			default: // E.g., int32
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toInt32(); v != 0 {
-						*dst.toInt32() = v
-					}
-				}
-			}
-		case reflect.Int64:
-			switch {
-			case isSlice: // E.g., []int64
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toInt64Slice()
-					if *sfsp != nil {
-						dfsp := dst.toInt64Slice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []int64{}
-						}
-					}
-				}
-			case isPointer: // E.g., *int64
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toInt64Ptr()
-					if *sfpp != nil {
-						dfpp := dst.toInt64Ptr()
-						if *dfpp == nil {
-							*dfpp = Int64(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., int64
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toInt64(); v != 0 {
-						*dst.toInt64() = v
-					}
-				}
-			}
-		case reflect.Uint32:
-			switch {
-			case isSlice: // E.g., []uint32
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toUint32Slice()
-					if *sfsp != nil {
-						dfsp := dst.toUint32Slice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []uint32{}
-						}
-					}
-				}
-			case isPointer: // E.g., *uint32
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toUint32Ptr()
-					if *sfpp != nil {
-						dfpp := dst.toUint32Ptr()
-						if *dfpp == nil {
-							*dfpp = Uint32(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., uint32
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toUint32(); v != 0 {
-						*dst.toUint32() = v
-					}
-				}
-			}
-		case reflect.Uint64:
-			switch {
-			case isSlice: // E.g., []uint64
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toUint64Slice()
-					if *sfsp != nil {
-						dfsp := dst.toUint64Slice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []uint64{}
-						}
-					}
-				}
-			case isPointer: // E.g., *uint64
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toUint64Ptr()
-					if *sfpp != nil {
-						dfpp := dst.toUint64Ptr()
-						if *dfpp == nil {
-							*dfpp = Uint64(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., uint64
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toUint64(); v != 0 {
-						*dst.toUint64() = v
-					}
-				}
-			}
-		case reflect.Float32:
-			switch {
-			case isSlice: // E.g., []float32
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toFloat32Slice()
-					if *sfsp != nil {
-						dfsp := dst.toFloat32Slice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []float32{}
-						}
-					}
-				}
-			case isPointer: // E.g., *float32
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toFloat32Ptr()
-					if *sfpp != nil {
-						dfpp := dst.toFloat32Ptr()
-						if *dfpp == nil {
-							*dfpp = Float32(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., float32
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toFloat32(); v != 0 {
-						*dst.toFloat32() = v
-					}
-				}
-			}
-		case reflect.Float64:
-			switch {
-			case isSlice: // E.g., []float64
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toFloat64Slice()
-					if *sfsp != nil {
-						dfsp := dst.toFloat64Slice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []float64{}
-						}
-					}
-				}
-			case isPointer: // E.g., *float64
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toFloat64Ptr()
-					if *sfpp != nil {
-						dfpp := dst.toFloat64Ptr()
-						if *dfpp == nil {
-							*dfpp = Float64(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., float64
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toFloat64(); v != 0 {
-						*dst.toFloat64() = v
-					}
-				}
-			}
-		case reflect.Bool:
-			switch {
-			case isSlice: // E.g., []bool
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toBoolSlice()
-					if *sfsp != nil {
-						dfsp := dst.toBoolSlice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []bool{}
-						}
-					}
-				}
-			case isPointer: // E.g., *bool
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toBoolPtr()
-					if *sfpp != nil {
-						dfpp := dst.toBoolPtr()
-						if *dfpp == nil {
-							*dfpp = Bool(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., bool
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toBool(); v {
-						*dst.toBool() = v
-					}
-				}
-			}
-		case reflect.String:
-			switch {
-			case isSlice: // E.g., []string
-				mfi.merge = func(dst, src pointer) {
-					sfsp := src.toStringSlice()
-					if *sfsp != nil {
-						dfsp := dst.toStringSlice()
-						*dfsp = append(*dfsp, *sfsp...)
-						if *dfsp == nil {
-							*dfsp = []string{}
-						}
-					}
-				}
-			case isPointer: // E.g., *string
-				mfi.merge = func(dst, src pointer) {
-					sfpp := src.toStringPtr()
-					if *sfpp != nil {
-						dfpp := dst.toStringPtr()
-						if *dfpp == nil {
-							*dfpp = String(**sfpp)
-						} else {
-							**dfpp = **sfpp
-						}
-					}
-				}
-			default: // E.g., string
-				mfi.merge = func(dst, src pointer) {
-					if v := *src.toString(); v != "" {
-						*dst.toString() = v
-					}
-				}
-			}
-		case reflect.Slice:
-			isProto3 := props.Prop[i].proto3
-			switch {
-			case isPointer:
-				panic("bad pointer in byte slice case in " + tf.Name())
-			case tf.Elem().Kind() != reflect.Uint8:
-				panic("bad element kind in byte slice case in " + tf.Name())
-			case isSlice: // E.g., [][]byte
-				mfi.merge = func(dst, src pointer) {
-					sbsp := src.toBytesSlice()
-					if *sbsp != nil {
-						dbsp := dst.toBytesSlice()
-						for _, sb := range *sbsp {
-							if sb == nil {
-								*dbsp = append(*dbsp, nil)
-							} else {
-								*dbsp = append(*dbsp, append([]byte{}, sb...))
-							}
-						}
-						if *dbsp == nil {
-							*dbsp = [][]byte{}
-						}
-					}
-				}
-			default: // E.g., []byte
-				mfi.merge = func(dst, src pointer) {
-					sbp := src.toBytes()
-					if *sbp != nil {
-						dbp := dst.toBytes()
-						if !isProto3 || len(*sbp) > 0 {
-							*dbp = append([]byte{}, *sbp...)
-						}
-					}
-				}
-			}
-		case reflect.Struct:
-			switch {
-			case !isPointer:
-				panic(fmt.Sprintf("message field %s without pointer", tf))
-			case isSlice: // E.g., []*pb.T
-				mi := getMergeInfo(tf)
-				mfi.merge = func(dst, src pointer) {
-					sps := src.getPointerSlice()
-					if sps != nil {
-						dps := dst.getPointerSlice()
-						for _, sp := range sps {
-							var dp pointer
-							if !sp.isNil() {
-								dp = valToPointer(reflect.New(tf))
-								mi.merge(dp, sp)
-							}
-							dps = append(dps, dp)
-						}
-						if dps == nil {
-							dps = []pointer{}
-						}
-						dst.setPointerSlice(dps)
-					}
-				}
-			default: // E.g., *pb.T
-				mi := getMergeInfo(tf)
-				mfi.merge = func(dst, src pointer) {
-					sp := src.getPointer()
-					if !sp.isNil() {
-						dp := dst.getPointer()
-						if dp.isNil() {
-							dp = valToPointer(reflect.New(tf))
-							dst.setPointer(dp)
-						}
-						mi.merge(dp, sp)
-					}
-				}
-			}
-		case reflect.Map:
-			switch {
-			case isPointer || isSlice:
-				panic("bad pointer or slice in map case in " + tf.Name())
-			default: // E.g., map[K]V
-				mfi.merge = func(dst, src pointer) {
-					sm := src.asPointerTo(tf).Elem()
-					if sm.Len() == 0 {
-						return
-					}
-					dm := dst.asPointerTo(tf).Elem()
-					if dm.IsNil() {
-						dm.Set(reflect.MakeMap(tf))
-					}
-
-					switch tf.Elem().Kind() {
-					case reflect.Ptr: // Proto struct (e.g., *T)
-						for _, key := range sm.MapKeys() {
-							val := sm.MapIndex(key)
-							val = reflect.ValueOf(Clone(val.Interface().(Message)))
-							dm.SetMapIndex(key, val)
-						}
-					case reflect.Slice: // E.g. Bytes type (e.g., []byte)
-						for _, key := range sm.MapKeys() {
-							val := sm.MapIndex(key)
-							val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
-							dm.SetMapIndex(key, val)
-						}
-					default: // Basic type (e.g., string)
-						for _, key := range sm.MapKeys() {
-							val := sm.MapIndex(key)
-							dm.SetMapIndex(key, val)
-						}
-					}
-				}
-			}
-		case reflect.Interface:
-			// Must be oneof field.
-			switch {
-			case isPointer || isSlice:
-				panic("bad pointer or slice in interface case in " + tf.Name())
-			default: // E.g., interface{}
-				// TODO: Make this faster?
-				mfi.merge = func(dst, src pointer) {
-					su := src.asPointerTo(tf).Elem()
-					if !su.IsNil() {
-						du := dst.asPointerTo(tf).Elem()
-						typ := su.Elem().Type()
-						if du.IsNil() || du.Elem().Type() != typ {
-							du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
-						}
-						sv := su.Elem().Elem().Field(0)
-						if sv.Kind() == reflect.Ptr && sv.IsNil() {
-							return
-						}
-						dv := du.Elem().Elem().Field(0)
-						if dv.Kind() == reflect.Ptr && dv.IsNil() {
-							dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
-						}
-						switch sv.Type().Kind() {
-						case reflect.Ptr: // Proto struct (e.g., *T)
-							Merge(dv.Interface().(Message), sv.Interface().(Message))
-						case reflect.Slice: // E.g. Bytes type (e.g., []byte)
-							dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
-						default: // Basic type (e.g., string)
-							dv.Set(sv)
-						}
-					}
-				}
-			}
-		default:
-			panic(fmt.Sprintf("merger not found for type:%s", tf))
-		}
-		mi.fields = append(mi.fields, mfi)
-	}
-
-	mi.unrecognized = invalidField
-	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
-		if f.Type != reflect.TypeOf([]byte{}) {
-			panic("expected XXX_unrecognized to be of type []byte")
-		}
-		mi.unrecognized = toField(&f)
-	}
-
-	atomic.StoreInt32(&mi.initialized, 1)
-}
diff --git a/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go
deleted file mode 100644
index 55f0340a3fde2e05e02b68256668c70341ea55bb..0000000000000000000000000000000000000000
--- a/vendor/github.com/golang/protobuf/proto/table_unmarshal.go
+++ /dev/null
@@ -1,1967 +0,0 @@
-// Go support for Protocol Buffers - Google's data interchange format
-//
-// Copyright 2016 The Go Authors.  All rights reserved.
-// https://github.com/golang/protobuf
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package proto
-
-import (
-	"errors"
-	"fmt"
-	"io"
-	"math"
-	"reflect"
-	"strconv"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"unicode/utf8"
-)
-
-// Unmarshal is the entry point from the generated .pb.go files.
-// This function is not intended to be used by non-generated code.
-// This function is not subject to any compatibility guarantee.
-// msg contains a pointer to a protocol buffer struct.
-// b is the data to be unmarshaled into the protocol buffer.
-// a is a pointer to a place to store cached unmarshal information.
-func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error {
-	// Load the unmarshal information for this message type.
-	// The atomic load ensures memory consistency.
-	u := atomicLoadUnmarshalInfo(&a.unmarshal)
-	if u == nil {
-		// Slow path: find unmarshal info for msg, update a with it.
-		u = getUnmarshalInfo(reflect.TypeOf(msg).Elem())
-		atomicStoreUnmarshalInfo(&a.unmarshal, u)
-	}
-	// Then do the unmarshaling.
-	err := u.unmarshal(toPointer(&msg), b)
-	return err
-}
-
-type unmarshalInfo struct {
-	typ reflect.Type // type of the protobuf struct
-
-	// 0 = only typ field is initialized
-	// 1 = completely initialized
-	initialized     int32
-	lock            sync.Mutex                    // prevents double initialization
-	dense           []unmarshalFieldInfo          // fields indexed by tag #
-	sparse          map[uint64]unmarshalFieldInfo // fields indexed by tag #
-	reqFields       []string                      // names of required fields
-	reqMask         uint64                        // 1<<len(reqFields)-1
-	unrecognized    field                         // offset of []byte to put unrecognized data (or invalidField if we should throw it away)
-	extensions      field                         // offset of extensions field (of type proto.XXX_InternalExtensions), or invalidField if it does not exist
-	oldExtensions   field                         // offset of old-form extensions field (of type map[int]Extension)
-	extensionRanges []ExtensionRange              // if non-nil, implies extensions field is valid
-	isMessageSet    bool                          // if true, implies extensions field is valid
-}
-
-// An unmarshaler takes a stream of bytes and a pointer to a field of a message.
-// It decodes the field, stores it at f, and returns the unused bytes.
-// w is the wire encoding.
-// b is the data after the tag and wire encoding have been read.
-type unmarshaler func(b []byte, f pointer, w int) ([]byte, error)
-
-type unmarshalFieldInfo struct {
-	// location of the field in the proto message structure.
-	field field
-
-	// function to unmarshal the data for the field.
-	unmarshal unmarshaler
-
-	// if a required field, contains a single set bit at this field's index in the required field list.
-	reqMask uint64
-}
-
-var (
-	unmarshalInfoMap  = map[reflect.Type]*unmarshalInfo{}
-	unmarshalInfoLock sync.Mutex
-)
-
-// getUnmarshalInfo returns the data structure which can be
-// subsequently used to unmarshal a message of the given type.
-// t is the type of the message (note: not pointer to message).
-func getUnmarshalInfo(t reflect.Type) *unmarshalInfo {
-	// It would be correct to return a new unmarshalInfo
-	// unconditionally. We would end up allocating one
-	// per occurrence of that type as a message or submessage.
-	// We use a cache here just to reduce memory usage.
-	unmarshalInfoLock.Lock()
-	defer unmarshalInfoLock.Unlock()
-	u := unmarshalInfoMap[t]
-	if u == nil {
-		u = &unmarshalInfo{typ: t}
-		// Note: we just set the type here. The rest of the fields
-		// will be initialized on first use.
-		unmarshalInfoMap[t] = u
-	}
-	return u
-}
-
-// unmarshal does the main work of unmarshaling a message.
-// u provides type information used to unmarshal the message.
-// m is a pointer to a protocol buffer message.
-// b is a byte stream to unmarshal into m.
-// This is top routine used when recursively unmarshaling submessages.
-func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
-	if atomic.LoadInt32(&u.initialized) == 0 {
-		u.computeUnmarshalInfo()
-	}
-	if u.isMessageSet {
-		return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
-	}
-	var reqMask uint64            // bitmask of required fields we've seen.
-	var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage.
-	for len(b) > 0 {
-		// Read tag and wire type.
-		// Special case 1 and 2 byte varints.
-		var x uint64
-		if b[0] < 128 {
-			x = uint64(b[0])
-			b = b[1:]
-		} else if len(b) >= 2 && b[1] < 128 {
-			x = uint64(b[0]&0x7f) + uint64(b[1])<<7
-			b = b[2:]
-		} else {
-			var n int
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-		}
-		tag := x >> 3
-		wire := int(x) & 7
-
-		// Dispatch on the tag to one of the unmarshal* functions below.
-		var f unmarshalFieldInfo
-		if tag < uint64(len(u.dense)) {
-			f = u.dense[tag]
-		} else {
-			f = u.sparse[tag]
-		}
-		if fn := f.unmarshal; fn != nil {
-			var err error
-			b, err = fn(b, m.offset(f.field), wire)
-			if err == nil {
-				reqMask |= f.reqMask
-				continue
-			}
-			if r, ok := err.(*RequiredNotSetError); ok {
-				// Remember this error, but keep parsing. We need to produce
-				// a full parse even if a required field is missing.
-				rnse = r
-				reqMask |= f.reqMask
-				continue
-			}
-			if err != errInternalBadWireType {
-				return err
-			}
-			// Fragments with bad wire type are treated as unknown fields.
-		}
-
-		// Unknown tag.
-		if !u.unrecognized.IsValid() {
-			// Don't keep unrecognized data; just skip it.
-			var err error
-			b, err = skipField(b, wire)
-			if err != nil {
-				return err
-			}
-			continue
-		}
-		// Keep unrecognized data around.
-		// maybe in extensions, maybe in the unrecognized field.
-		z := m.offset(u.unrecognized).toBytes()
-		var emap map[int32]Extension
-		var e Extension
-		for _, r := range u.extensionRanges {
-			if uint64(r.Start) <= tag && tag <= uint64(r.End) {
-				if u.extensions.IsValid() {
-					mp := m.offset(u.extensions).toExtensions()
-					emap = mp.extensionsWrite()
-					e = emap[int32(tag)]
-					z = &e.enc
-					break
-				}
-				if u.oldExtensions.IsValid() {
-					p := m.offset(u.oldExtensions).toOldExtensions()
-					emap = *p
-					if emap == nil {
-						emap = map[int32]Extension{}
-						*p = emap
-					}
-					e = emap[int32(tag)]
-					z = &e.enc
-					break
-				}
-				panic("no extensions field available")
-			}
-		}
-
-		// Use wire type to skip data.
-		var err error
-		b0 := b
-		b, err = skipField(b, wire)
-		if err != nil {
-			return err
-		}
-		*z = encodeVarint(*z, tag<<3|uint64(wire))
-		*z = append(*z, b0[:len(b0)-len(b)]...)
-
-		if emap != nil {
-			emap[int32(tag)] = e
-		}
-	}
-	if rnse != nil {
-		// A required field of a submessage/group is missing. Return that error.
-		return rnse
-	}
-	if reqMask != u.reqMask {
-		// A required field of this message is missing.
-		for _, n := range u.reqFields {
-			if reqMask&1 == 0 {
-				return &RequiredNotSetError{n}
-			}
-			reqMask >>= 1
-		}
-	}
-	return nil
-}
-
-// computeUnmarshalInfo fills in u with information for use
-// in unmarshaling protocol buffers of type u.typ.
-func (u *unmarshalInfo) computeUnmarshalInfo() {
-	u.lock.Lock()
-	defer u.lock.Unlock()
-	if u.initialized != 0 {
-		return
-	}
-	t := u.typ
-	n := t.NumField()
-
-	// Set up the "not found" value for the unrecognized byte buffer.
-	// This is the default for proto3.
-	u.unrecognized = invalidField
-	u.extensions = invalidField
-	u.oldExtensions = invalidField
-
-	// List of the generated type and offset for each oneof field.
-	type oneofField struct {
-		ityp  reflect.Type // interface type of oneof field
-		field field        // offset in containing message
-	}
-	var oneofFields []oneofField
-
-	for i := 0; i < n; i++ {
-		f := t.Field(i)
-		if f.Name == "XXX_unrecognized" {
-			// The byte slice used to hold unrecognized input is special.
-			if f.Type != reflect.TypeOf(([]byte)(nil)) {
-				panic("bad type for XXX_unrecognized field: " + f.Type.Name())
-			}
-			u.unrecognized = toField(&f)
-			continue
-		}
-		if f.Name == "XXX_InternalExtensions" {
-			// Ditto here.
-			if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) {
-				panic("bad type for XXX_InternalExtensions field: " + f.Type.Name())
-			}
-			u.extensions = toField(&f)
-			if f.Tag.Get("protobuf_messageset") == "1" {
-				u.isMessageSet = true
-			}
-			continue
-		}
-		if f.Name == "XXX_extensions" {
-			// An older form of the extensions field.
-			if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) {
-				panic("bad type for XXX_extensions field: " + f.Type.Name())
-			}
-			u.oldExtensions = toField(&f)
-			continue
-		}
-		if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" {
-			continue
-		}
-
-		oneof := f.Tag.Get("protobuf_oneof")
-		if oneof != "" {
-			oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)})
-			// The rest of oneof processing happens below.
-			continue
-		}
-
-		tags := f.Tag.Get("protobuf")
-		tagArray := strings.Split(tags, ",")
-		if len(tagArray) < 2 {
-			panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags)
-		}
-		tag, err := strconv.Atoi(tagArray[1])
-		if err != nil {
-			panic("protobuf tag field not an integer: " + tagArray[1])
-		}
-
-		name := ""
-		for _, tag := range tagArray[3:] {
-			if strings.HasPrefix(tag, "name=") {
-				name = tag[5:]
-			}
-		}
-
-		// Extract unmarshaling function from the field (its type and tags).
-		unmarshal := fieldUnmarshaler(&f)
-
-		// Required field?
-		var reqMask uint64
-		if tagArray[2] == "req" {
-			bit := len(u.reqFields)
-			u.reqFields = append(u.reqFields, name)
-			reqMask = uint64(1) << uint(bit)
-			// TODO: if we have more than 64 required fields, we end up
-			// not verifying that all required fields are present.
-			// Fix this, perhaps using a count of required fields?
-		}
-
-		// Store the info in the correct slot in the message.
-		u.setTag(tag, toField(&f), unmarshal, reqMask)
-	}
-
-	// Find any types associated with oneof fields.
-	// TODO: XXX_OneofFuncs returns more info than we need.  Get rid of some of it?
-	fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
-	if fn.IsValid() {
-		res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
-		for i := res.Len() - 1; i >= 0; i-- {
-			v := res.Index(i)                             // interface{}
-			tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
-			typ := tptr.Elem()                            // Msg_X
-
-			f := typ.Field(0) // oneof implementers have one field
-			baseUnmarshal := fieldUnmarshaler(&f)
-			tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1]
-			tag, err := strconv.Atoi(tagstr)
-			if err != nil {
-				panic("protobuf tag field not an integer: " + tagstr)
-			}
-
-			// Find the oneof field that this struct implements.
-			// Might take O(n^2) to process all of the oneofs, but who cares.
-			for _, of := range oneofFields {
-				if tptr.Implements(of.ityp) {
-					// We have found the corresponding interface for this struct.
-					// That lets us know where this struct should be stored
-					// when we encounter it during unmarshaling.
-					unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
-					u.setTag(tag, of.field, unmarshal, 0)
-				}
-			}
-		}
-	}
-
-	// Get extension ranges, if any.
-	fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
-	if fn.IsValid() {
-		if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
-			panic("a message with extensions, but no extensions field in " + t.Name())
-		}
-		u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange)
-	}
-
-	// Explicitly disallow tag 0. This will ensure we flag an error
-	// when decoding a buffer of all zeros. Without this code, we
-	// would decode and skip an all-zero buffer of even length.
-	// [0 0] is [tag=0/wiretype=varint varint-encoded-0].
-	u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
-		return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
-	}, 0)
-
-	// Set mask for required field check.
-	u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
-
-	atomic.StoreInt32(&u.initialized, 1)
-}
-
-// setTag stores the unmarshal information for the given tag.
-// tag = tag # for field
-// field/unmarshal = unmarshal info for that field.
-// reqMask = if required, bitmask for field position in required field list. 0 otherwise.
-func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64) {
-	i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask}
-	n := u.typ.NumField()
-	if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
-		for len(u.dense) <= tag {
-			u.dense = append(u.dense, unmarshalFieldInfo{})
-		}
-		u.dense[tag] = i
-		return
-	}
-	if u.sparse == nil {
-		u.sparse = map[uint64]unmarshalFieldInfo{}
-	}
-	u.sparse[uint64(tag)] = i
-}
-
-// fieldUnmarshaler returns an unmarshaler for the given field.
-func fieldUnmarshaler(f *reflect.StructField) unmarshaler {
-	if f.Type.Kind() == reflect.Map {
-		return makeUnmarshalMap(f)
-	}
-	return typeUnmarshaler(f.Type, f.Tag.Get("protobuf"))
-}
-
-// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair.
-func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
-	tagArray := strings.Split(tags, ",")
-	encoding := tagArray[0]
-	name := "unknown"
-	for _, tag := range tagArray[3:] {
-		if strings.HasPrefix(tag, "name=") {
-			name = tag[5:]
-		}
-	}
-
-	// Figure out packaging (pointer, slice, or both)
-	slice := false
-	pointer := false
-	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
-		slice = true
-		t = t.Elem()
-	}
-	if t.Kind() == reflect.Ptr {
-		pointer = true
-		t = t.Elem()
-	}
-
-	// We'll never have both pointer and slice for basic types.
-	if pointer && slice && t.Kind() != reflect.Struct {
-		panic("both pointer and slice for basic type in " + t.Name())
-	}
-
-	switch t.Kind() {
-	case reflect.Bool:
-		if pointer {
-			return unmarshalBoolPtr
-		}
-		if slice {
-			return unmarshalBoolSlice
-		}
-		return unmarshalBoolValue
-	case reflect.Int32:
-		switch encoding {
-		case "fixed32":
-			if pointer {
-				return unmarshalFixedS32Ptr
-			}
-			if slice {
-				return unmarshalFixedS32Slice
-			}
-			return unmarshalFixedS32Value
-		case "varint":
-			// this could be int32 or enum
-			if pointer {
-				return unmarshalInt32Ptr
-			}
-			if slice {
-				return unmarshalInt32Slice
-			}
-			return unmarshalInt32Value
-		case "zigzag32":
-			if pointer {
-				return unmarshalSint32Ptr
-			}
-			if slice {
-				return unmarshalSint32Slice
-			}
-			return unmarshalSint32Value
-		}
-	case reflect.Int64:
-		switch encoding {
-		case "fixed64":
-			if pointer {
-				return unmarshalFixedS64Ptr
-			}
-			if slice {
-				return unmarshalFixedS64Slice
-			}
-			return unmarshalFixedS64Value
-		case "varint":
-			if pointer {
-				return unmarshalInt64Ptr
-			}
-			if slice {
-				return unmarshalInt64Slice
-			}
-			return unmarshalInt64Value
-		case "zigzag64":
-			if pointer {
-				return unmarshalSint64Ptr
-			}
-			if slice {
-				return unmarshalSint64Slice
-			}
-			return unmarshalSint64Value
-		}
-	case reflect.Uint32:
-		switch encoding {
-		case "fixed32":
-			if pointer {
-				return unmarshalFixed32Ptr
-			}
-			if slice {
-				return unmarshalFixed32Slice
-			}
-			return unmarshalFixed32Value
-		case "varint":
-			if pointer {
-				return unmarshalUint32Ptr
-			}
-			if slice {
-				return unmarshalUint32Slice
-			}
-			return unmarshalUint32Value
-		}
-	case reflect.Uint64:
-		switch encoding {
-		case "fixed64":
-			if pointer {
-				return unmarshalFixed64Ptr
-			}
-			if slice {
-				return unmarshalFixed64Slice
-			}
-			return unmarshalFixed64Value
-		case "varint":
-			if pointer {
-				return unmarshalUint64Ptr
-			}
-			if slice {
-				return unmarshalUint64Slice
-			}
-			return unmarshalUint64Value
-		}
-	case reflect.Float32:
-		if pointer {
-			return unmarshalFloat32Ptr
-		}
-		if slice {
-			return unmarshalFloat32Slice
-		}
-		return unmarshalFloat32Value
-	case reflect.Float64:
-		if pointer {
-			return unmarshalFloat64Ptr
-		}
-		if slice {
-			return unmarshalFloat64Slice
-		}
-		return unmarshalFloat64Value
-	case reflect.Map:
-		panic("map type in typeUnmarshaler in " + t.Name())
-	case reflect.Slice:
-		if pointer {
-			panic("bad pointer in slice case in " + t.Name())
-		}
-		if slice {
-			return unmarshalBytesSlice
-		}
-		return unmarshalBytesValue
-	case reflect.String:
-		if pointer {
-			return unmarshalStringPtr
-		}
-		if slice {
-			return unmarshalStringSlice
-		}
-		return unmarshalStringValue
-	case reflect.Struct:
-		// message or group field
-		if !pointer {
-			panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding))
-		}
-		switch encoding {
-		case "bytes":
-			if slice {
-				return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name)
-			}
-			return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name)
-		case "group":
-			if slice {
-				return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name)
-			}
-			return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name)
-		}
-	}
-	panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding))
-}
-
-// Below are all the unmarshalers for individual fields of various types.
-
-func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x)
-	*f.toInt64() = v
-	return b, nil
-}
-
-func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x)
-	*f.toInt64Ptr() = &v
-	return b, nil
-}
-
-func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := int64(x)
-			s := f.toInt64Slice()
-			*s = append(*s, v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x)
-	s := f.toInt64Slice()
-	*s = append(*s, v)
-	return b, nil
-}
-
-func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x>>1) ^ int64(x)<<63>>63
-	*f.toInt64() = v
-	return b, nil
-}
-
-func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x>>1) ^ int64(x)<<63>>63
-	*f.toInt64Ptr() = &v
-	return b, nil
-}
-
-func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := int64(x>>1) ^ int64(x)<<63>>63
-			s := f.toInt64Slice()
-			*s = append(*s, v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int64(x>>1) ^ int64(x)<<63>>63
-	s := f.toInt64Slice()
-	*s = append(*s, v)
-	return b, nil
-}
-
-func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint64(x)
-	*f.toUint64() = v
-	return b, nil
-}
-
-func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint64(x)
-	*f.toUint64Ptr() = &v
-	return b, nil
-}
-
-func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := uint64(x)
-			s := f.toUint64Slice()
-			*s = append(*s, v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint64(x)
-	s := f.toUint64Slice()
-	*s = append(*s, v)
-	return b, nil
-}
-
-func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x)
-	*f.toInt32() = v
-	return b, nil
-}
-
-func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x)
-	f.setInt32Ptr(v)
-	return b, nil
-}
-
-func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := int32(x)
-			f.appendInt32Slice(v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x)
-	f.appendInt32Slice(v)
-	return b, nil
-}
-
-func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x>>1) ^ int32(x)<<31>>31
-	*f.toInt32() = v
-	return b, nil
-}
-
-func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x>>1) ^ int32(x)<<31>>31
-	f.setInt32Ptr(v)
-	return b, nil
-}
-
-func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := int32(x>>1) ^ int32(x)<<31>>31
-			f.appendInt32Slice(v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := int32(x>>1) ^ int32(x)<<31>>31
-	f.appendInt32Slice(v)
-	return b, nil
-}
-
-func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint32(x)
-	*f.toUint32() = v
-	return b, nil
-}
-
-func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint32(x)
-	*f.toUint32Ptr() = &v
-	return b, nil
-}
-
-func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			b = b[n:]
-			v := uint32(x)
-			s := f.toUint32Slice()
-			*s = append(*s, v)
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	v := uint32(x)
-	s := f.toUint32Slice()
-	*s = append(*s, v)
-	return b, nil
-}
-
-func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
-	*f.toUint64() = v
-	return b[8:], nil
-}
-
-func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
-	*f.toUint64Ptr() = &v
-	return b[8:], nil
-}
-
-func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 8 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
-			s := f.toUint64Slice()
-			*s = append(*s, v)
-			b = b[8:]
-		}
-		return res, nil
-	}
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
-	s := f.toUint64Slice()
-	*s = append(*s, v)
-	return b[8:], nil
-}
-
-func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
-	*f.toInt64() = v
-	return b[8:], nil
-}
-
-func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
-	*f.toInt64Ptr() = &v
-	return b[8:], nil
-}
-
-func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 8 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
-			s := f.toInt64Slice()
-			*s = append(*s, v)
-			b = b[8:]
-		}
-		return res, nil
-	}
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
-	s := f.toInt64Slice()
-	*s = append(*s, v)
-	return b[8:], nil
-}
-
-func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-	*f.toUint32() = v
-	return b[4:], nil
-}
-
-func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-	*f.toUint32Ptr() = &v
-	return b[4:], nil
-}
-
-func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 4 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-			s := f.toUint32Slice()
-			*s = append(*s, v)
-			b = b[4:]
-		}
-		return res, nil
-	}
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-	s := f.toUint32Slice()
-	*s = append(*s, v)
-	return b[4:], nil
-}
-
-func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
-	*f.toInt32() = v
-	return b[4:], nil
-}
-
-func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
-	f.setInt32Ptr(v)
-	return b[4:], nil
-}
-
-func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 4 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
-			f.appendInt32Slice(v)
-			b = b[4:]
-		}
-		return res, nil
-	}
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
-	f.appendInt32Slice(v)
-	return b[4:], nil
-}
-
-func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	// Note: any length varint is allowed, even though any sane
-	// encoder will use one byte.
-	// See https://github.com/golang/protobuf/issues/76
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	// TODO: check if x>1? Tests seem to indicate no.
-	v := x != 0
-	*f.toBool() = v
-	return b[n:], nil
-}
-
-func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := x != 0
-	*f.toBoolPtr() = &v
-	return b[n:], nil
-}
-
-func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			x, n = decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := x != 0
-			s := f.toBoolSlice()
-			*s = append(*s, v)
-			b = b[n:]
-		}
-		return res, nil
-	}
-	if w != WireVarint {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := x != 0
-	s := f.toBoolSlice()
-	*s = append(*s, v)
-	return b[n:], nil
-}
-
-func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
-	*f.toFloat64() = v
-	return b[8:], nil
-}
-
-func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
-	*f.toFloat64Ptr() = &v
-	return b[8:], nil
-}
-
-func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 8 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
-			s := f.toFloat64Slice()
-			*s = append(*s, v)
-			b = b[8:]
-		}
-		return res, nil
-	}
-	if w != WireFixed64 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 8 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
-	s := f.toFloat64Slice()
-	*s = append(*s, v)
-	return b[8:], nil
-}
-
-func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
-	*f.toFloat32() = v
-	return b[4:], nil
-}
-
-func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
-	*f.toFloat32Ptr() = &v
-	return b[4:], nil
-}
-
-func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) {
-	if w == WireBytes { // packed
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		res := b[x:]
-		b = b[:x]
-		for len(b) > 0 {
-			if len(b) < 4 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
-			s := f.toFloat32Slice()
-			*s = append(*s, v)
-			b = b[4:]
-		}
-		return res, nil
-	}
-	if w != WireFixed32 {
-		return b, errInternalBadWireType
-	}
-	if len(b) < 4 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
-	s := f.toFloat32Slice()
-	*s = append(*s, v)
-	return b[4:], nil
-}
-
-func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireBytes {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	if x > uint64(len(b)) {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := string(b[:x])
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	*f.toString() = v
-	return b[x:], nil
-}
-
-func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireBytes {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	if x > uint64(len(b)) {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := string(b[:x])
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	*f.toStringPtr() = &v
-	return b[x:], nil
-}
-
-func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireBytes {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	if x > uint64(len(b)) {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := string(b[:x])
-	if !utf8.ValidString(v) {
-		return nil, errInvalidUTF8
-	}
-	s := f.toStringSlice()
-	*s = append(*s, v)
-	return b[x:], nil
-}
-
-var emptyBuf [0]byte
-
-func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireBytes {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	if x > uint64(len(b)) {
-		return nil, io.ErrUnexpectedEOF
-	}
-	// The use of append here is a trick which avoids the zeroing
-	// that would be required if we used a make/copy pair.
-	// We append to emptyBuf instead of nil because we want
-	// a non-nil result even when the length is 0.
-	v := append(emptyBuf[:], b[:x]...)
-	*f.toBytes() = v
-	return b[x:], nil
-}
-
-func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) {
-	if w != WireBytes {
-		return b, errInternalBadWireType
-	}
-	x, n := decodeVarint(b)
-	if n == 0 {
-		return nil, io.ErrUnexpectedEOF
-	}
-	b = b[n:]
-	if x > uint64(len(b)) {
-		return nil, io.ErrUnexpectedEOF
-	}
-	v := append(emptyBuf[:], b[:x]...)
-	s := f.toBytesSlice()
-	*s = append(*s, v)
-	return b[x:], nil
-}
-
-func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler {
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		if w != WireBytes {
-			return b, errInternalBadWireType
-		}
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		// First read the message field to see if something is there.
-		// The semantics of multiple submessages are weird.  Instead of
-		// the last one winning (as it is for all other fields), multiple
-		// submessages are merged.
-		v := f.getPointer()
-		if v.isNil() {
-			v = valToPointer(reflect.New(sub.typ))
-			f.setPointer(v)
-		}
-		err := sub.unmarshal(v, b[:x])
-		if err != nil {
-			if r, ok := err.(*RequiredNotSetError); ok {
-				r.field = name + "." + r.field
-			} else {
-				return nil, err
-			}
-		}
-		return b[x:], err
-	}
-}
-
-func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		if w != WireBytes {
-			return b, errInternalBadWireType
-		}
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		v := valToPointer(reflect.New(sub.typ))
-		err := sub.unmarshal(v, b[:x])
-		if err != nil {
-			if r, ok := err.(*RequiredNotSetError); ok {
-				r.field = name + "." + r.field
-			} else {
-				return nil, err
-			}
-		}
-		f.appendPointer(v)
-		return b[x:], err
-	}
-}
-
-func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler {
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		if w != WireStartGroup {
-			return b, errInternalBadWireType
-		}
-		x, y := findEndGroup(b)
-		if x < 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		v := f.getPointer()
-		if v.isNil() {
-			v = valToPointer(reflect.New(sub.typ))
-			f.setPointer(v)
-		}
-		err := sub.unmarshal(v, b[:x])
-		if err != nil {
-			if r, ok := err.(*RequiredNotSetError); ok {
-				r.field = name + "." + r.field
-			} else {
-				return nil, err
-			}
-		}
-		return b[y:], err
-	}
-}
-
-func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		if w != WireStartGroup {
-			return b, errInternalBadWireType
-		}
-		x, y := findEndGroup(b)
-		if x < 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		v := valToPointer(reflect.New(sub.typ))
-		err := sub.unmarshal(v, b[:x])
-		if err != nil {
-			if r, ok := err.(*RequiredNotSetError); ok {
-				r.field = name + "." + r.field
-			} else {
-				return nil, err
-			}
-		}
-		f.appendPointer(v)
-		return b[y:], err
-	}
-}
-
-func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
-	t := f.Type
-	kt := t.Key()
-	vt := t.Elem()
-	unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
-	unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val"))
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		// The map entry is a submessage. Figure out how big it is.
-		if w != WireBytes {
-			return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes)
-		}
-		x, n := decodeVarint(b)
-		if n == 0 {
-			return nil, io.ErrUnexpectedEOF
-		}
-		b = b[n:]
-		if x > uint64(len(b)) {
-			return nil, io.ErrUnexpectedEOF
-		}
-		r := b[x:] // unused data to return
-		b = b[:x]  // data for map entry
-
-		// Note: we could use #keys * #values ~= 200 functions
-		// to do map decoding without reflection. Probably not worth it.
-		// Maps will be somewhat slow. Oh well.
-
-		// Read key and value from data.
-		k := reflect.New(kt)
-		v := reflect.New(vt)
-		for len(b) > 0 {
-			x, n := decodeVarint(b)
-			if n == 0 {
-				return nil, io.ErrUnexpectedEOF
-			}
-			wire := int(x) & 7
-			b = b[n:]
-
-			var err error
-			switch x >> 3 {
-			case 1:
-				b, err = unmarshalKey(b, valToPointer(k), wire)
-			case 2:
-				b, err = unmarshalVal(b, valToPointer(v), wire)
-			default:
-				err = errInternalBadWireType // skip unknown tag
-			}
-
-			if err == nil {
-				continue
-			}
-			if err != errInternalBadWireType {
-				return nil, err
-			}
-
-			// Skip past unknown fields.
-			b, err = skipField(b, wire)
-			if err != nil {
-				return nil, err
-			}
-		}
-
-		// Get map, allocate if needed.
-		m := f.asPointerTo(t).Elem() // an addressable map[K]T
-		if m.IsNil() {
-			m.Set(reflect.MakeMap(t))
-		}
-
-		// Insert into map.
-		m.SetMapIndex(k.Elem(), v.Elem())
-
-		return r, nil
-	}
-}
-
-// makeUnmarshalOneof makes an unmarshaler for oneof fields.
-// for:
-// message Msg {
-//   oneof F {
-//     int64 X = 1;
-//     float64 Y = 2;
-//   }
-// }
-// typ is the type of the concrete entry for a oneof case (e.g. Msg_X).
-// ityp is the interface type of the oneof field (e.g. isMsg_F).
-// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64).
-// Note that this function will be called once for each case in the oneof.
-func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler {
-	sf := typ.Field(0)
-	field0 := toField(&sf)
-	return func(b []byte, f pointer, w int) ([]byte, error) {
-		// Allocate holder for value.
-		v := reflect.New(typ)
-
-		// Unmarshal data into holder.
-		// We unmarshal into the first field of the holder object.
-		var err error
-		b, err = unmarshal(b, valToPointer(v).offset(field0), w)
-		if err != nil {
-			return nil, err
-		}
-
-		// Write pointer to holder into target field.
-		f.asPointerTo(ityp).Elem().Set(v)
-
-		return b, nil
-	}
-}
-
-// Error used by decode internally.
-var errInternalBadWireType = errors.New("proto: internal error: bad wiretype")
-
-// skipField skips past a field of type wire and returns the remaining bytes.
-func skipField(b []byte, wire int) ([]byte, error) {
-	switch wire {
-	case WireVarint:
-		_, k := decodeVarint(b)
-		if k == 0 {
-			return b, io.ErrUnexpectedEOF
-		}
-		b = b[k:]
-	case WireFixed32:
-		if len(b) < 4 {
-			return b, io.ErrUnexpectedEOF
-		}
-		b = b[4:]
-	case WireFixed64:
-		if len(b) < 8 {
-			return b, io.ErrUnexpectedEOF
-		}
-		b = b[8:]
-	case WireBytes:
-		m, k := decodeVarint(b)
-		if k == 0 || uint64(len(b)-k) < m {
-			return b, io.ErrUnexpectedEOF
-		}
-		b = b[uint64(k)+m:]
-	case WireStartGroup:
-		_, i := findEndGroup(b)
-		if i == -1 {
-			return b, io.ErrUnexpectedEOF
-		}
-		b = b[i:]
-	default:
-		return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire)
-	}
-	return b, nil
-}
-
-// findEndGroup finds the index of the next EndGroup tag.
-// Groups may be nested, so the "next" EndGroup tag is the first
-// unpaired EndGroup.
-// findEndGroup returns the indexes of the start and end of the EndGroup tag.
-// Returns (-1,-1) if it can't find one.
-func findEndGroup(b []byte) (int, int) {
-	depth := 1
-	i := 0
-	for {
-		x, n := decodeVarint(b[i:])
-		if n == 0 {
-			return -1, -1
-		}
-		j := i
-		i += n
-		switch x & 7 {
-		case WireVarint:
-			_, k := decodeVarint(b[i:])
-			if k == 0 {
-				return -1, -1
-			}
-			i += k
-		case WireFixed32:
-			if len(b)-4 < i {
-				return -1, -1
-			}
-			i += 4
-		case WireFixed64:
-			if len(b)-8 < i {
-				return -1, -1
-			}
-			i += 8
-		case WireBytes:
-			m, k := decodeVarint(b[i:])
-			if k == 0 {
-				return -1, -1
-			}
-			i += k
-			if uint64(len(b)-i) < m {
-				return -1, -1
-			}
-			i += int(m)
-		case WireStartGroup:
-			depth++
-		case WireEndGroup:
-			depth--
-			if depth == 0 {
-				return j, i
-			}
-		default:
-			return -1, -1
-		}
-	}
-}
-
-// encodeVarint appends a varint-encoded integer to b and returns the result.
-func encodeVarint(b []byte, x uint64) []byte {
-	for x >= 1<<7 {
-		b = append(b, byte(x&0x7f|0x80))
-		x >>= 7
-	}
-	return append(b, byte(x))
-}
-
-// decodeVarint reads a varint-encoded integer from b.
-// Returns the decoded integer and the number of bytes read.
-// If there is an error, it returns 0,0.
-func decodeVarint(b []byte) (uint64, int) {
-	var x, y uint64
-	if len(b) <= 0 {
-		goto bad
-	}
-	x = uint64(b[0])
-	if x < 0x80 {
-		return x, 1
-	}
-	x -= 0x80
-
-	if len(b) <= 1 {
-		goto bad
-	}
-	y = uint64(b[1])
-	x += y << 7
-	if y < 0x80 {
-		return x, 2
-	}
-	x -= 0x80 << 7
-
-	if len(b) <= 2 {
-		goto bad
-	}
-	y = uint64(b[2])
-	x += y << 14
-	if y < 0x80 {
-		return x, 3
-	}
-	x -= 0x80 << 14
-
-	if len(b) <= 3 {
-		goto bad
-	}
-	y = uint64(b[3])
-	x += y << 21
-	if y < 0x80 {
-		return x, 4
-	}
-	x -= 0x80 << 21
-
-	if len(b) <= 4 {
-		goto bad
-	}
-	y = uint64(b[4])
-	x += y << 28
-	if y < 0x80 {
-		return x, 5
-	}
-	x -= 0x80 << 28
-
-	if len(b) <= 5 {
-		goto bad
-	}
-	y = uint64(b[5])
-	x += y << 35
-	if y < 0x80 {
-		return x, 6
-	}
-	x -= 0x80 << 35
-
-	if len(b) <= 6 {
-		goto bad
-	}
-	y = uint64(b[6])
-	x += y << 42
-	if y < 0x80 {
-		return x, 7
-	}
-	x -= 0x80 << 42
-
-	if len(b) <= 7 {
-		goto bad
-	}
-	y = uint64(b[7])
-	x += y << 49
-	if y < 0x80 {
-		return x, 8
-	}
-	x -= 0x80 << 49
-
-	if len(b) <= 8 {
-		goto bad
-	}
-	y = uint64(b[8])
-	x += y << 56
-	if y < 0x80 {
-		return x, 9
-	}
-	x -= 0x80 << 56
-
-	if len(b) <= 9 {
-		goto bad
-	}
-	y = uint64(b[9])
-	x += y << 63
-	if y < 2 {
-		return x, 10
-	}
-
-bad:
-	return 0, 0
-}
diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go
index 2205fdaadf84c0c467d0ea05d08d99426643b641..965876bf033b64fac26deb2730244625d033fa41 100644
--- a/vendor/github.com/golang/protobuf/proto/text.go
+++ b/vendor/github.com/golang/protobuf/proto/text.go
@@ -50,6 +50,7 @@ import (
 var (
 	newline         = []byte("\n")
 	spaces          = []byte("                                        ")
+	gtNewline       = []byte(">\n")
 	endBraceNewline = []byte("}\n")
 	backslashN      = []byte{'\\', 'n'}
 	backslashR      = []byte{'\\', 'r'}
@@ -169,6 +170,11 @@ func writeName(w *textWriter, props *Properties) error {
 	return nil
 }
 
+// raw is the interface satisfied by RawMessage.
+type raw interface {
+	Bytes() []byte
+}
+
 func requiresQuotes(u string) bool {
 	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
 	for _, ch := range u {
@@ -263,10 +269,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 		props := sprops.Prop[i]
 		name := st.Field(i).Name
 
-		if name == "XXX_NoUnkeyedLiteral" {
-			continue
-		}
-
 		if strings.HasPrefix(name, "XXX_") {
 			// There are two XXX_ fields:
 			//   XXX_unrecognized []byte
@@ -434,6 +436,12 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 				return err
 			}
 		}
+		if b, ok := fv.Interface().(raw); ok {
+			if err := writeRaw(w, b.Bytes()); err != nil {
+				return err
+			}
+			continue
+		}
 
 		// Enums have a String method, so writeAny will work fine.
 		if err := tm.writeAny(w, fv, props); err != nil {
@@ -447,7 +455,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 
 	// Extensions (the XXX_extensions field).
 	pv := sv.Addr()
-	if _, err := extendable(pv.Interface()); err == nil {
+	if _, ok := extendable(pv.Interface()); ok {
 		if err := tm.writeExtensions(w, pv); err != nil {
 			return err
 		}
@@ -456,6 +464,27 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 	return nil
 }
 
+// writeRaw writes an uninterpreted raw message.
+func writeRaw(w *textWriter, b []byte) error {
+	if err := w.WriteByte('<'); err != nil {
+		return err
+	}
+	if !w.compact {
+		if err := w.WriteByte('\n'); err != nil {
+			return err
+		}
+	}
+	w.indent()
+	if err := writeUnknownStruct(w, b); err != nil {
+		return err
+	}
+	w.unindent()
+	if err := w.WriteByte('>'); err != nil {
+		return err
+	}
+	return nil
+}
+
 // writeAny writes an arbitrary field.
 func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
 	v = reflect.Indirect(v)
@@ -506,19 +535,6 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 			}
 		}
 		w.indent()
-		if v.CanAddr() {
-			// Calling v.Interface on a struct causes the reflect package to
-			// copy the entire struct. This is racy with the new Marshaler
-			// since we atomically update the XXX_sizecache.
-			//
-			// Thus, we retrieve a pointer to the struct if possible to avoid
-			// a race since v.Interface on the pointer doesn't copy the struct.
-			//
-			// If v is not addressable, then we are not worried about a race
-			// since it implies that the binary Marshaler cannot possibly be
-			// mutating this value.
-			v = v.Addr()
-		}
 		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
 			text, err := etm.MarshalText()
 			if err != nil {
@@ -527,13 +543,8 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 			if _, err = w.Write(text); err != nil {
 				return err
 			}
-		} else {
-			if v.Kind() == reflect.Ptr {
-				v = v.Elem()
-			}
-			if err := tm.writeStruct(w, v); err != nil {
-				return err
-			}
+		} else if err := tm.writeStruct(w, v); err != nil {
+			return err
 		}
 		w.unindent()
 		if err := w.WriteByte(ket); err != nil {
diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go
index 0685bae36d507a2b47c423379ccd3c08df36cf9d..5e14513f28c9041020ee559c9ec437361720024f 100644
--- a/vendor/github.com/golang/protobuf/proto/text_parser.go
+++ b/vendor/github.com/golang/protobuf/proto/text_parser.go
@@ -206,6 +206,7 @@ func (p *textParser) advance() {
 
 var (
 	errBadUTF8 = errors.New("proto: bad UTF-8")
+	errBadHex  = errors.New("proto: bad hexadecimal")
 )
 
 func unquoteC(s string, quote rune) (string, error) {
@@ -276,47 +277,60 @@ func unescape(s string) (ch string, tail string, err error) {
 		return "?", s, nil // trigraph workaround
 	case '\'', '"', '\\':
 		return string(r), s, nil
-	case '0', '1', '2', '3', '4', '5', '6', '7':
+	case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
 		if len(s) < 2 {
 			return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
 		}
-		ss := string(r) + s[:2]
+		base := 8
+		ss := s[:2]
 		s = s[2:]
-		i, err := strconv.ParseUint(ss, 8, 8)
+		if r == 'x' || r == 'X' {
+			base = 16
+		} else {
+			ss = string(r) + ss
+		}
+		i, err := strconv.ParseUint(ss, base, 8)
 		if err != nil {
-			return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
+			return "", "", err
 		}
 		return string([]byte{byte(i)}), s, nil
-	case 'x', 'X', 'u', 'U':
-		var n int
-		switch r {
-		case 'x', 'X':
-			n = 2
-		case 'u':
-			n = 4
-		case 'U':
+	case 'u', 'U':
+		n := 4
+		if r == 'U' {
 			n = 8
 		}
 		if len(s) < n {
-			return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
-		}
-		ss := s[:n]
-		s = s[n:]
-		i, err := strconv.ParseUint(ss, 16, 64)
-		if err != nil {
-			return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
+			return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
 		}
-		if r == 'x' || r == 'X' {
-			return string([]byte{byte(i)}), s, nil
-		}
-		if i > utf8.MaxRune {
-			return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
+
+		bs := make([]byte, n/2)
+		for i := 0; i < n; i += 2 {
+			a, ok1 := unhex(s[i])
+			b, ok2 := unhex(s[i+1])
+			if !ok1 || !ok2 {
+				return "", "", errBadHex
+			}
+			bs[i/2] = a<<4 | b
 		}
-		return string(i), s, nil
+		s = s[n:]
+		return string(bs), s, nil
 	}
 	return "", "", fmt.Errorf(`unknown escape \%c`, r)
 }
 
+// Adapted from src/pkg/strconv/quote.go.
+func unhex(b byte) (v byte, ok bool) {
+	switch {
+	case '0' <= b && b <= '9':
+		return b - '0', true
+	case 'a' <= b && b <= 'f':
+		return b - 'a' + 10, true
+	case 'A' <= b && b <= 'F':
+		return b - 'A' + 10, true
+	}
+	return 0, false
+}
+
 // Back off the parser by one token. Can only be done between calls to next().
 // It makes the next advance() a no-op.
 func (p *textParser) back() { p.backed = true }
@@ -714,9 +728,6 @@ func (p *textParser) consumeExtName() (string, error) {
 		if tok.err != nil {
 			return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
 		}
-		if p.done && tok.value != "]" {
-			return "", p.errorf("unclosed type_url or extension name")
-		}
 	}
 	return strings.Join(parts, ""), nil
 }
@@ -854,7 +865,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 		return p.readStruct(fv, terminator)
 	case reflect.Uint32:
 		if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
-			fv.SetUint(uint64(x))
+			fv.SetUint(x)
 			return nil
 		}
 	case reflect.Uint64:
@@ -872,9 +883,13 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 // UnmarshalText returns *RequiredNotSetError.
 func UnmarshalText(s string, pb Message) error {
 	if um, ok := pb.(encoding.TextUnmarshaler); ok {
-		return um.UnmarshalText([]byte(s))
+		err := um.UnmarshalText([]byte(s))
+		return err
 	}
 	pb.Reset()
 	v := reflect.ValueOf(pb)
-	return newTextParser(s).readStruct(v.Elem(), "")
+	if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
+		return pe
+	}
+	return nil
 }
diff --git a/vendor/github.com/miekg/dns/AUTHORS b/vendor/github.com/miekg/dns/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..1965683525addf5b9e195995e8e82a9a695e9664
--- /dev/null
+++ b/vendor/github.com/miekg/dns/AUTHORS
@@ -0,0 +1 @@
+Miek Gieben <miek@miek.nl>
diff --git a/vendor/github.com/miekg/dns/CONTRIBUTORS b/vendor/github.com/miekg/dns/CONTRIBUTORS
new file mode 100644
index 0000000000000000000000000000000000000000..f77e8a895f91bb1624ca2a8ede0d4961418822f4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/CONTRIBUTORS
@@ -0,0 +1,9 @@
+Alex A. Skinner
+Andrew Tunnell-Jones
+Ask Bjørn Hansen
+Dave Cheney
+Dusty Wilson
+Marek Majkowski
+Peter van Dijk
+Omri Bahumi
+Alex Sergeyev
diff --git a/vendor/github.com/miekg/dns/COPYRIGHT b/vendor/github.com/miekg/dns/COPYRIGHT
new file mode 100644
index 0000000000000000000000000000000000000000..35702b10e87ecd129b3374f554ab57cd59f7dcc9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/COPYRIGHT
@@ -0,0 +1,9 @@
+Copyright 2009 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.
+Extensions of the original work are copyright (c) 2011 Miek Gieben
+
+Copyright 2011 Miek Gieben. All rights reserved. Use of this source code is
+governed by a BSD-style license that can be found in the LICENSE file.
+
+Copyright 2014 CloudFlare. All rights reserved. Use of this source code is
+governed by a BSD-style license that can be found in the LICENSE file.
diff --git a/vendor/github.com/miekg/dns/LICENSE b/vendor/github.com/miekg/dns/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..5763fa7fe5d963c854627c7fd5b8a76534f5c0d1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/LICENSE
@@ -0,0 +1,32 @@
+Extensions of the original work are copyright (c) 2011 Miek Gieben
+
+As this is fork of the official Go code the same license applies:
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..744e20de5f17532c402ce95039c547152d3a5e21
--- /dev/null
+++ b/vendor/github.com/miekg/dns/README.md
@@ -0,0 +1,149 @@
+[![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns)
+
+# Alternative (more granular) approach to a DNS library
+
+> Less is more.
+
+Complete and usable DNS library. All widely used Resource Records are
+supported, including the DNSSEC types. It follows a lean and mean philosophy.
+If there is stuff you should know as a DNS programmer there isn't a convenience
+function for it. Server side and client side programming is supported, i.e. you
+can build servers and resolvers with it.
+
+If you like this, you may also be interested in:
+
+* https://github.com/miekg/unbound -- Go wrapper for the Unbound resolver.
+
+# Goals
+
+* KISS;
+* Fast;
+* Small API, if its easy to code in Go, don't make a function for it.
+
+# Users
+
+A not-so-up-to-date-list-that-may-be-actually-current:
+
+* https://cloudflare.com
+* https://github.com/abh/geodns
+* http://www.statdns.com/
+* http://www.dnsinspect.com/
+* https://github.com/chuangbo/jianbing-dictionary-dns
+* http://www.dns-lg.com/
+* https://github.com/fcambus/rrda
+* https://github.com/kenshinx/godns
+* https://github.com/skynetservices/skydns
+* https://github.com/DevelopersPL/godnsagent
+* https://github.com/duedil-ltd/discodns
+* https://github.com/StalkR/dns-reverse-proxy
+* https://github.com/tianon/rawdns
+* https://mesosphere.github.io/mesos-dns/
+* https://pulse.turbobytes.com/
+* https://play.google.com/store/apps/details?id=com.turbobytes.dig
+* https://github.com/fcambus/statzone
+* https://github.com/benschw/dns-clb-go
+* https://github.com/corny/dnscheck for http://public-dns.tk/
+
+Send pull request if you want to be listed here.
+
+# Features
+
+* UDP/TCP queries, IPv4 and IPv6;
+* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
+* Fast:
+    * Reply speed around ~ 80K qps (faster hardware results in more qps);
+    * Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
+* Server side programming (mimicking the net/http package);
+* Client side programming;
+* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
+* EDNS0, NSID;
+* AXFR/IXFR;
+* TSIG, SIG(0);
+* DNS name compression;
+* Depends only on the standard library.
+
+Have fun!
+
+Miek Gieben  -  2010-2012  -  <miek@miek.nl>
+
+# Building
+
+Building is done with the `go` tool. If you have setup your GOPATH
+correctly, the following should work:
+
+    go get github.com/miekg/dns
+    go build github.com/miekg/dns
+
+## Examples
+
+A short "how to use the API" is at the beginning of doc.go (this also will show
+when you call `godoc github.com/miekg/dns`).
+
+Example programs can be found in the `github.com/miekg/exdns` repository.
+
+## Supported RFCs
+
+*all of them*
+
+* 103{4,5} - DNS standard
+* 1348 - NSAP record (removed the record)
+* 1982 - Serial Arithmetic
+* 1876 - LOC record
+* 1995 - IXFR
+* 1996 - DNS notify
+* 2136 - DNS Update (dynamic updates)
+* 2181 - RRset definition - there is no RRset type though, just []RR
+* 2537 - RSAMD5 DNS keys
+* 2065 - DNSSEC (updated in later RFCs)
+* 2671 - EDNS record
+* 2782 - SRV record
+* 2845 - TSIG record
+* 2915 - NAPTR record
+* 2929 - DNS IANA Considerations
+* 3110 - RSASHA1 DNS keys
+* 3225 - DO bit (DNSSEC OK)
+* 340{1,2,3} - NAPTR record
+* 3445 - Limiting the scope of (DNS)KEY
+* 3597 - Unknown RRs
+* 4025 - IPSECKEY
+* 403{3,4,5} - DNSSEC + validation functions
+* 4255 - SSHFP record
+* 4343 - Case insensitivity
+* 4408 - SPF record
+* 4509 - SHA256 Hash in DS
+* 4592 - Wildcards in the DNS
+* 4635 - HMAC SHA TSIG
+* 4701 - DHCID
+* 4892 - id.server
+* 5001 - NSID
+* 5155 - NSEC3 record
+* 5205 - HIP record
+* 5702 - SHA2 in the DNS
+* 5936 - AXFR
+* 5966 - TCP implementation recommendations
+* 6605 - ECDSA
+* 6725 - IANA Registry Update
+* 6742 - ILNP DNS
+* 6844 - CAA record
+* 6891 - EDNS0 update
+* 6895 - DNS IANA considerations
+* 6975 - Algorithm Understanding in DNSSEC
+* 7043 - EUI48/EUI64 records
+* 7314 - DNS (EDNS) EXPIRE Option
+* 7553 - URI record
+* xxxx - EDNS0 DNS Update Lease (draft)
+
+## Loosely based upon
+
+* `ldns`
+* `NSD`
+* `Net::DNS`
+* `GRONG`
+
+## TODO
+
+* privatekey.Precompute() when signing?
+* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
+* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
+* NSEC(3) cover/match/closest enclose.
+* Replies with TC bit are not parsed to the end.
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
new file mode 100644
index 0000000000000000000000000000000000000000..ea0985194755d503b945d09e2d5059f188c01052
--- /dev/null
+++ b/vendor/github.com/miekg/dns/client.go
@@ -0,0 +1,378 @@
+package dns
+
+// A client implementation.
+
+import (
+	"bytes"
+	"io"
+	"net"
+	"time"
+)
+
+const dnsTimeout time.Duration = 2 * time.Second
+const tcpIdleTimeout time.Duration = 8 * time.Second
+
+// A Conn represents a connection to a DNS server.
+type Conn struct {
+	net.Conn                         // a net.Conn holding the connection
+	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
+	rtt            time.Duration
+	t              time.Time
+	tsigRequestMAC string
+}
+
+// A Client defines parameters for a DNS client.
+type Client struct {
+	Net            string            // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
+	UDPSize        uint16            // minimum receive buffer for UDP messages
+	DialTimeout    time.Duration     // net.DialTimeout, 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
+	TsigSecret     map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
+	group          singleflight
+}
+
+// Exchange performs a synchronous UDP query. It sends the message m to the address
+// contained in a and waits for an reply. Exchange does not retry a failed query, nor
+// will it fall back to TCP in case of truncation.
+// If you need to send a DNS message on an already existing connection, you can use the
+// following:
+//
+//	co := &dns.Conn{Conn: c} // c is your net.Conn
+//	co.WriteMsg(m)
+//	in, err := co.ReadMsg()
+//	co.Close()
+//
+func Exchange(m *Msg, a string) (r *Msg, err error) {
+	var co *Conn
+	co, err = DialTimeout("udp", a, dnsTimeout)
+	if err != nil {
+		return nil, err
+	}
+
+	defer co.Close()
+	co.SetReadDeadline(time.Now().Add(dnsTimeout))
+	co.SetWriteDeadline(time.Now().Add(dnsTimeout))
+
+	opt := m.IsEdns0()
+	// If EDNS0 is used use that for size.
+	if opt != nil && opt.UDPSize() >= MinMsgSize {
+		co.UDPSize = opt.UDPSize()
+	}
+
+	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
+}
+
+// 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 an synchronous query. It sends the message m to the address
+// contained in a and waits for an 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.
+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 {
+	if c.DialTimeout != 0 {
+		return c.DialTimeout
+	}
+	return dnsTimeout
+}
+
+func (c *Client) readTimeout() time.Duration {
+	if c.ReadTimeout != 0 {
+		return c.ReadTimeout
+	}
+	return dnsTimeout
+}
+
+func (c *Client) writeTimeout() time.Duration {
+	if c.WriteTimeout != 0 {
+		return c.WriteTimeout
+	}
+	return dnsTimeout
+}
+
+func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
+	var co *Conn
+	if c.Net == "" {
+		co, err = DialTimeout("udp", a, c.dialTimeout())
+	} else {
+		co, err = DialTimeout(c.Net, a, c.dialTimeout())
+	}
+	if err != nil {
+		return nil, 0, 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()
+	}
+	// Otherwise use the client's configured UDP size.
+	if opt == nil && c.UDPSize >= MinMsgSize {
+		co.UDPSize = c.UDPSize
+	}
+
+	co.SetReadDeadline(time.Now().Add(c.readTimeout()))
+	co.SetWriteDeadline(time.Now().Add(c.writeTimeout()))
+
+	co.TsigSecret = c.TsigSecret
+	if err = co.WriteMsg(m); err != nil {
+		return nil, 0, err
+	}
+	r, err = co.ReadMsg()
+	if err == nil && r.Id != m.Id {
+		err = ErrId
+	}
+	return r, co.rtt, err
+}
+
+// ReadMsg reads a message from the connection co.
+// If the received message contains a TSIG record the transaction
+// signature is verified.
+func (co *Conn) ReadMsg() (*Msg, error) {
+	p, err := co.ReadMsgHeader(nil)
+	if err != nil {
+		return nil, err
+	}
+
+	m := new(Msg)
+	if err := m.Unpack(p); err != nil {
+		return nil, err
+	}
+	if t := m.IsTsig(); t != nil {
+		if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
+			return m, ErrSecret
+		}
+		// Need to work on the original message p, as that was used to calculate the tsig.
+		err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
+	}
+	return m, err
+}
+
+// ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil).
+// Returns message as a byte slice to be parsed with Msg.Unpack later on.
+// Note that error handling on the message body is not possible as only the header is parsed.
+func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
+	var (
+		p   []byte
+		n   int
+		err error
+	)
+
+	if t, ok := co.Conn.(*net.TCPConn); ok {
+		// First two bytes specify the length of the entire message.
+		l, err := tcpMsgLen(t)
+		if err != nil {
+			return nil, err
+		}
+		p = make([]byte, l)
+		n, err = tcpRead(t, p)
+	} else {
+		if co.UDPSize > MinMsgSize {
+			p = make([]byte, co.UDPSize)
+		} else {
+			p = make([]byte, MinMsgSize)
+		}
+		n, err = co.Read(p)
+	}
+
+	if err != nil {
+		return nil, err
+	} else if n < headerSize {
+		return nil, ErrShortRead
+	}
+
+	p = p[:n]
+	if hdr != nil {
+		if _, err = UnpackStruct(hdr, p, 0); err != nil {
+			return nil, err
+		}
+	}
+	return p, err
+}
+
+// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
+func tcpMsgLen(t *net.TCPConn) (int, error) {
+	p := []byte{0, 0}
+	n, err := t.Read(p)
+	if err != nil {
+		return 0, err
+	}
+	if n != 2 {
+		return 0, ErrShortRead
+	}
+	l, _ := unpackUint16(p, 0)
+	if l == 0 {
+		return 0, ErrShortRead
+	}
+	return int(l), nil
+}
+
+// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
+func tcpRead(t *net.TCPConn, p []byte) (int, error) {
+	n, err := t.Read(p)
+	if err != nil {
+		return n, err
+	}
+	for n < len(p) {
+		j, err := t.Read(p[n:])
+		if err != nil {
+			return n, err
+		}
+		n += j
+	}
+	return n, err
+}
+
+// Read implements the net.Conn read method.
+func (co *Conn) Read(p []byte) (n int, err error) {
+	if co.Conn == nil {
+		return 0, ErrConnEmpty
+	}
+	if len(p) < 2 {
+		return 0, io.ErrShortBuffer
+	}
+	if t, ok := co.Conn.(*net.TCPConn); ok {
+		l, err := tcpMsgLen(t)
+		if err != nil {
+			return 0, err
+		}
+		if l > len(p) {
+			return int(l), io.ErrShortBuffer
+		}
+		return tcpRead(t, p[:l])
+	}
+	// UDP connection
+	n, err = co.Conn.Read(p)
+	if err != nil {
+		return n, err
+	}
+
+	co.rtt = time.Since(co.t)
+	return n, err
+}
+
+// WriteMsg sends a message throught the connection co.
+// If the message m contains a TSIG record the transaction
+// signature is calculated.
+func (co *Conn) WriteMsg(m *Msg) (err error) {
+	var out []byte
+	if t := m.IsTsig(); t != nil {
+		mac := ""
+		if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
+			return ErrSecret
+		}
+		out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
+		// Set for the next read, allthough only used in zone transfers
+		co.tsigRequestMAC = mac
+	} else {
+		out, err = m.Pack()
+	}
+	if err != nil {
+		return err
+	}
+	co.t = time.Now()
+	if _, err = co.Write(out); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Write implements the net.Conn Write method.
+func (co *Conn) Write(p []byte) (n int, err error) {
+	if t, ok := co.Conn.(*net.TCPConn); ok {
+		lp := len(p)
+		if lp < 2 {
+			return 0, io.ErrShortBuffer
+		}
+		if lp > MaxMsgSize {
+			return 0, &Error{err: "message too large"}
+		}
+		l := make([]byte, 2, lp+2)
+		l[0], l[1] = packUint16(uint16(lp))
+		p = append(l, p...)
+		n, err := io.Copy(t, bytes.NewReader(p))
+		return int(n), err
+	}
+	n, err = co.Conn.(*net.UDPConn).Write(p)
+	return n, err
+}
+
+// Dial connects to the address on the named network.
+func Dial(network, address string) (conn *Conn, err error) {
+	conn = new(Conn)
+	conn.Conn, err = net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	return conn, nil
+}
+
+// DialTimeout acts like Dial but takes a timeout.
+func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
+	conn = new(Conn)
+	conn.Conn, err = net.DialTimeout(network, address, timeout)
+	if err != nil {
+		return nil, err
+	}
+	return conn, nil
+}
diff --git a/vendor/github.com/miekg/dns/clientconfig.go b/vendor/github.com/miekg/dns/clientconfig.go
new file mode 100644
index 0000000000000000000000000000000000000000..cfa9ad0b228ee17fc80f743d5cddaa2eebb175bb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/clientconfig.go
@@ -0,0 +1,99 @@
+package dns
+
+import (
+	"bufio"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// ClientConfig wraps the contents of the /etc/resolv.conf file.
+type ClientConfig struct {
+	Servers  []string // servers to use
+	Search   []string // suffixes to append to local name
+	Port     string   // what port to use
+	Ndots    int      // number of dots in name to trigger absolute lookup
+	Timeout  int      // seconds before giving up on packet
+	Attempts int      // lost packets before giving up on server, not used in the package dns
+}
+
+// ClientConfigFromFile parses a resolv.conf(5) like file and returns
+// a *ClientConfig.
+func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
+	file, err := os.Open(resolvconf)
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+	c := new(ClientConfig)
+	scanner := bufio.NewScanner(file)
+	c.Servers = make([]string, 0)
+	c.Search = make([]string, 0)
+	c.Port = "53"
+	c.Ndots = 1
+	c.Timeout = 5
+	c.Attempts = 2
+
+	for scanner.Scan() {
+		if err := scanner.Err(); err != nil {
+			return nil, err
+		}
+		line := scanner.Text()
+		f := strings.Fields(line)
+		if len(f) < 1 {
+			continue
+		}
+		switch f[0] {
+		case "nameserver": // add one name server
+			if len(f) > 1 {
+				// One more check: make sure server name is
+				// just an IP address.  Otherwise we need DNS
+				// to look it up.
+				name := f[1]
+				c.Servers = append(c.Servers, name)
+			}
+
+		case "domain": // set search path to just this domain
+			if len(f) > 1 {
+				c.Search = make([]string, 1)
+				c.Search[0] = f[1]
+			} else {
+				c.Search = make([]string, 0)
+			}
+
+		case "search": // set search path to given servers
+			c.Search = make([]string, len(f)-1)
+			for i := 0; i < len(c.Search); i++ {
+				c.Search[i] = f[i+1]
+			}
+
+		case "options": // magic options
+			for i := 1; i < len(f); i++ {
+				s := f[i]
+				switch {
+				case len(s) >= 6 && s[:6] == "ndots:":
+					n, _ := strconv.Atoi(s[6:])
+					if n < 1 {
+						n = 1
+					}
+					c.Ndots = n
+				case len(s) >= 8 && s[:8] == "timeout:":
+					n, _ := strconv.Atoi(s[8:])
+					if n < 1 {
+						n = 1
+					}
+					c.Timeout = n
+				case len(s) >= 8 && s[:9] == "attempts:":
+					n, _ := strconv.Atoi(s[9:])
+					if n < 1 {
+						n = 1
+					}
+					c.Attempts = n
+				case s == "rotate":
+					/* not imp */
+				}
+			}
+		}
+	}
+	return c, nil
+}
diff --git a/vendor/github.com/miekg/dns/defaults.go b/vendor/github.com/miekg/dns/defaults.go
new file mode 100644
index 0000000000000000000000000000000000000000..63165b4fa9cecddcd84ddb54aabc8b86f5dc486f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/defaults.go
@@ -0,0 +1,278 @@
+package dns
+
+import (
+	"errors"
+	"net"
+	"strconv"
+)
+
+const hexDigit = "0123456789abcdef"
+
+// Everything is assumed in ClassINET.
+
+// SetReply creates a reply message from a request message.
+func (dns *Msg) SetReply(request *Msg) *Msg {
+	dns.Id = request.Id
+	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
+	dns.Response = true
+	dns.Opcode = OpcodeQuery
+	dns.Rcode = RcodeSuccess
+	if len(request.Question) > 0 {
+		dns.Question = make([]Question, 1)
+		dns.Question[0] = request.Question[0]
+	}
+	return dns
+}
+
+// SetQuestion creates a question message, it sets the Question
+// section, generates an Id and sets the RecursionDesired (RD)
+// bit to true.
+func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
+	dns.Id = Id()
+	dns.RecursionDesired = true
+	dns.Question = make([]Question, 1)
+	dns.Question[0] = Question{z, t, ClassINET}
+	return dns
+}
+
+// SetNotify creates a notify message, it sets the Question
+// section, generates an Id and sets the Authoritative (AA)
+// bit to true.
+func (dns *Msg) SetNotify(z string) *Msg {
+	dns.Opcode = OpcodeNotify
+	dns.Authoritative = true
+	dns.Id = Id()
+	dns.Question = make([]Question, 1)
+	dns.Question[0] = Question{z, TypeSOA, ClassINET}
+	return dns
+}
+
+// SetRcode creates an error message suitable for the request.
+func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
+	dns.SetReply(request)
+	dns.Rcode = rcode
+	return dns
+}
+
+// SetRcodeFormatError creates a message with FormError set.
+func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
+	dns.Rcode = RcodeFormatError
+	dns.Opcode = OpcodeQuery
+	dns.Response = true
+	dns.Authoritative = false
+	dns.Id = request.Id
+	return dns
+}
+
+// SetUpdate makes the message a dynamic update message. It
+// sets the ZONE section to: z, TypeSOA, ClassINET.
+func (dns *Msg) SetUpdate(z string) *Msg {
+	dns.Id = Id()
+	dns.Response = false
+	dns.Opcode = OpcodeUpdate
+	dns.Compress = false // BIND9 cannot handle compression
+	dns.Question = make([]Question, 1)
+	dns.Question[0] = Question{z, TypeSOA, ClassINET}
+	return dns
+}
+
+// SetIxfr creates message for requesting an IXFR.
+func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
+	dns.Id = Id()
+	dns.Question = make([]Question, 1)
+	dns.Ns = make([]RR, 1)
+	s := new(SOA)
+	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
+	s.Serial = serial
+	s.Ns = ns
+	s.Mbox = mbox
+	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
+	dns.Ns[0] = s
+	return dns
+}
+
+// SetAxfr creates message for requesting an AXFR.
+func (dns *Msg) SetAxfr(z string) *Msg {
+	dns.Id = Id()
+	dns.Question = make([]Question, 1)
+	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
+	return dns
+}
+
+// SetTsig appends a TSIG RR to the message.
+// This is only a skeleton TSIG RR that is added as the last RR in the
+// additional section. The Tsig is calculated when the message is being send.
+func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
+	t := new(TSIG)
+	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
+	t.Algorithm = algo
+	t.Fudge = 300
+	t.TimeSigned = uint64(timesigned)
+	t.OrigId = dns.Id
+	dns.Extra = append(dns.Extra, t)
+	return dns
+}
+
+// SetEdns0 appends a EDNS0 OPT RR to the message.
+// TSIG should always the last RR in a message.
+func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
+	e := new(OPT)
+	e.Hdr.Name = "."
+	e.Hdr.Rrtype = TypeOPT
+	e.SetUDPSize(udpsize)
+	if do {
+		e.SetDo()
+	}
+	dns.Extra = append(dns.Extra, e)
+	return dns
+}
+
+// IsTsig checks if the message has a TSIG record as the last record
+// in the additional section. It returns the TSIG record found or nil.
+func (dns *Msg) IsTsig() *TSIG {
+	if len(dns.Extra) > 0 {
+		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
+			return dns.Extra[len(dns.Extra)-1].(*TSIG)
+		}
+	}
+	return nil
+}
+
+// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
+// record in the additional section will do. It returns the OPT record
+// found or nil.
+func (dns *Msg) IsEdns0() *OPT {
+	for _, r := range dns.Extra {
+		if r.Header().Rrtype == TypeOPT {
+			return r.(*OPT)
+		}
+	}
+	return nil
+}
+
+// IsDomainName checks if s is a valid domain name, it returns the number of
+// labels and true, when a domain name is valid.  Note that non fully qualified
+// domain name is considered valid, in this case the last label is counted in
+// the number of labels.  When false is returned the number of labels is not
+// defined.  Also note that this function is extremely liberal; almost any
+// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
+// label fits in 63 characters, but there is no length check for the entire
+// string s. I.e.  a domain name longer than 255 characters is considered valid.
+func IsDomainName(s string) (labels int, ok bool) {
+	_, labels, err := packDomainName(s, nil, 0, nil, false)
+	return labels, err == nil
+}
+
+// IsSubDomain checks if child is indeed a child of the parent. Both child and
+// parent are *not* downcased before doing the comparison.
+func IsSubDomain(parent, child string) bool {
+	// Entire child is contained in parent
+	return CompareDomainName(parent, child) == CountLabel(parent)
+}
+
+// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
+// The checking is performed on the binary payload.
+func IsMsg(buf []byte) error {
+	// Header
+	if len(buf) < 12 {
+		return errors.New("dns: bad message header")
+	}
+	// Header: Opcode
+	// TODO(miek): more checks here, e.g. check all header bits.
+	return nil
+}
+
+// IsFqdn checks if a domain name is fully qualified.
+func IsFqdn(s string) bool {
+	l := len(s)
+	if l == 0 {
+		return false
+	}
+	return s[l-1] == '.'
+}
+
+// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
+// This means the RRs need to have the same type, name, and class. Returns true
+// if the RR set is valid, otherwise false.
+func IsRRset(rrset []RR) bool {
+	if len(rrset) == 0 {
+		return false
+	}
+	if len(rrset) == 1 {
+		return true
+	}
+	rrHeader := rrset[0].Header()
+	rrType := rrHeader.Rrtype
+	rrClass := rrHeader.Class
+	rrName := rrHeader.Name
+
+	for _, rr := range rrset[1:] {
+		curRRHeader := rr.Header()
+		if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
+			// Mismatch between the records, so this is not a valid rrset for
+			//signing/verifying
+			return false
+		}
+	}
+
+	return true
+}
+
+// Fqdn return the fully qualified domain name from s.
+// If s is already fully qualified, it behaves as the identity function.
+func Fqdn(s string) string {
+	if IsFqdn(s) {
+		return s
+	}
+	return s + "."
+}
+
+// Copied from the official Go code.
+
+// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
+// address suitable for reverse DNS (PTR) record lookups or an error if it fails
+// to parse the IP address.
+func ReverseAddr(addr string) (arpa string, err error) {
+	ip := net.ParseIP(addr)
+	if ip == nil {
+		return "", &Error{err: "unrecognized address: " + addr}
+	}
+	if ip.To4() != nil {
+		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
+			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
+	}
+	// Must be IPv6
+	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
+	// Add it, in reverse, to the buffer
+	for i := len(ip) - 1; i >= 0; i-- {
+		v := ip[i]
+		buf = append(buf, hexDigit[v&0xF])
+		buf = append(buf, '.')
+		buf = append(buf, hexDigit[v>>4])
+		buf = append(buf, '.')
+	}
+	// Append "ip6.arpa." and return (buf already has the final .)
+	buf = append(buf, "ip6.arpa."...)
+	return string(buf), nil
+}
+
+// String returns the string representation for the type t.
+func (t Type) String() string {
+	if t1, ok := TypeToString[uint16(t)]; ok {
+		return t1
+	}
+	return "TYPE" + strconv.Itoa(int(t))
+}
+
+// String returns the string representation for the class c.
+func (c Class) String() string {
+	if c1, ok := ClassToString[uint16(c)]; ok {
+		return c1
+	}
+	return "CLASS" + strconv.Itoa(int(c))
+}
+
+// String returns the string representation for the name n.
+func (n Name) String() string {
+	return sprintName(string(n))
+}
diff --git a/vendor/github.com/miekg/dns/dns.go b/vendor/github.com/miekg/dns/dns.go
new file mode 100644
index 0000000000000000000000000000000000000000..a3e4a0efae5571867a1b5b85a4b577aa0e3620b3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/dns.go
@@ -0,0 +1,100 @@
+package dns
+
+import "strconv"
+
+const (
+	year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
+	// DefaultMsgSize is the standard default for messages larger than 512 bytes.
+	DefaultMsgSize = 4096
+	// MinMsgSize is the minimal size of a DNS packet.
+	MinMsgSize = 512
+	// MaxMsgSize is the largest possible DNS packet.
+	MaxMsgSize = 65535
+	defaultTtl = 3600 // Default internal TTL.
+)
+
+// Error represents a DNS error
+type Error struct{ err string }
+
+func (e *Error) Error() string {
+	if e == nil {
+		return "dns: <nil>"
+	}
+	return "dns: " + e.err
+}
+
+// An RR represents a resource record.
+type RR interface {
+	// Header returns the header of an resource record. The header contains
+	// everything up to the rdata.
+	Header() *RR_Header
+	// String returns the text representation of the resource record.
+	String() string
+	// copy returns a copy of the RR
+	copy() RR
+	// len returns the length (in octets) of the uncompressed RR in wire format.
+	len() int
+}
+
+// RR_Header is the header all DNS resource records share.
+type RR_Header struct {
+	Name     string `dns:"cdomain-name"`
+	Rrtype   uint16
+	Class    uint16
+	Ttl      uint32
+	Rdlength uint16 // length of data after header
+}
+
+// Header returns itself. This is here to make RR_Header implement the RR interface.
+func (h *RR_Header) Header() *RR_Header { return h }
+
+// Just to imlement the RR interface.
+func (h *RR_Header) copy() RR { return nil }
+
+func (h *RR_Header) copyHeader() *RR_Header {
+	r := new(RR_Header)
+	r.Name = h.Name
+	r.Rrtype = h.Rrtype
+	r.Class = h.Class
+	r.Ttl = h.Ttl
+	r.Rdlength = h.Rdlength
+	return r
+}
+
+func (h *RR_Header) String() string {
+	var s string
+
+	if h.Rrtype == TypeOPT {
+		s = ";"
+		// and maybe other things
+	}
+
+	s += sprintName(h.Name) + "\t"
+	s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
+	s += Class(h.Class).String() + "\t"
+	s += Type(h.Rrtype).String() + "\t"
+	return s
+}
+
+func (h *RR_Header) len() int {
+	l := len(h.Name) + 1
+	l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
+	return l
+}
+
+// ToRFC3597 converts a known RR to the unknown RR representation
+// from RFC 3597.
+func (rr *RFC3597) ToRFC3597(r RR) error {
+	buf := make([]byte, r.len()*2)
+	off, err := PackStruct(r, buf, 0)
+	if err != nil {
+		return err
+	}
+	buf = buf[:off]
+	rawSetRdlength(buf, 0, off)
+	_, err = UnpackStruct(rr, buf, 0)
+	if err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go
new file mode 100644
index 0000000000000000000000000000000000000000..49ab4f1eb6f90bdd6ac830c8b16be403a25dfbfd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/dnssec.go
@@ -0,0 +1,659 @@
+package dns
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	_ "crypto/md5"
+	"crypto/rand"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/asn1"
+	"encoding/hex"
+	"math/big"
+	"sort"
+	"strings"
+	"time"
+)
+
+// DNSSEC encryption algorithm codes.
+const (
+	_ uint8 = iota
+	RSAMD5
+	DH
+	DSA
+	_ // Skip 4, RFC 6725, section 2.1
+	RSASHA1
+	DSANSEC3SHA1
+	RSASHA1NSEC3SHA1
+	RSASHA256
+	_ // Skip 9, RFC 6725, section 2.1
+	RSASHA512
+	_ // Skip 11, RFC 6725, section 2.1
+	ECCGOST
+	ECDSAP256SHA256
+	ECDSAP384SHA384
+	INDIRECT   uint8 = 252
+	PRIVATEDNS uint8 = 253 // Private (experimental keys)
+	PRIVATEOID uint8 = 254
+)
+
+// Map for algorithm names.
+var AlgorithmToString = map[uint8]string{
+	RSAMD5:           "RSAMD5",
+	DH:               "DH",
+	DSA:              "DSA",
+	RSASHA1:          "RSASHA1",
+	DSANSEC3SHA1:     "DSA-NSEC3-SHA1",
+	RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
+	RSASHA256:        "RSASHA256",
+	RSASHA512:        "RSASHA512",
+	ECCGOST:          "ECC-GOST",
+	ECDSAP256SHA256:  "ECDSAP256SHA256",
+	ECDSAP384SHA384:  "ECDSAP384SHA384",
+	INDIRECT:         "INDIRECT",
+	PRIVATEDNS:       "PRIVATEDNS",
+	PRIVATEOID:       "PRIVATEOID",
+}
+
+// Map of algorithm strings.
+var StringToAlgorithm = reverseInt8(AlgorithmToString)
+
+// Map of algorithm crypto hashes.
+var AlgorithmToHash = map[uint8]crypto.Hash{
+	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725
+	RSASHA1:          crypto.SHA1,
+	RSASHA1NSEC3SHA1: crypto.SHA1,
+	RSASHA256:        crypto.SHA256,
+	ECDSAP256SHA256:  crypto.SHA256,
+	ECDSAP384SHA384:  crypto.SHA384,
+	RSASHA512:        crypto.SHA512,
+}
+
+// DNSSEC hashing algorithm codes.
+const (
+	_      uint8 = iota
+	SHA1         // RFC 4034
+	SHA256       // RFC 4509
+	GOST94       // RFC 5933
+	SHA384       // Experimental
+	SHA512       // Experimental
+)
+
+// Map for hash names.
+var HashToString = map[uint8]string{
+	SHA1:   "SHA1",
+	SHA256: "SHA256",
+	GOST94: "GOST94",
+	SHA384: "SHA384",
+	SHA512: "SHA512",
+}
+
+// Map of hash strings.
+var StringToHash = reverseInt8(HashToString)
+
+// DNSKEY flag values.
+const (
+	SEP    = 1
+	REVOKE = 1 << 7
+	ZONE   = 1 << 8
+)
+
+// The RRSIG needs to be converted to wireformat with some of
+// the rdata (the signature) missing. Use this struct to easy
+// the conversion (and re-use the pack/unpack functions).
+type rrsigWireFmt struct {
+	TypeCovered uint16
+	Algorithm   uint8
+	Labels      uint8
+	OrigTtl     uint32
+	Expiration  uint32
+	Inception   uint32
+	KeyTag      uint16
+	SignerName  string `dns:"domain-name"`
+	/* No Signature */
+}
+
+// Used for converting DNSKEY's rdata to wirefmt.
+type dnskeyWireFmt struct {
+	Flags     uint16
+	Protocol  uint8
+	Algorithm uint8
+	PublicKey string `dns:"base64"`
+	/* Nothing is left out */
+}
+
+func divRoundUp(a, b int) int {
+	return (a + b - 1) / b
+}
+
+// KeyTag calculates the keytag (or key-id) of the DNSKEY.
+func (k *DNSKEY) KeyTag() uint16 {
+	if k == nil {
+		return 0
+	}
+	var keytag int
+	switch k.Algorithm {
+	case RSAMD5:
+		// Look at the bottom two bytes of the modules, which the last
+		// item in the pubkey. We could do this faster by looking directly
+		// at the base64 values. But I'm lazy.
+		modulus, _ := fromBase64([]byte(k.PublicKey))
+		if len(modulus) > 1 {
+			x, _ := unpackUint16(modulus, len(modulus)-2)
+			keytag = int(x)
+		}
+	default:
+		keywire := new(dnskeyWireFmt)
+		keywire.Flags = k.Flags
+		keywire.Protocol = k.Protocol
+		keywire.Algorithm = k.Algorithm
+		keywire.PublicKey = k.PublicKey
+		wire := make([]byte, DefaultMsgSize)
+		n, err := PackStruct(keywire, wire, 0)
+		if err != nil {
+			return 0
+		}
+		wire = wire[:n]
+		for i, v := range wire {
+			if i&1 != 0 {
+				keytag += int(v) // must be larger than uint32
+			} else {
+				keytag += int(v) << 8
+			}
+		}
+		keytag += (keytag >> 16) & 0xFFFF
+		keytag &= 0xFFFF
+	}
+	return uint16(keytag)
+}
+
+// ToDS converts a DNSKEY record to a DS record.
+func (k *DNSKEY) ToDS(h uint8) *DS {
+	if k == nil {
+		return nil
+	}
+	ds := new(DS)
+	ds.Hdr.Name = k.Hdr.Name
+	ds.Hdr.Class = k.Hdr.Class
+	ds.Hdr.Rrtype = TypeDS
+	ds.Hdr.Ttl = k.Hdr.Ttl
+	ds.Algorithm = k.Algorithm
+	ds.DigestType = h
+	ds.KeyTag = k.KeyTag()
+
+	keywire := new(dnskeyWireFmt)
+	keywire.Flags = k.Flags
+	keywire.Protocol = k.Protocol
+	keywire.Algorithm = k.Algorithm
+	keywire.PublicKey = k.PublicKey
+	wire := make([]byte, DefaultMsgSize)
+	n, err := PackStruct(keywire, wire, 0)
+	if err != nil {
+		return nil
+	}
+	wire = wire[:n]
+
+	owner := make([]byte, 255)
+	off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false)
+	if err1 != nil {
+		return nil
+	}
+	owner = owner[:off]
+	// RFC4034:
+	// digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+	// "|" denotes concatenation
+	// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+
+	// digest buffer
+	digest := append(owner, wire...) // another copy
+
+	var hash crypto.Hash
+	switch h {
+	case SHA1:
+		hash = crypto.SHA1
+	case SHA256:
+		hash = crypto.SHA256
+	case SHA384:
+		hash = crypto.SHA384
+	case SHA512:
+		hash = crypto.SHA512
+	default:
+		return nil
+	}
+
+	s := hash.New()
+	s.Write(digest)
+	ds.Digest = hex.EncodeToString(s.Sum(nil))
+	return ds
+}
+
+// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
+func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
+	c := &CDNSKEY{DNSKEY: *k}
+	c.Hdr = *k.Hdr.copyHeader()
+	c.Hdr.Rrtype = TypeCDNSKEY
+	return c
+}
+
+// ToCDS converts a DS record to a CDS record.
+func (d *DS) ToCDS() *CDS {
+	c := &CDS{DS: *d}
+	c.Hdr = *d.Hdr.copyHeader()
+	c.Hdr.Rrtype = TypeCDS
+	return c
+}
+
+// Sign signs an RRSet. The signature needs to be filled in with
+// the values: Inception, Expiration, KeyTag, SignerName and Algorithm.
+// The rest is copied from the RRset. Sign returns true when the signing went OK,
+// otherwise false.
+// There is no check if RRSet is a proper (RFC 2181) RRSet.
+// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
+// is used as the OrigTTL.
+func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
+	if k == nil {
+		return ErrPrivKey
+	}
+	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
+	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+		return ErrKey
+	}
+
+	rr.Hdr.Rrtype = TypeRRSIG
+	rr.Hdr.Name = rrset[0].Header().Name
+	rr.Hdr.Class = rrset[0].Header().Class
+	if rr.OrigTtl == 0 { // If set don't override
+		rr.OrigTtl = rrset[0].Header().Ttl
+	}
+	rr.TypeCovered = rrset[0].Header().Rrtype
+	rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
+
+	if strings.HasPrefix(rrset[0].Header().Name, "*") {
+		rr.Labels-- // wildcard, remove from label count
+	}
+
+	sigwire := new(rrsigWireFmt)
+	sigwire.TypeCovered = rr.TypeCovered
+	sigwire.Algorithm = rr.Algorithm
+	sigwire.Labels = rr.Labels
+	sigwire.OrigTtl = rr.OrigTtl
+	sigwire.Expiration = rr.Expiration
+	sigwire.Inception = rr.Inception
+	sigwire.KeyTag = rr.KeyTag
+	// For signing, lowercase this name
+	sigwire.SignerName = strings.ToLower(rr.SignerName)
+
+	// Create the desired binary blob
+	signdata := make([]byte, DefaultMsgSize)
+	n, err := PackStruct(sigwire, signdata, 0)
+	if err != nil {
+		return err
+	}
+	signdata = signdata[:n]
+	wire, err := rawSignatureData(rrset, rr)
+	if err != nil {
+		return err
+	}
+	signdata = append(signdata, wire...)
+
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
+		return ErrAlg
+	}
+
+	h := hash.New()
+	h.Write(signdata)
+
+	signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
+	if err != nil {
+		return err
+	}
+
+	rr.Signature = toBase64(signature)
+
+	return nil
+}
+
+func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
+	signature, err := k.Sign(rand.Reader, hashed, hash)
+	if err != nil {
+		return nil, err
+	}
+
+	switch alg {
+	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
+		return signature, nil
+
+	case ECDSAP256SHA256, ECDSAP384SHA384:
+		ecdsaSignature := &struct {
+			R, S *big.Int
+		}{}
+		if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
+			return nil, err
+		}
+
+		var intlen int
+		switch alg {
+		case ECDSAP256SHA256:
+			intlen = 32
+		case ECDSAP384SHA384:
+			intlen = 48
+		}
+
+		signature := intToBytes(ecdsaSignature.R, intlen)
+		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
+		return signature, nil
+
+	// There is no defined interface for what a DSA backed crypto.Signer returns
+	case DSA, DSANSEC3SHA1:
+		// 	t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
+		// 	signature := []byte{byte(t)}
+		// 	signature = append(signature, intToBytes(r1, 20)...)
+		// 	signature = append(signature, intToBytes(s1, 20)...)
+		// 	rr.Signature = signature
+	}
+
+	return nil, ErrAlg
+}
+
+// Verify validates an RRSet with the signature and key. This is only the
+// cryptographic test, the signature validity period must be checked separately.
+// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
+func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
+	// First the easy checks
+	if !IsRRset(rrset) {
+		return ErrRRset
+	}
+	if rr.KeyTag != k.KeyTag() {
+		return ErrKey
+	}
+	if rr.Hdr.Class != k.Hdr.Class {
+		return ErrKey
+	}
+	if rr.Algorithm != k.Algorithm {
+		return ErrKey
+	}
+	if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
+		return ErrKey
+	}
+	if k.Protocol != 3 {
+		return ErrKey
+	}
+
+	// IsRRset checked that we have at least one RR and that the RRs in
+	// the set have consistent type, class, and name. Also check that type and
+	// class matches the RRSIG record.
+	if rrset[0].Header().Class != rr.Hdr.Class {
+		return ErrRRset
+	}
+	if rrset[0].Header().Rrtype != rr.TypeCovered {
+		return ErrRRset
+	}
+
+	// RFC 4035 5.3.2.  Reconstructing the Signed Data
+	// Copy the sig, except the rrsig data
+	sigwire := new(rrsigWireFmt)
+	sigwire.TypeCovered = rr.TypeCovered
+	sigwire.Algorithm = rr.Algorithm
+	sigwire.Labels = rr.Labels
+	sigwire.OrigTtl = rr.OrigTtl
+	sigwire.Expiration = rr.Expiration
+	sigwire.Inception = rr.Inception
+	sigwire.KeyTag = rr.KeyTag
+	sigwire.SignerName = strings.ToLower(rr.SignerName)
+	// Create the desired binary blob
+	signeddata := make([]byte, DefaultMsgSize)
+	n, err := PackStruct(sigwire, signeddata, 0)
+	if err != nil {
+		return err
+	}
+	signeddata = signeddata[:n]
+	wire, err := rawSignatureData(rrset, rr)
+	if err != nil {
+		return err
+	}
+	signeddata = append(signeddata, wire...)
+
+	sigbuf := rr.sigBuf()           // Get the binary signature data
+	if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
+		// TODO(mg)
+		// remove the domain name and assume its our
+	}
+
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
+		return ErrAlg
+	}
+
+	switch rr.Algorithm {
+	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
+		// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
+		pubkey := k.publicKeyRSA() // Get the key
+		if pubkey == nil {
+			return ErrKey
+		}
+
+		h := hash.New()
+		h.Write(signeddata)
+		return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
+
+	case ECDSAP256SHA256, ECDSAP384SHA384:
+		pubkey := k.publicKeyECDSA()
+		if pubkey == nil {
+			return ErrKey
+		}
+
+		// Split sigbuf into the r and s coordinates
+		r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
+		s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
+
+		h := hash.New()
+		h.Write(signeddata)
+		if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
+			return nil
+		}
+		return ErrSig
+
+	default:
+		return ErrAlg
+	}
+}
+
+// ValidityPeriod uses RFC1982 serial arithmetic to calculate
+// if a signature period is valid. If t is the zero time, the
+// current time is taken other t is. Returns true if the signature
+// is valid at the given time, otherwise returns false.
+func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
+	var utc int64
+	if t.IsZero() {
+		utc = time.Now().UTC().Unix()
+	} else {
+		utc = t.UTC().Unix()
+	}
+	modi := (int64(rr.Inception) - utc) / year68
+	mode := (int64(rr.Expiration) - utc) / year68
+	ti := int64(rr.Inception) + (modi * year68)
+	te := int64(rr.Expiration) + (mode * year68)
+	return ti <= utc && utc <= te
+}
+
+// Return the signatures base64 encodedig sigdata as a byte slice.
+func (rr *RRSIG) sigBuf() []byte {
+	sigbuf, err := fromBase64([]byte(rr.Signature))
+	if err != nil {
+		return nil
+	}
+	return sigbuf
+}
+
+// publicKeyRSA returns the RSA public key from a DNSKEY record.
+func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
+	keybuf, err := fromBase64([]byte(k.PublicKey))
+	if err != nil {
+		return nil
+	}
+
+	// RFC 2537/3110, section 2. RSA Public KEY Resource Records
+	// Length is in the 0th byte, unless its zero, then it
+	// it in bytes 1 and 2 and its a 16 bit number
+	explen := uint16(keybuf[0])
+	keyoff := 1
+	if explen == 0 {
+		explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
+		keyoff = 3
+	}
+	pubkey := new(rsa.PublicKey)
+
+	pubkey.N = big.NewInt(0)
+	shift := uint64((explen - 1) * 8)
+	expo := uint64(0)
+	for i := int(explen - 1); i > 0; i-- {
+		expo += uint64(keybuf[keyoff+i]) << shift
+		shift -= 8
+	}
+	// Remainder
+	expo += uint64(keybuf[keyoff])
+	if expo > 2<<31 {
+		// Larger expo than supported.
+		// println("dns: F5 primes (or larger) are not supported")
+		return nil
+	}
+	pubkey.E = int(expo)
+
+	pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
+	return pubkey
+}
+
+// publicKeyECDSA returns the Curve public key from the DNSKEY record.
+func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
+	keybuf, err := fromBase64([]byte(k.PublicKey))
+	if err != nil {
+		return nil
+	}
+	pubkey := new(ecdsa.PublicKey)
+	switch k.Algorithm {
+	case ECDSAP256SHA256:
+		pubkey.Curve = elliptic.P256()
+		if len(keybuf) != 64 {
+			// wrongly encoded key
+			return nil
+		}
+	case ECDSAP384SHA384:
+		pubkey.Curve = elliptic.P384()
+		if len(keybuf) != 96 {
+			// Wrongly encoded key
+			return nil
+		}
+	}
+	pubkey.X = big.NewInt(0)
+	pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
+	pubkey.Y = big.NewInt(0)
+	pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
+	return pubkey
+}
+
+func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
+	keybuf, err := fromBase64([]byte(k.PublicKey))
+	if err != nil {
+		return nil
+	}
+	if len(keybuf) < 22 {
+		return nil
+	}
+	t, keybuf := int(keybuf[0]), keybuf[1:]
+	size := 64 + t*8
+	q, keybuf := keybuf[:20], keybuf[20:]
+	if len(keybuf) != 3*size {
+		return nil
+	}
+	p, keybuf := keybuf[:size], keybuf[size:]
+	g, y := keybuf[:size], keybuf[size:]
+	pubkey := new(dsa.PublicKey)
+	pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
+	pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
+	pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
+	pubkey.Y = big.NewInt(0).SetBytes(y)
+	return pubkey
+}
+
+type wireSlice [][]byte
+
+func (p wireSlice) Len() int      { return len(p) }
+func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p wireSlice) Less(i, j int) bool {
+	_, ioff, _ := UnpackDomainName(p[i], 0)
+	_, joff, _ := UnpackDomainName(p[j], 0)
+	return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0
+}
+
+// Return the raw signature data.
+func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
+	wires := make(wireSlice, len(rrset))
+	for i, r := range rrset {
+		r1 := r.copy()
+		r1.Header().Ttl = s.OrigTtl
+		labels := SplitDomainName(r1.Header().Name)
+		// 6.2. Canonical RR Form. (4) - wildcards
+		if len(labels) > int(s.Labels) {
+			// Wildcard
+			r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
+		}
+		// RFC 4034: 6.2.  Canonical RR Form. (2) - domain name to lowercase
+		r1.Header().Name = strings.ToLower(r1.Header().Name)
+		// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
+		//   NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+		//   HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+		//   SRV, DNAME, A6
+		switch x := r1.(type) {
+		case *NS:
+			x.Ns = strings.ToLower(x.Ns)
+		case *CNAME:
+			x.Target = strings.ToLower(x.Target)
+		case *SOA:
+			x.Ns = strings.ToLower(x.Ns)
+			x.Mbox = strings.ToLower(x.Mbox)
+		case *MB:
+			x.Mb = strings.ToLower(x.Mb)
+		case *MG:
+			x.Mg = strings.ToLower(x.Mg)
+		case *MR:
+			x.Mr = strings.ToLower(x.Mr)
+		case *PTR:
+			x.Ptr = strings.ToLower(x.Ptr)
+		case *MINFO:
+			x.Rmail = strings.ToLower(x.Rmail)
+			x.Email = strings.ToLower(x.Email)
+		case *MX:
+			x.Mx = strings.ToLower(x.Mx)
+		case *NAPTR:
+			x.Replacement = strings.ToLower(x.Replacement)
+		case *KX:
+			x.Exchanger = strings.ToLower(x.Exchanger)
+		case *SRV:
+			x.Target = strings.ToLower(x.Target)
+		case *DNAME:
+			x.Target = strings.ToLower(x.Target)
+		}
+		// 6.2. Canonical RR Form. (5) - origTTL
+		wire := make([]byte, r1.len()+1) // +1 to be safe(r)
+		off, err1 := PackRR(r1, wire, 0, nil, false)
+		if err1 != nil {
+			return nil, err1
+		}
+		wire = wire[:off]
+		wires[i] = wire
+	}
+	sort.Sort(wires)
+	for i, wire := range wires {
+		if i > 0 && bytes.Equal(wire, wires[i-1]) {
+			continue
+		}
+		buf = append(buf, wire...)
+	}
+	return buf, nil
+}
diff --git a/vendor/github.com/miekg/dns/dnssec_keygen.go b/vendor/github.com/miekg/dns/dnssec_keygen.go
new file mode 100644
index 0000000000000000000000000000000000000000..229a079370b742295b99fe3ee9342b77bfb4fd0d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/dnssec_keygen.go
@@ -0,0 +1,156 @@
+package dns
+
+import (
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	"math/big"
+)
+
+// Generate generates a DNSKEY of the given bit size.
+// The public part is put inside the DNSKEY record.
+// The Algorithm in the key must be set as this will define
+// what kind of DNSKEY will be generated.
+// The ECDSA algorithms imply a fixed keysize, in that case
+// bits should be set to the size of the algorithm.
+func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
+	switch k.Algorithm {
+	case DSA, DSANSEC3SHA1:
+		if bits != 1024 {
+			return nil, ErrKeySize
+		}
+	case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
+		if bits < 512 || bits > 4096 {
+			return nil, ErrKeySize
+		}
+	case RSASHA512:
+		if bits < 1024 || bits > 4096 {
+			return nil, ErrKeySize
+		}
+	case ECDSAP256SHA256:
+		if bits != 256 {
+			return nil, ErrKeySize
+		}
+	case ECDSAP384SHA384:
+		if bits != 384 {
+			return nil, ErrKeySize
+		}
+	}
+
+	switch k.Algorithm {
+	case DSA, DSANSEC3SHA1:
+		params := new(dsa.Parameters)
+		if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
+			return nil, err
+		}
+		priv := new(dsa.PrivateKey)
+		priv.PublicKey.Parameters = *params
+		err := dsa.GenerateKey(priv, rand.Reader)
+		if err != nil {
+			return nil, err
+		}
+		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
+		return priv, nil
+	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
+		priv, err := rsa.GenerateKey(rand.Reader, bits)
+		if err != nil {
+			return nil, err
+		}
+		k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
+		return priv, nil
+	case ECDSAP256SHA256, ECDSAP384SHA384:
+		var c elliptic.Curve
+		switch k.Algorithm {
+		case ECDSAP256SHA256:
+			c = elliptic.P256()
+		case ECDSAP384SHA384:
+			c = elliptic.P384()
+		}
+		priv, err := ecdsa.GenerateKey(c, rand.Reader)
+		if err != nil {
+			return nil, err
+		}
+		k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
+		return priv, nil
+	default:
+		return nil, ErrAlg
+	}
+}
+
+// Set the public key (the value E and N)
+func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
+	if _E == 0 || _N == nil {
+		return false
+	}
+	buf := exponentToBuf(_E)
+	buf = append(buf, _N.Bytes()...)
+	k.PublicKey = toBase64(buf)
+	return true
+}
+
+// Set the public key for Elliptic Curves
+func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
+	if _X == nil || _Y == nil {
+		return false
+	}
+	var intlen int
+	switch k.Algorithm {
+	case ECDSAP256SHA256:
+		intlen = 32
+	case ECDSAP384SHA384:
+		intlen = 48
+	}
+	k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
+	return true
+}
+
+// Set the public key for DSA
+func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
+	if _Q == nil || _P == nil || _G == nil || _Y == nil {
+		return false
+	}
+	buf := dsaToBuf(_Q, _P, _G, _Y)
+	k.PublicKey = toBase64(buf)
+	return true
+}
+
+// Set the public key (the values E and N) for RSA
+// RFC 3110: Section 2. RSA Public KEY Resource Records
+func exponentToBuf(_E int) []byte {
+	var buf []byte
+	i := big.NewInt(int64(_E))
+	if len(i.Bytes()) < 256 {
+		buf = make([]byte, 1)
+		buf[0] = uint8(len(i.Bytes()))
+	} else {
+		buf = make([]byte, 3)
+		buf[0] = 0
+		buf[1] = uint8(len(i.Bytes()) >> 8)
+		buf[2] = uint8(len(i.Bytes()))
+	}
+	buf = append(buf, i.Bytes()...)
+	return buf
+}
+
+// Set the public key for X and Y for Curve. The two
+// values are just concatenated.
+func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
+	buf := intToBytes(_X, intlen)
+	buf = append(buf, intToBytes(_Y, intlen)...)
+	return buf
+}
+
+// Set the public key for X and Y for Curve. The two
+// values are just concatenated.
+func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
+	t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
+	buf := []byte{byte(t)}
+	buf = append(buf, intToBytes(_Q, 20)...)
+	buf = append(buf, intToBytes(_P, 64+t*8)...)
+	buf = append(buf, intToBytes(_G, 64+t*8)...)
+	buf = append(buf, intToBytes(_Y, 64+t*8)...)
+	return buf
+}
diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go
new file mode 100644
index 0000000000000000000000000000000000000000..19a783389ab2f64c38a9fe650d7322b9d0782fcd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go
@@ -0,0 +1,249 @@
+package dns
+
+import (
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"io"
+	"math/big"
+	"strconv"
+	"strings"
+)
+
+// NewPrivateKey returns a PrivateKey by parsing the string s.
+// s should be in the same form of the BIND private key files.
+func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
+	if s[len(s)-1] != '\n' { // We need a closing newline
+		return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
+	}
+	return k.ReadPrivateKey(strings.NewReader(s), "")
+}
+
+// ReadPrivateKey reads a private key from the io.Reader q. The string file is
+// only used in error reporting.
+// The public key must be known, because some cryptographic algorithms embed
+// the public inside the privatekey.
+func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
+	m, e := parseKey(q, file)
+	if m == nil {
+		return nil, e
+	}
+	if _, ok := m["private-key-format"]; !ok {
+		return nil, ErrPrivKey
+	}
+	if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" {
+		return nil, ErrPrivKey
+	}
+	// TODO(mg): check if the pubkey matches the private key
+	algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
+	if err != nil {
+		return nil, ErrPrivKey
+	}
+	switch uint8(algo) {
+	case DSA:
+		priv, e := readPrivateKeyDSA(m)
+		if e != nil {
+			return nil, e
+		}
+		pub := k.publicKeyDSA()
+		if pub == nil {
+			return nil, ErrKey
+		}
+		priv.PublicKey = *pub
+		return priv, e
+	case RSAMD5:
+		fallthrough
+	case RSASHA1:
+		fallthrough
+	case RSASHA1NSEC3SHA1:
+		fallthrough
+	case RSASHA256:
+		fallthrough
+	case RSASHA512:
+		priv, e := readPrivateKeyRSA(m)
+		if e != nil {
+			return nil, e
+		}
+		pub := k.publicKeyRSA()
+		if pub == nil {
+			return nil, ErrKey
+		}
+		priv.PublicKey = *pub
+		return priv, e
+	case ECCGOST:
+		return nil, ErrPrivKey
+	case ECDSAP256SHA256:
+		fallthrough
+	case ECDSAP384SHA384:
+		priv, e := readPrivateKeyECDSA(m)
+		if e != nil {
+			return nil, e
+		}
+		pub := k.publicKeyECDSA()
+		if pub == nil {
+			return nil, ErrKey
+		}
+		priv.PublicKey = *pub
+		return priv, e
+	default:
+		return nil, ErrPrivKey
+	}
+}
+
+// Read a private key (file) string and create a public key. Return the private key.
+func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
+	p := new(rsa.PrivateKey)
+	p.Primes = []*big.Int{nil, nil}
+	for k, v := range m {
+		switch k {
+		case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
+			v1, err := fromBase64([]byte(v))
+			if err != nil {
+				return nil, err
+			}
+			switch k {
+			case "modulus":
+				p.PublicKey.N = big.NewInt(0)
+				p.PublicKey.N.SetBytes(v1)
+			case "publicexponent":
+				i := big.NewInt(0)
+				i.SetBytes(v1)
+				p.PublicKey.E = int(i.Int64()) // int64 should be large enough
+			case "privateexponent":
+				p.D = big.NewInt(0)
+				p.D.SetBytes(v1)
+			case "prime1":
+				p.Primes[0] = big.NewInt(0)
+				p.Primes[0].SetBytes(v1)
+			case "prime2":
+				p.Primes[1] = big.NewInt(0)
+				p.Primes[1].SetBytes(v1)
+			}
+		case "exponent1", "exponent2", "coefficient":
+			// not used in Go (yet)
+		case "created", "publish", "activate":
+			// not used in Go (yet)
+		}
+	}
+	return p, nil
+}
+
+func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
+	p := new(dsa.PrivateKey)
+	p.X = big.NewInt(0)
+	for k, v := range m {
+		switch k {
+		case "private_value(x)":
+			v1, err := fromBase64([]byte(v))
+			if err != nil {
+				return nil, err
+			}
+			p.X.SetBytes(v1)
+		case "created", "publish", "activate":
+			/* not used in Go (yet) */
+		}
+	}
+	return p, nil
+}
+
+func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
+	p := new(ecdsa.PrivateKey)
+	p.D = big.NewInt(0)
+	// TODO: validate that the required flags are present
+	for k, v := range m {
+		switch k {
+		case "privatekey":
+			v1, err := fromBase64([]byte(v))
+			if err != nil {
+				return nil, err
+			}
+			p.D.SetBytes(v1)
+		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,
+// 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) {
+	s := scanInit(r)
+	m := make(map[string]string)
+	c := make(chan lex)
+	k := ""
+	// Start the lexer
+	go klexer(s, c)
+	for l := range c {
+		// It should alternate
+		switch l.value {
+		case zKey:
+			k = l.token
+		case zValue:
+			if k == "" {
+				return nil, &ParseError{file, "no private key seen", l}
+			}
+			//println("Setting", strings.ToLower(k), "to", l.token, "b")
+			m[strings.ToLower(k)] = l.token
+			k = ""
+		}
+	}
+	return m, nil
+}
+
+// klexer scans the sourcefile and returns tokens on the channel c.
+func klexer(s *scan, c chan lex) {
+	var l lex
+	str := "" // Hold the current read text
+	commt := false
+	key := true
+	x, err := s.tokenText()
+	defer close(c)
+	for err == nil {
+		l.column = s.position.Column
+		l.line = s.position.Line
+		switch x {
+		case ':':
+			if commt {
+				break
+			}
+			l.token = str
+			if key {
+				l.value = zKey
+				c <- l
+				// Next token is a space, eat it
+				s.tokenText()
+				key = false
+				str = ""
+			} else {
+				l.value = zValue
+			}
+		case ';':
+			commt = true
+		case '\n':
+			if commt {
+				// Reset a comment
+				commt = false
+			}
+			l.value = zValue
+			l.token = str
+			c <- l
+			str = ""
+			commt = false
+			key = true
+		default:
+			if commt {
+				break
+			}
+			str += string(x)
+		}
+		x, err = s.tokenText()
+	}
+	if len(str) > 0 {
+		// Send remainder
+		l.token = str
+		l.value = zValue
+		c <- l
+	}
+}
diff --git a/vendor/github.com/miekg/dns/dnssec_privkey.go b/vendor/github.com/miekg/dns/dnssec_privkey.go
new file mode 100644
index 0000000000000000000000000000000000000000..56f3ea934f63f731de101a729d40350006bc1956
--- /dev/null
+++ b/vendor/github.com/miekg/dns/dnssec_privkey.go
@@ -0,0 +1,85 @@
+package dns
+
+import (
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"math/big"
+	"strconv"
+)
+
+const format = "Private-key-format: v1.3\n"
+
+// PrivateKeyString converts a PrivateKey to a string. This string has the same
+// format as the private-key-file of BIND9 (Private-key-format: v1.3).
+// It needs some info from the key (the algorithm), so its a method of the DNSKEY
+// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey
+func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
+	algorithm := strconv.Itoa(int(r.Algorithm))
+	algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
+
+	switch p := p.(type) {
+	case *rsa.PrivateKey:
+		modulus := toBase64(p.PublicKey.N.Bytes())
+		e := big.NewInt(int64(p.PublicKey.E))
+		publicExponent := toBase64(e.Bytes())
+		privateExponent := toBase64(p.D.Bytes())
+		prime1 := toBase64(p.Primes[0].Bytes())
+		prime2 := toBase64(p.Primes[1].Bytes())
+		// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
+		// and from: http://code.google.com/p/go/issues/detail?id=987
+		one := big.NewInt(1)
+		p1 := big.NewInt(0).Sub(p.Primes[0], one)
+		q1 := big.NewInt(0).Sub(p.Primes[1], one)
+		exp1 := big.NewInt(0).Mod(p.D, p1)
+		exp2 := big.NewInt(0).Mod(p.D, q1)
+		coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
+
+		exponent1 := toBase64(exp1.Bytes())
+		exponent2 := toBase64(exp2.Bytes())
+		coefficient := toBase64(coeff.Bytes())
+
+		return format +
+			"Algorithm: " + algorithm + "\n" +
+			"Modulus: " + modulus + "\n" +
+			"PublicExponent: " + publicExponent + "\n" +
+			"PrivateExponent: " + privateExponent + "\n" +
+			"Prime1: " + prime1 + "\n" +
+			"Prime2: " + prime2 + "\n" +
+			"Exponent1: " + exponent1 + "\n" +
+			"Exponent2: " + exponent2 + "\n" +
+			"Coefficient: " + coefficient + "\n"
+
+	case *ecdsa.PrivateKey:
+		var intlen int
+		switch r.Algorithm {
+		case ECDSAP256SHA256:
+			intlen = 32
+		case ECDSAP384SHA384:
+			intlen = 48
+		}
+		private := toBase64(intToBytes(p.D, intlen))
+		return format +
+			"Algorithm: " + algorithm + "\n" +
+			"PrivateKey: " + private + "\n"
+
+	case *dsa.PrivateKey:
+		T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
+		prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
+		subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
+		base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
+		priv := toBase64(intToBytes(p.X, 20))
+		pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
+		return format +
+			"Algorithm: " + algorithm + "\n" +
+			"Prime(p): " + prime + "\n" +
+			"Subprime(q): " + subprime + "\n" +
+			"Base(g): " + base + "\n" +
+			"Private_value(x): " + priv + "\n" +
+			"Public_value(y): " + pub + "\n"
+
+	default:
+		return ""
+	}
+}
diff --git a/vendor/github.com/miekg/dns/doc.go b/vendor/github.com/miekg/dns/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..89eace59de904da069a18a2be7dc46abfb58b590
--- /dev/null
+++ b/vendor/github.com/miekg/dns/doc.go
@@ -0,0 +1,251 @@
+/*
+Package dns implements a full featured interface to the Domain Name System.
+Server- and client-side programming is supported.
+The package allows complete control over what is send out to the DNS. The package
+API follows the less-is-more principle, by presenting a small, clean interface.
+
+The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
+TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
+Note that domain names MUST be fully qualified, before sending them, unqualified
+names in a message will result in a packing failure.
+
+Resource records are native types. They are not stored in wire format.
+Basic usage pattern for creating a new resource record:
+
+     r := new(dns.MX)
+     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
+	Class: dns.ClassINET, Ttl: 3600}
+     r.Preference = 10
+     r.Mx = "mx.miek.nl."
+
+Or directly from a string:
+
+     mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
+
+Or when the default TTL (3600) and class (IN) suit you:
+
+     mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
+
+Or even:
+
+     mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
+
+In the DNS messages are exchanged, these messages contain resource
+records (sets).  Use pattern for creating a message:
+
+     m := new(dns.Msg)
+     m.SetQuestion("miek.nl.", dns.TypeMX)
+
+Or when not certain if the domain name is fully qualified:
+
+	m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
+
+The message m is now a message with the question section set to ask
+the MX records for the miek.nl. zone.
+
+The following is slightly more verbose, but more flexible:
+
+     m1 := new(dns.Msg)
+     m1.Id = dns.Id()
+     m1.RecursionDesired = true
+     m1.Question = make([]dns.Question, 1)
+     m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
+
+After creating a message it can be send.
+Basic use pattern for synchronous querying the DNS at a
+server configured on 127.0.0.1 and port 53:
+
+     c := new(dns.Client)
+     in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
+
+Suppressing multiple outstanding queries (with the same question, type and
+class) is as easy as setting:
+
+	c.SingleInflight = true
+
+If these "advanced" features are not needed, a simple UDP query can be send,
+with:
+
+	in, err := dns.Exchange(m1, "127.0.0.1:53")
+
+When this functions returns you will get dns message. A dns message consists
+out of four sections.
+The question section: in.Question, the answer section: in.Answer,
+the authority section: in.Ns and the additional section: in.Extra.
+
+Each of these sections (except the Question section) contain a []RR. Basic
+use pattern for accessing the rdata of a TXT RR as the first RR in
+the Answer section:
+
+	if t, ok := in.Answer[0].(*dns.TXT); ok {
+		// do something with t.Txt
+	}
+
+Domain Name and TXT Character String Representations
+
+Both domain names and TXT character strings are converted to presentation
+form both when unpacked and when converted to strings.
+
+For TXT character strings, tabs, carriage returns and line feeds will be
+converted to \t, \r and \n respectively. Back slashes and quotations marks
+will be escaped. Bytes below 32 and above 127 will be converted to \DDD
+form.
+
+For domain names, in addition to the above rules brackets, periods,
+spaces, semicolons and the at symbol are escaped.
+
+DNSSEC
+
+DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
+uses public key cryptography to sign resource records. The
+public keys are stored in DNSKEY records and the signatures in RRSIG records.
+
+Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
+to an request.
+
+     m := new(dns.Msg)
+     m.SetEdns0(4096, true)
+
+Signature generation, signature verification and key generation are all supported.
+
+DYNAMIC UPDATES
+
+Dynamic updates reuses the DNS message format, but renames three of
+the sections. Question is Zone, Answer is Prerequisite, Authority is
+Update, only the Additional is not renamed. See RFC 2136 for the gory details.
+
+You can set a rather complex set of rules for the existence of absence of
+certain resource records or names in a zone to specify if resource records
+should be added or removed. The table from RFC 2136 supplemented with the Go
+DNS function shows which functions exist to specify the prerequisites.
+
+ 3.2.4 - Table Of Metavalues Used In Prerequisite Section
+
+  CLASS    TYPE     RDATA    Meaning                    Function
+  --------------------------------------------------------------
+  ANY      ANY      empty    Name is in use             dns.NameUsed
+  ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed
+  NONE     ANY      empty    Name is not in use         dns.NameNotUsed
+  NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
+  zone     rrset    rr       RRset exists (value dep)   dns.Used
+
+The prerequisite section can also be left empty.
+If you have decided on the prerequisites you can tell what RRs should
+be added or deleted. The next table shows the options you have and
+what functions to call.
+
+ 3.4.2.6 - Table Of Metavalues Used In Update Section
+
+  CLASS    TYPE     RDATA    Meaning                     Function
+  ---------------------------------------------------------------
+  ANY      ANY      empty    Delete all RRsets from name dns.RemoveName
+  ANY      rrset    empty    Delete an RRset             dns.RemoveRRset
+  NONE     rrset    rr       Delete an RR from RRset     dns.Remove
+  zone     rrset    rr       Add to an RRset             dns.Insert
+
+TRANSACTION SIGNATURE
+
+An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
+The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512.
+
+Basic use pattern when querying with a TSIG name "axfr." (note that these key names
+must be fully qualified - as they are domain names) and the base64 secret
+"so6ZGir4GPAqINNh9U5c3A==":
+
+	c := new(dns.Client)
+	c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+	m := new(dns.Msg)
+	m.SetQuestion("miek.nl.", dns.TypeMX)
+	m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+	...
+	// When sending the TSIG RR is calculated and filled in before sending
+
+When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
+TSIG, this is the basic use pattern. In this example we request an AXFR for
+miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
+and using the server 176.58.119.54:
+
+	t := new(dns.Transfer)
+	m := new(dns.Msg)
+	t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+	m.SetAxfr("miek.nl.")
+	m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+	c, err := t.In(m, "176.58.119.54:53")
+	for r := range c { ... }
+
+You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
+If something is not correct an error is returned.
+
+Basic use pattern validating and replying to a message that has TSIG set.
+
+	server := &dns.Server{Addr: ":53", Net: "udp"}
+	server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+	go server.ListenAndServe()
+	dns.HandleFunc(".", handleRequest)
+
+	func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
+		m := new(dns.Msg)
+		m.SetReply(r)
+		if r.IsTsig() {
+			if w.TsigStatus() == nil {
+				// *Msg r has an TSIG record and it was validated
+				m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+			} else {
+				// *Msg r has an TSIG records and it was not valided
+			}
+		}
+		w.WriteMsg(m)
+	}
+
+PRIVATE RRS
+
+RFC 6895 sets aside a range of type codes for private use. This range
+is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
+can be used, before requesting an official type code from IANA.
+
+see http://miek.nl/posts/2014/Sep/21/Private%20RRs%20and%20IDN%20in%20Go%20DNS/ for more
+information.
+
+EDNS0
+
+EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
+by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
+abused.
+Basic use pattern for creating an (empty) OPT RR:
+
+	o := new(dns.OPT)
+	o.Hdr.Name = "." // MUST be the root zone, per definition.
+	o.Hdr.Rrtype = dns.TypeOPT
+
+The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
+interfaces. Currently only a few have been standardized: EDNS0_NSID
+(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
+that these options may be combined in an OPT RR.
+Basic use pattern for a server to check if (and which) options are set:
+
+	// o is a dns.OPT
+	for _, s := range o.Option {
+		switch e := s.(type) {
+		case *dns.EDNS0_NSID:
+			// do stuff with e.Nsid
+		case *dns.EDNS0_SUBNET:
+			// access e.Family, e.Address, etc.
+		}
+	}
+
+SIG(0)
+
+From RFC 2931:
+
+    SIG(0) provides protection for DNS transactions and requests ....
+    ... protection for glue records, DNS requests, protection for message headers
+    on requests and responses, and protection of the overall integrity of a response.
+
+It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
+secret approach in TSIG.
+Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
+RSASHA512.
+
+Signing subsequent messages in multi-message sessions is not implemented.
+*/
+package dns
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
new file mode 100644
index 0000000000000000000000000000000000000000..87c8affec2d214ed6551e417cd8a0b63f4a5ab27
--- /dev/null
+++ b/vendor/github.com/miekg/dns/edns.go
@@ -0,0 +1,514 @@
+package dns
+
+import (
+	"encoding/hex"
+	"errors"
+	"net"
+	"strconv"
+)
+
+// EDNS0 Option codes.
+const (
+	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
+	EDNS0NSID        = 0x3     // nsid (RFC5001)
+	EDNS0DAU         = 0x5     // DNSSEC Algorithm Understood
+	EDNS0DHU         = 0x6     // DS Hash Understood
+	EDNS0N3U         = 0x7     // NSEC3 Hash Understood
+	EDNS0SUBNET      = 0x8     // client-subnet (RFC6891)
+	EDNS0EXPIRE      = 0x9     // EDNS0 expire
+	EDNS0SUBNETDRAFT = 0x50fa  // Don't use! Use EDNS0SUBNET
+	EDNS0LOCALSTART  = 0xFDE9  // Beginning of range reserved for local/experimental use (RFC6891)
+	EDNS0LOCALEND    = 0xFFFE  // End of range reserved for local/experimental use (RFC6891)
+	_DO              = 1 << 15 // dnssec ok
+)
+
+// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
+// See RFC 6891.
+type OPT struct {
+	Hdr    RR_Header
+	Option []EDNS0 `dns:"opt"`
+}
+
+// Header implements the RR interface.
+func (rr *OPT) Header() *RR_Header {
+	return &rr.Hdr
+}
+
+func (rr *OPT) String() string {
+	s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
+	if rr.Do() {
+		s += "flags: do; "
+	} else {
+		s += "flags: ; "
+	}
+	s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
+
+	for _, o := range rr.Option {
+		switch o.(type) {
+		case *EDNS0_NSID:
+			s += "\n; NSID: " + o.String()
+			h, e := o.pack()
+			var r string
+			if e == nil {
+				for _, c := range h {
+					r += "(" + string(c) + ")"
+				}
+				s += "  " + r
+			}
+		case *EDNS0_SUBNET:
+			s += "\n; SUBNET: " + o.String()
+			if o.(*EDNS0_SUBNET).DraftOption {
+				s += " (draft)"
+			}
+		case *EDNS0_UL:
+			s += "\n; UPDATE LEASE: " + o.String()
+		case *EDNS0_LLQ:
+			s += "\n; LONG LIVED QUERIES: " + o.String()
+		case *EDNS0_DAU:
+			s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String()
+		case *EDNS0_DHU:
+			s += "\n; DS HASH UNDERSTOOD: " + o.String()
+		case *EDNS0_N3U:
+			s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
+		case *EDNS0_LOCAL:
+			s += "\n; LOCAL OPT: " + o.String()
+		}
+	}
+	return s
+}
+
+func (rr *OPT) len() int {
+	l := rr.Hdr.len()
+	for i := 0; i < len(rr.Option); i++ {
+		l += 4 // Account for 2-byte option code and 2-byte option length.
+		lo, _ := rr.Option[i].pack()
+		l += len(lo)
+	}
+	return l
+}
+
+func (rr *OPT) copy() RR {
+	return &OPT{*rr.Hdr.copyHeader(), rr.Option}
+}
+
+// return the old value -> delete SetVersion?
+
+// Version returns the EDNS version used. Only zero is defined.
+func (rr *OPT) Version() uint8 {
+	return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
+}
+
+// SetVersion sets the version of EDNS. This is usually zero.
+func (rr *OPT) SetVersion(v uint8) {
+	rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
+}
+
+// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
+func (rr *OPT) ExtendedRcode() uint8 {
+	return uint8((rr.Hdr.Ttl & 0xFF000000) >> 24)
+}
+
+// SetExtendedRcode sets the EDNS extended RCODE field.
+func (rr *OPT) SetExtendedRcode(v uint8) {
+	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24)
+}
+
+// UDPSize returns the UDP buffer size.
+func (rr *OPT) UDPSize() uint16 {
+	return rr.Hdr.Class
+}
+
+// SetUDPSize sets the UDP buffer size.
+func (rr *OPT) SetUDPSize(size uint16) {
+	rr.Hdr.Class = size
+}
+
+// Do returns the value of the DO (DNSSEC OK) bit.
+func (rr *OPT) Do() bool {
+	return rr.Hdr.Ttl&_DO == _DO
+}
+
+// SetDo sets the DO (DNSSEC OK) bit.
+func (rr *OPT) SetDo() {
+	rr.Hdr.Ttl |= _DO
+}
+
+// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to
+// it.
+type EDNS0 interface {
+	// Option returns the option code for the option.
+	Option() uint16
+	// pack returns the bytes of the option data.
+	pack() ([]byte, error)
+	// unpack sets the data as found in the buffer. Is also sets
+	// the length of the slice as the length of the option data.
+	unpack([]byte) error
+	// String returns the string representation of the option.
+	String() string
+}
+
+// The nsid EDNS0 option is used to retrieve a nameserver
+// identifier. When sending a request Nsid must be set to the empty string
+// The identifier is an opaque string encoded as hex.
+// Basic use pattern for creating an nsid option:
+//
+//	o := new(dns.OPT)
+//	o.Hdr.Name = "."
+//	o.Hdr.Rrtype = dns.TypeOPT
+//	e := new(dns.EDNS0_NSID)
+//	e.Code = dns.EDNS0NSID
+//	e.Nsid = "AA"
+//	o.Option = append(o.Option, e)
+type EDNS0_NSID struct {
+	Code uint16 // Always EDNS0NSID
+	Nsid string // This string needs to be hex encoded
+}
+
+func (e *EDNS0_NSID) pack() ([]byte, error) {
+	h, err := hex.DecodeString(e.Nsid)
+	if err != nil {
+		return nil, err
+	}
+	return h, nil
+}
+
+func (e *EDNS0_NSID) Option() uint16        { return EDNS0NSID }
+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) }
+
+// 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
+// answer depending on the location or network topology.
+// Basic use pattern for creating an subnet option:
+//
+//	o := new(dns.OPT)
+//	o.Hdr.Name = "."
+//	o.Hdr.Rrtype = dns.TypeOPT
+//	e := new(dns.EDNS0_SUBNET)
+//	e.Code = dns.EDNS0SUBNET
+//	e.Family = 1	// 1 for IPv4 source address, 2 for IPv6
+//	e.NetMask = 32	// 32 for IPV4, 128 for IPv6
+//	e.SourceScope = 0
+//	e.Address = net.ParseIP("127.0.0.1").To4()	// for IPv4
+//	// e.Address = net.ParseIP("2001:7b8:32a::2")	// for IPV6
+//	o.Option = append(o.Option, e)
+//
+// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
+// for which netmask applies to the address. This code will parse all the
+// available bits when unpacking (up to optlen). When packing it will apply
+// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
+type EDNS0_SUBNET struct {
+	Code          uint16 // Always EDNS0SUBNET
+	Family        uint16 // 1 for IP, 2 for IP6
+	SourceNetmask uint8
+	SourceScope   uint8
+	Address       net.IP
+	DraftOption   bool // Set to true if using the old (0x50fa) option code
+}
+
+func (e *EDNS0_SUBNET) Option() uint16 {
+	if e.DraftOption {
+		return EDNS0SUBNETDRAFT
+	}
+	return EDNS0SUBNET
+}
+
+func (e *EDNS0_SUBNET) pack() ([]byte, error) {
+	b := make([]byte, 4)
+	b[0], b[1] = packUint16(e.Family)
+	b[2] = e.SourceNetmask
+	b[3] = e.SourceScope
+	switch e.Family {
+	case 1:
+		if e.SourceNetmask > net.IPv4len*8 {
+			return nil, errors.New("dns: bad netmask")
+		}
+		if len(e.Address.To4()) != net.IPv4len {
+			return nil, errors.New("dns: bad address")
+		}
+		ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
+		needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
+		b = append(b, ip[:needLength]...)
+	case 2:
+		if e.SourceNetmask > net.IPv6len*8 {
+			return nil, errors.New("dns: bad netmask")
+		}
+		if len(e.Address) != net.IPv6len {
+			return nil, errors.New("dns: bad address")
+		}
+		ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
+		needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
+		b = append(b, ip[:needLength]...)
+	default:
+		return nil, errors.New("dns: bad address family")
+	}
+	return b, nil
+}
+
+func (e *EDNS0_SUBNET) unpack(b []byte) error {
+	if len(b) < 4 {
+		return ErrBuf
+	}
+	e.Family, _ = unpackUint16(b, 0)
+	e.SourceNetmask = b[2]
+	e.SourceScope = b[3]
+	switch e.Family {
+	case 1:
+		if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
+			return errors.New("dns: bad netmask")
+		}
+		addr := make([]byte, net.IPv4len)
+		for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
+			addr[i] = b[4+i]
+		}
+		e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
+	case 2:
+		if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
+			return errors.New("dns: bad netmask")
+		}
+		addr := make([]byte, net.IPv6len)
+		for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
+			addr[i] = b[4+i]
+		}
+		e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
+			addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
+			addr[11], addr[12], addr[13], addr[14], addr[15]}
+	default:
+		return errors.New("dns: bad address family")
+	}
+	return nil
+}
+
+func (e *EDNS0_SUBNET) String() (s string) {
+	if e.Address == nil {
+		s = "<nil>"
+	} else if e.Address.To4() != nil {
+		s = e.Address.String()
+	} else {
+		s = "[" + e.Address.String() + "]"
+	}
+	s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope))
+	return
+}
+
+// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
+// an expiration on an update RR. This is helpful for clients that cannot clean
+// up after themselves. This is a draft RFC and more information can be found at
+// http://files.dns-sd.org/draft-sekar-dns-ul.txt
+//
+//	o := new(dns.OPT)
+//	o.Hdr.Name = "."
+//	o.Hdr.Rrtype = dns.TypeOPT
+//	e := new(dns.EDNS0_UL)
+//	e.Code = dns.EDNS0UL
+//	e.Lease = 120 // in seconds
+//	o.Option = append(o.Option, e)
+type EDNS0_UL struct {
+	Code  uint16 // Always EDNS0UL
+	Lease uint32
+}
+
+func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
+func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
+
+// Copied: http://golang.org/src/pkg/net/dnsmsg.go
+func (e *EDNS0_UL) pack() ([]byte, error) {
+	b := make([]byte, 4)
+	b[0] = byte(e.Lease >> 24)
+	b[1] = byte(e.Lease >> 16)
+	b[2] = byte(e.Lease >> 8)
+	b[3] = byte(e.Lease)
+	return b, nil
+}
+
+func (e *EDNS0_UL) unpack(b []byte) error {
+	if len(b) < 4 {
+		return ErrBuf
+	}
+	e.Lease = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
+	return nil
+}
+
+// EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
+// Implemented for completeness, as the EDNS0 type code is assigned.
+type EDNS0_LLQ struct {
+	Code      uint16 // Always EDNS0LLQ
+	Version   uint16
+	Opcode    uint16
+	Error     uint16
+	Id        uint64
+	LeaseLife uint32
+}
+
+func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
+
+func (e *EDNS0_LLQ) pack() ([]byte, error) {
+	b := make([]byte, 18)
+	b[0], b[1] = packUint16(e.Version)
+	b[2], b[3] = packUint16(e.Opcode)
+	b[4], b[5] = packUint16(e.Error)
+	b[6] = byte(e.Id >> 56)
+	b[7] = byte(e.Id >> 48)
+	b[8] = byte(e.Id >> 40)
+	b[9] = byte(e.Id >> 32)
+	b[10] = byte(e.Id >> 24)
+	b[11] = byte(e.Id >> 16)
+	b[12] = byte(e.Id >> 8)
+	b[13] = byte(e.Id)
+	b[14] = byte(e.LeaseLife >> 24)
+	b[15] = byte(e.LeaseLife >> 16)
+	b[16] = byte(e.LeaseLife >> 8)
+	b[17] = byte(e.LeaseLife)
+	return b, nil
+}
+
+func (e *EDNS0_LLQ) unpack(b []byte) error {
+	if len(b) < 18 {
+		return ErrBuf
+	}
+	e.Version, _ = unpackUint16(b, 0)
+	e.Opcode, _ = unpackUint16(b, 2)
+	e.Error, _ = unpackUint16(b, 4)
+	e.Id = uint64(b[6])<<56 | uint64(b[6+1])<<48 | uint64(b[6+2])<<40 |
+		uint64(b[6+3])<<32 | uint64(b[6+4])<<24 | uint64(b[6+5])<<16 | uint64(b[6+6])<<8 | uint64(b[6+7])
+	e.LeaseLife = uint32(b[14])<<24 | uint32(b[14+1])<<16 | uint32(b[14+2])<<8 | uint32(b[14+3])
+	return nil
+}
+
+func (e *EDNS0_LLQ) String() string {
+	s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
+		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
+		" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
+	return s
+}
+
+type EDNS0_DAU struct {
+	Code    uint16 // Always EDNS0DAU
+	AlgCode []uint8
+}
+
+func (e *EDNS0_DAU) Option() uint16        { return EDNS0DAU }
+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) String() string {
+	s := ""
+	for i := 0; i < len(e.AlgCode); i++ {
+		if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
+			s += " " + a
+		} else {
+			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+		}
+	}
+	return s
+}
+
+type EDNS0_DHU struct {
+	Code    uint16 // Always EDNS0DHU
+	AlgCode []uint8
+}
+
+func (e *EDNS0_DHU) Option() uint16        { return EDNS0DHU }
+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) String() string {
+	s := ""
+	for i := 0; i < len(e.AlgCode); i++ {
+		if a, ok := HashToString[e.AlgCode[i]]; ok {
+			s += " " + a
+		} else {
+			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+		}
+	}
+	return s
+}
+
+type EDNS0_N3U struct {
+	Code    uint16 // Always EDNS0N3U
+	AlgCode []uint8
+}
+
+func (e *EDNS0_N3U) Option() uint16        { return EDNS0N3U }
+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) String() string {
+	// Re-use the hash map
+	s := ""
+	for i := 0; i < len(e.AlgCode); i++ {
+		if a, ok := HashToString[e.AlgCode[i]]; ok {
+			s += " " + a
+		} else {
+			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+		}
+	}
+	return s
+}
+
+type EDNS0_EXPIRE struct {
+	Code   uint16 // Always EDNS0EXPIRE
+	Expire uint32
+}
+
+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) pack() ([]byte, error) {
+	b := make([]byte, 4)
+	b[0] = byte(e.Expire >> 24)
+	b[1] = byte(e.Expire >> 16)
+	b[2] = byte(e.Expire >> 8)
+	b[3] = byte(e.Expire)
+	return b, nil
+}
+
+func (e *EDNS0_EXPIRE) unpack(b []byte) error {
+	if len(b) < 4 {
+		return ErrBuf
+	}
+	e.Expire = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
+	return nil
+}
+
+// The EDNS0_LOCAL option is used for local/experimental purposes. The option
+// code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
+// (RFC6891), although any unassigned code can actually be used.  The content of
+// the option is made available in Data, unaltered.
+// Basic use pattern for creating a local option:
+//
+//	o := new(dns.OPT)
+//	o.Hdr.Name = "."
+//	o.Hdr.Rrtype = dns.TypeOPT
+//	e := new(dns.EDNS0_LOCAL)
+//	e.Code = dns.EDNS0LOCALSTART
+//	e.Data = []byte{72, 82, 74}
+//	o.Option = append(o.Option, e)
+type EDNS0_LOCAL struct {
+	Code uint16
+	Data []byte
+}
+
+func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
+func (e *EDNS0_LOCAL) String() string {
+	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
+}
+
+func (e *EDNS0_LOCAL) pack() ([]byte, error) {
+	b := make([]byte, len(e.Data))
+	copied := copy(b, e.Data)
+	if copied != len(e.Data) {
+		return nil, ErrBuf
+	}
+	return b, nil
+}
+
+func (e *EDNS0_LOCAL) unpack(b []byte) error {
+	e.Data = make([]byte, len(b))
+	copied := copy(e.Data, b)
+	if copied != len(b) {
+		return ErrBuf
+	}
+	return nil
+}
diff --git a/vendor/github.com/miekg/dns/format.go b/vendor/github.com/miekg/dns/format.go
new file mode 100644
index 0000000000000000000000000000000000000000..1ac1664fe29fa1b71a83d53b2be92b9e274f71e7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/format.go
@@ -0,0 +1,96 @@
+package dns
+
+import (
+	"net"
+	"reflect"
+	"strconv"
+)
+
+// NumField returns the number of rdata fields r has.
+func NumField(r RR) int {
+	return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header
+}
+
+// Field returns the rdata field i as a string. Fields are indexed starting from 1.
+// RR types that holds slice data, for instance the NSEC type bitmap will return a single
+// string where the types are concatenated using a space.
+// Accessing non existing fields will cause a panic.
+func Field(r RR, i int) string {
+	if i == 0 {
+		return ""
+	}
+	d := reflect.ValueOf(r).Elem().Field(i)
+	switch k := d.Kind(); k {
+	case reflect.String:
+		return d.String()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return strconv.FormatInt(d.Int(), 10)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return strconv.FormatUint(d.Uint(), 10)
+	case reflect.Slice:
+		switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
+		case `dns:"a"`:
+			// TODO(miek): Hmm store this as 16 bytes
+			if d.Len() < net.IPv6len {
+				return net.IPv4(byte(d.Index(0).Uint()),
+					byte(d.Index(1).Uint()),
+					byte(d.Index(2).Uint()),
+					byte(d.Index(3).Uint())).String()
+			}
+			return net.IPv4(byte(d.Index(12).Uint()),
+				byte(d.Index(13).Uint()),
+				byte(d.Index(14).Uint()),
+				byte(d.Index(15).Uint())).String()
+		case `dns:"aaaa"`:
+			return net.IP{
+				byte(d.Index(0).Uint()),
+				byte(d.Index(1).Uint()),
+				byte(d.Index(2).Uint()),
+				byte(d.Index(3).Uint()),
+				byte(d.Index(4).Uint()),
+				byte(d.Index(5).Uint()),
+				byte(d.Index(6).Uint()),
+				byte(d.Index(7).Uint()),
+				byte(d.Index(8).Uint()),
+				byte(d.Index(9).Uint()),
+				byte(d.Index(10).Uint()),
+				byte(d.Index(11).Uint()),
+				byte(d.Index(12).Uint()),
+				byte(d.Index(13).Uint()),
+				byte(d.Index(14).Uint()),
+				byte(d.Index(15).Uint()),
+			}.String()
+		case `dns:"nsec"`:
+			if d.Len() == 0 {
+				return ""
+			}
+			s := Type(d.Index(0).Uint()).String()
+			for i := 1; i < d.Len(); i++ {
+				s += " " + Type(d.Index(i).Uint()).String()
+			}
+			return s
+		case `dns:"wks"`:
+			if d.Len() == 0 {
+				return ""
+			}
+			s := strconv.Itoa(int(d.Index(0).Uint()))
+			for i := 0; i < d.Len(); i++ {
+				s += " " + strconv.Itoa(int(d.Index(i).Uint()))
+			}
+			return s
+		default:
+			// if it does not have a tag its a string slice
+			fallthrough
+		case `dns:"txt"`:
+			if d.Len() == 0 {
+				return ""
+			}
+			s := d.Index(0).String()
+			for i := 1; i < d.Len(); i++ {
+				s += " " + d.Index(i).String()
+			}
+			return s
+		}
+	}
+	return ""
+}
diff --git a/vendor/github.com/miekg/dns/labels.go b/vendor/github.com/miekg/dns/labels.go
new file mode 100644
index 0000000000000000000000000000000000000000..3944dd0632ffaf6a4117cd49696df1124861eedb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/labels.go
@@ -0,0 +1,162 @@
+package dns
+
+// Holds a bunch of helper functions for dealing with labels.
+
+// SplitDomainName splits a name string into it's labels.
+// www.miek.nl. returns []string{"www", "miek", "nl"}
+// The root label (.) returns nil. Note that using
+// strings.Split(s) will work in most cases, but does not handle
+// escaped dots (\.) for instance.
+func SplitDomainName(s string) (labels []string) {
+	if len(s) == 0 {
+		return nil
+	}
+	fqdnEnd := 0 // offset of the final '.' or the length of the name
+	idx := Split(s)
+	begin := 0
+	if s[len(s)-1] == '.' {
+		fqdnEnd = len(s) - 1
+	} else {
+		fqdnEnd = len(s)
+	}
+
+	switch len(idx) {
+	case 0:
+		return nil
+	case 1:
+		// no-op
+	default:
+		end := 0
+		for i := 1; i < len(idx); i++ {
+			end = idx[i]
+			labels = append(labels, s[begin:end-1])
+			begin = end
+		}
+	}
+
+	labels = append(labels, s[begin:fqdnEnd])
+	return labels
+}
+
+// CompareDomainName compares the names s1 and s2 and
+// returns how many labels they have in common starting from the *right*.
+// The comparison stops at the first inequality. The names are not downcased
+// before the comparison.
+//
+// www.miek.nl. and miek.nl. have two labels in common: miek and nl
+// www.miek.nl. and www.bla.nl. have one label in common: nl
+func CompareDomainName(s1, s2 string) (n int) {
+	s1 = Fqdn(s1)
+	s2 = Fqdn(s2)
+	l1 := Split(s1)
+	l2 := Split(s2)
+
+	// the first check: root label
+	if l1 == nil || l2 == nil {
+		return
+	}
+
+	j1 := len(l1) - 1 // end
+	i1 := len(l1) - 2 // start
+	j2 := len(l2) - 1
+	i2 := len(l2) - 2
+	// the second check can be done here: last/only label
+	// before we fall through into the for-loop below
+	if s1[l1[j1]:] == s2[l2[j2]:] {
+		n++
+	} else {
+		return
+	}
+	for {
+		if i1 < 0 || i2 < 0 {
+			break
+		}
+		if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
+			n++
+		} else {
+			break
+		}
+		j1--
+		i1--
+		j2--
+		i2--
+	}
+	return
+}
+
+// CountLabel counts the the number of labels in the string s.
+func CountLabel(s string) (labels int) {
+	if s == "." {
+		return
+	}
+	off := 0
+	end := false
+	for {
+		off, end = NextLabel(s, off)
+		labels++
+		if end {
+			return
+		}
+	}
+}
+
+// Split splits a name s into its label indexes.
+// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
+// The root name (.) returns nil. Also see SplitDomainName.
+func Split(s string) []int {
+	if s == "." {
+		return nil
+	}
+	idx := make([]int, 1, 3)
+	off := 0
+	end := false
+
+	for {
+		off, end = NextLabel(s, off)
+		if end {
+			return idx
+		}
+		idx = append(idx, off)
+	}
+}
+
+// NextLabel returns the index of the start of the next label in the
+// string s starting at offset.
+// The bool end is true when the end of the string has been reached.
+// Also see PrevLabel.
+func NextLabel(s string, offset int) (i int, end bool) {
+	quote := false
+	for i = offset; i < len(s)-1; i++ {
+		switch s[i] {
+		case '\\':
+			quote = !quote
+		default:
+			quote = false
+		case '.':
+			if quote {
+				quote = !quote
+				continue
+			}
+			return i + 1, false
+		}
+	}
+	return i + 1, true
+}
+
+// PrevLabel returns the index of the label when starting from the right and
+// jumping n labels to the left.
+// The bool start is true when the start of the string has been overshot.
+// Also see NextLabel.
+func PrevLabel(s string, n int) (i int, start bool) {
+	if n == 0 {
+		return len(s), false
+	}
+	lab := Split(s)
+	if lab == nil {
+		return 0, true
+	}
+	if n > len(lab) {
+		return 0, true
+	}
+	return lab[len(lab)-n], false
+}
diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go
new file mode 100644
index 0000000000000000000000000000000000000000..3d13135c69000e59fbf1bb257bebe10a4e746bf6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/msg.go
@@ -0,0 +1,2030 @@
+// DNS packet assembly, see RFC 1035. Converting from - Unpack() -
+// and to - Pack() - wire format.
+// All the packers and unpackers take a (msg []byte, off int)
+// and return (off1 int, ok bool).  If they return ok==false, they
+// also return off1==len(msg), so that the next unpacker will
+// also fail.  This lets us avoid checks of ok until the end of a
+// packing sequence.
+
+package dns
+
+import (
+	"encoding/base32"
+	"encoding/base64"
+	"encoding/hex"
+	"math/big"
+	"math/rand"
+	"net"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
+
+var (
+	// ErrAlg indicates an error with the (DNSSEC) algorithm.
+	ErrAlg error = &Error{err: "bad algorithm"}
+	// ErrAuth indicates an error in the TSIG authentication.
+	ErrAuth error = &Error{err: "bad authentication"}
+	// ErrBuf indicates that the buffer used it too small for the message.
+	ErrBuf error = &Error{err: "buffer size too small"}
+	// ErrConnEmpty indicates a connection is being uses before it is initialized.
+	ErrConnEmpty error = &Error{err: "conn has no connection"}
+	// ErrExtendedRcode ...
+	ErrExtendedRcode error = &Error{err: "bad extended rcode"}
+	// ErrFqdn indicates that a domain name does not have a closing dot.
+	ErrFqdn error = &Error{err: "domain must be fully qualified"}
+	// ErrId indicates there is a mismatch with the message's ID.
+	ErrId error = &Error{err: "id mismatch"}
+	// ErrKeyAlg indicates that the algorithm in the key is not valid.
+	ErrKeyAlg    error = &Error{err: "bad key algorithm"}
+	ErrKey       error = &Error{err: "bad key"}
+	ErrKeySize   error = &Error{err: "bad key size"}
+	ErrNoSig     error = &Error{err: "no signature found"}
+	ErrPrivKey   error = &Error{err: "bad private key"}
+	ErrRcode     error = &Error{err: "bad rcode"}
+	ErrRdata     error = &Error{err: "bad rdata"}
+	ErrRRset     error = &Error{err: "bad rrset"}
+	ErrSecret    error = &Error{err: "no secrets defined"}
+	ErrShortRead error = &Error{err: "short read"}
+	// ErrSig indicates that a signature can not be cryptographically validated.
+	ErrSig error = &Error{err: "bad signature"}
+	// ErrSOA indicates that no SOA RR was seen when doing zone transfers.
+	ErrSoa error = &Error{err: "no SOA"}
+	// ErrTime indicates a timing error in TSIG authentication.
+	ErrTime error = &Error{err: "bad time"}
+)
+
+// Id, by default, returns a 16 bits random number to be used as a
+// message id. The random provided should be good enough. This being a
+// variable the function can be reassigned to a custom function.
+// For instance, to make it return a static value:
+//
+//	dns.Id = func() uint16 { return 3 }
+var Id func() uint16 = id
+
+// MsgHdr is a a manually-unpacked version of (id, bits).
+type MsgHdr struct {
+	Id                 uint16
+	Response           bool
+	Opcode             int
+	Authoritative      bool
+	Truncated          bool
+	RecursionDesired   bool
+	RecursionAvailable bool
+	Zero               bool
+	AuthenticatedData  bool
+	CheckingDisabled   bool
+	Rcode              int
+}
+
+// Msg contains the layout of a DNS message.
+type Msg struct {
+	MsgHdr
+	Compress bool       `json:"-"` // If true, the message will be compressed when converted to wire format. This not part of the official DNS packet format.
+	Question []Question // Holds the RR(s) of the question section.
+	Answer   []RR       // Holds the RR(s) of the answer section.
+	Ns       []RR       // Holds the RR(s) of the authority section.
+	Extra    []RR       // Holds the RR(s) of the additional section.
+}
+
+// TypeToString is a map of strings for each RR wire type.
+var TypeToString = map[uint16]string{
+	TypeA:          "A",
+	TypeAAAA:       "AAAA",
+	TypeAFSDB:      "AFSDB",
+	TypeANY:        "ANY", // Meta RR
+	TypeATMA:       "ATMA",
+	TypeAXFR:       "AXFR", // Meta RR
+	TypeCAA:        "CAA",
+	TypeCDNSKEY:    "CDNSKEY",
+	TypeCDS:        "CDS",
+	TypeCERT:       "CERT",
+	TypeCNAME:      "CNAME",
+	TypeDHCID:      "DHCID",
+	TypeDLV:        "DLV",
+	TypeDNAME:      "DNAME",
+	TypeDNSKEY:     "DNSKEY",
+	TypeDS:         "DS",
+	TypeEID:        "EID",
+	TypeEUI48:      "EUI48",
+	TypeEUI64:      "EUI64",
+	TypeGID:        "GID",
+	TypeGPOS:       "GPOS",
+	TypeHINFO:      "HINFO",
+	TypeHIP:        "HIP",
+	TypeIPSECKEY:   "IPSECKEY",
+	TypeISDN:       "ISDN",
+	TypeIXFR:       "IXFR", // Meta RR
+	TypeKEY:        "KEY",
+	TypeKX:         "KX",
+	TypeL32:        "L32",
+	TypeL64:        "L64",
+	TypeLOC:        "LOC",
+	TypeLP:         "LP",
+	TypeMB:         "MB",
+	TypeMD:         "MD",
+	TypeMF:         "MF",
+	TypeMG:         "MG",
+	TypeMINFO:      "MINFO",
+	TypeMR:         "MR",
+	TypeMX:         "MX",
+	TypeNAPTR:      "NAPTR",
+	TypeNID:        "NID",
+	TypeNINFO:      "NINFO",
+	TypeNIMLOC:     "NIMLOC",
+	TypeNS:         "NS",
+	TypeNSAPPTR:    "NSAP-PTR",
+	TypeNSEC3:      "NSEC3",
+	TypeNSEC3PARAM: "NSEC3PARAM",
+	TypeNSEC:       "NSEC",
+	TypeNULL:       "NULL",
+	TypeOPT:        "OPT",
+	TypeOPENPGPKEY: "OPENPGPKEY",
+	TypePTR:        "PTR",
+	TypeRKEY:       "RKEY",
+	TypeRP:         "RP",
+	TypeRRSIG:      "RRSIG",
+	TypeRT:         "RT",
+	TypeSIG:        "SIG",
+	TypeSOA:        "SOA",
+	TypeSPF:        "SPF",
+	TypeSRV:        "SRV",
+	TypeSSHFP:      "SSHFP",
+	TypeTA:         "TA",
+	TypeTALINK:     "TALINK",
+	TypeTKEY:       "TKEY", // Meta RR
+	TypeTLSA:       "TLSA",
+	TypeTSIG:       "TSIG", // Meta RR
+	TypeTXT:        "TXT",
+	TypePX:         "PX",
+	TypeUID:        "UID",
+	TypeUINFO:      "UINFO",
+	TypeUNSPEC:     "UNSPEC",
+	TypeURI:        "URI",
+	TypeWKS:        "WKS",
+	TypeX25:        "X25",
+}
+
+// StringToType is the reverse of TypeToString, needed for string parsing.
+var StringToType = reverseInt16(TypeToString)
+
+// StringToClass is the reverse of ClassToString, needed for string parsing.
+var StringToClass = reverseInt16(ClassToString)
+
+// Map of opcodes strings.
+var StringToOpcode = reverseInt(OpcodeToString)
+
+// Map of rcodes strings.
+var StringToRcode = reverseInt(RcodeToString)
+
+// ClassToString is a maps Classes to strings for each CLASS wire type.
+var ClassToString = map[uint16]string{
+	ClassINET:   "IN",
+	ClassCSNET:  "CS",
+	ClassCHAOS:  "CH",
+	ClassHESIOD: "HS",
+	ClassNONE:   "NONE",
+	ClassANY:    "ANY",
+}
+
+// OpcodeToString maps Opcodes to strings.
+var OpcodeToString = map[int]string{
+	OpcodeQuery:  "QUERY",
+	OpcodeIQuery: "IQUERY",
+	OpcodeStatus: "STATUS",
+	OpcodeNotify: "NOTIFY",
+	OpcodeUpdate: "UPDATE",
+}
+
+// RcodeToString maps Rcodes to strings.
+var RcodeToString = map[int]string{
+	RcodeSuccess:        "NOERROR",
+	RcodeFormatError:    "FORMERR",
+	RcodeServerFailure:  "SERVFAIL",
+	RcodeNameError:      "NXDOMAIN",
+	RcodeNotImplemented: "NOTIMPL",
+	RcodeRefused:        "REFUSED",
+	RcodeYXDomain:       "YXDOMAIN", // From RFC 2136
+	RcodeYXRrset:        "YXRRSET",
+	RcodeNXRrset:        "NXRRSET",
+	RcodeNotAuth:        "NOTAUTH",
+	RcodeNotZone:        "NOTZONE",
+	RcodeBadSig:         "BADSIG", // Also known as RcodeBadVers, see RFC 6891
+	//	RcodeBadVers:        "BADVERS",
+	RcodeBadKey:   "BADKEY",
+	RcodeBadTime:  "BADTIME",
+	RcodeBadMode:  "BADMODE",
+	RcodeBadName:  "BADNAME",
+	RcodeBadAlg:   "BADALG",
+	RcodeBadTrunc: "BADTRUNC",
+}
+
+// Rather than write the usual handful of routines to pack and
+// unpack every message that can appear on the wire, we use
+// reflection to write a generic pack/unpack for structs and then
+// use it. Thus, if in the future we need to define new message
+// structs, no new pack/unpack/printing code needs to be written.
+
+// Domain names are a sequence of counted strings
+// split at the dots. They end with a zero-length string.
+
+// PackDomainName packs a domain name s into msg[off:].
+// If compression is wanted compress must be true and the compression
+// map needs to hold a mapping between domain names and offsets
+// pointing into msg.
+func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+	off1, _, err = packDomainName(s, msg, off, compression, compress)
+	return
+}
+
+func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) {
+	// special case if msg == nil
+	lenmsg := 256
+	if msg != nil {
+		lenmsg = len(msg)
+	}
+	ls := len(s)
+	if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
+		return off, 0, nil
+	}
+	// If not fully qualified, error out, but only if msg == nil #ugly
+	switch {
+	case msg == nil:
+		if s[ls-1] != '.' {
+			s += "."
+			ls++
+		}
+	case msg != nil:
+		if s[ls-1] != '.' {
+			return lenmsg, 0, ErrFqdn
+		}
+	}
+	// Each dot ends a segment of the name.
+	// We trade each dot byte for a length byte.
+	// Except for escaped dots (\.), which are normal dots.
+	// There is also a trailing zero.
+
+	// Compression
+	nameoffset := -1
+	pointer := -1
+	// Emit sequence of counted strings, chopping at dots.
+	begin := 0
+	bs := []byte(s)
+	roBs, bsFresh, escapedDot := s, true, false
+	for i := 0; i < ls; i++ {
+		if bs[i] == '\\' {
+			for j := i; j < ls-1; j++ {
+				bs[j] = bs[j+1]
+			}
+			ls--
+			if off+1 > lenmsg {
+				return lenmsg, labels, ErrBuf
+			}
+			// check for \DDD
+			if i+2 < ls && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+				bs[i] = dddToByte(bs[i:])
+				for j := i + 1; j < ls-2; j++ {
+					bs[j] = bs[j+2]
+				}
+				ls -= 2
+			} else if bs[i] == 't' {
+				bs[i] = '\t'
+			} else if bs[i] == 'r' {
+				bs[i] = '\r'
+			} else if bs[i] == 'n' {
+				bs[i] = '\n'
+			}
+			escapedDot = bs[i] == '.'
+			bsFresh = false
+			continue
+		}
+
+		if bs[i] == '.' {
+			if i > 0 && bs[i-1] == '.' && !escapedDot {
+				// two dots back to back is not legal
+				return lenmsg, labels, ErrRdata
+			}
+			if i-begin >= 1<<6 { // top two bits of length must be clear
+				return lenmsg, labels, ErrRdata
+			}
+			// off can already (we're in a loop) be bigger than len(msg)
+			// this happens when a name isn't fully qualified
+			if off+1 > lenmsg {
+				return lenmsg, labels, ErrBuf
+			}
+			if msg != nil {
+				msg[off] = byte(i - begin)
+			}
+			offset := off
+			off++
+			for j := begin; j < i; j++ {
+				if off+1 > lenmsg {
+					return lenmsg, labels, ErrBuf
+				}
+				if msg != nil {
+					msg[off] = bs[j]
+				}
+				off++
+			}
+			if compress && !bsFresh {
+				roBs = string(bs)
+				bsFresh = true
+			}
+			// Dont try to compress '.'
+			if compress && roBs[begin:] != "." {
+				if p, ok := compression[roBs[begin:]]; !ok {
+					// Only offsets smaller than this can be used.
+					if offset < maxCompressionOffset {
+						compression[roBs[begin:]] = offset
+					}
+				} else {
+					// The first hit is the longest matching dname
+					// keep the pointer offset we get back and store
+					// the offset of the current name, because that's
+					// where we need to insert the pointer later
+
+					// If compress is true, we're allowed to compress this dname
+					if pointer == -1 && compress {
+						pointer = p         // Where to point to
+						nameoffset = offset // Where to point from
+						break
+					}
+				}
+			}
+			labels++
+			begin = i + 1
+		}
+		escapedDot = false
+	}
+	// Root label is special
+	if len(bs) == 1 && bs[0] == '.' {
+		return off, labels, nil
+	}
+	// If we did compression and we find something add the pointer here
+	if pointer != -1 {
+		// We have two bytes (14 bits) to put the pointer in
+		// if msg == nil, we will never do compression
+		msg[nameoffset], msg[nameoffset+1] = packUint16(uint16(pointer ^ 0xC000))
+		off = nameoffset + 1
+		goto End
+	}
+	if msg != nil {
+		msg[off] = 0
+	}
+End:
+	off++
+	return off, labels, nil
+}
+
+// Unpack a domain name.
+// In addition to the simple sequences of counted strings above,
+// domain names are allowed to refer to strings elsewhere in the
+// packet, to avoid repeating common suffixes when returning
+// many entries in a single domain.  The pointers are marked
+// by a length byte with the top two bits set.  Ignoring those
+// two bits, that byte and the next give a 14 bit offset from msg[0]
+// where we should pick up the trail.
+// Note that if we jump elsewhere in the packet,
+// we return off1 == the offset after the first pointer we found,
+// which is where the next record will start.
+// In theory, the pointers are only allowed to jump backward.
+// We let them jump anywhere and stop jumping after a while.
+
+// UnpackDomainName unpacks a domain name into a string.
+func UnpackDomainName(msg []byte, off int) (string, int, error) {
+	s := make([]byte, 0, 64)
+	off1 := 0
+	lenmsg := len(msg)
+	ptr := 0 // number of pointers followed
+Loop:
+	for {
+		if off >= lenmsg {
+			return "", lenmsg, ErrBuf
+		}
+		c := int(msg[off])
+		off++
+		switch c & 0xC0 {
+		case 0x00:
+			if c == 0x00 {
+				// end of name
+				break Loop
+			}
+			// literal string
+			if off+c > lenmsg {
+				return "", lenmsg, ErrBuf
+			}
+			for j := off; j < off+c; j++ {
+				switch b := msg[j]; b {
+				case '.', '(', ')', ';', ' ', '@':
+					fallthrough
+				case '"', '\\':
+					s = append(s, '\\', b)
+				case '\t':
+					s = append(s, '\\', 't')
+				case '\r':
+					s = append(s, '\\', 'r')
+				default:
+					if b < 32 || b >= 127 { // unprintable use \DDD
+						var buf [3]byte
+						bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+						s = append(s, '\\')
+						for i := 0; i < 3-len(bufs); i++ {
+							s = append(s, '0')
+						}
+						for _, r := range bufs {
+							s = append(s, r)
+						}
+					} else {
+						s = append(s, b)
+					}
+				}
+			}
+			s = append(s, '.')
+			off += c
+		case 0xC0:
+			// pointer to somewhere else in msg.
+			// remember location after first ptr,
+			// since that's how many bytes we consumed.
+			// also, don't follow too many pointers --
+			// maybe there's a loop.
+			if off >= lenmsg {
+				return "", lenmsg, ErrBuf
+			}
+			c1 := msg[off]
+			off++
+			if ptr == 0 {
+				off1 = off
+			}
+			if ptr++; ptr > 10 {
+				return "", lenmsg, &Error{err: "too many compression pointers"}
+			}
+			off = (c^0xC0)<<8 | int(c1)
+		default:
+			// 0x80 and 0x40 are reserved
+			return "", lenmsg, ErrRdata
+		}
+	}
+	if ptr == 0 {
+		off1 = off
+	}
+	if len(s) == 0 {
+		s = []byte(".")
+	}
+	return string(s), off1, nil
+}
+
+func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
+	var err error
+	if len(txt) == 0 {
+		if offset >= len(msg) {
+			return offset, ErrBuf
+		}
+		msg[offset] = 0
+		return offset, nil
+	}
+	for i := range txt {
+		if len(txt[i]) > len(tmp) {
+			return offset, ErrBuf
+		}
+		offset, err = packTxtString(txt[i], msg, offset, tmp)
+		if err != nil {
+			return offset, err
+		}
+	}
+	return offset, err
+}
+
+func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
+	lenByteOffset := offset
+	if offset >= len(msg) {
+		return offset, ErrBuf
+	}
+	offset++
+	bs := tmp[:len(s)]
+	copy(bs, s)
+	for i := 0; i < len(bs); i++ {
+		if len(msg) <= offset {
+			return offset, ErrBuf
+		}
+		if bs[i] == '\\' {
+			i++
+			if i == len(bs) {
+				break
+			}
+			// check for \DDD
+			if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+				msg[offset] = dddToByte(bs[i:])
+				i += 2
+			} else if bs[i] == 't' {
+				msg[offset] = '\t'
+			} else if bs[i] == 'r' {
+				msg[offset] = '\r'
+			} else if bs[i] == 'n' {
+				msg[offset] = '\n'
+			} else {
+				msg[offset] = bs[i]
+			}
+		} else {
+			msg[offset] = bs[i]
+		}
+		offset++
+	}
+	l := offset - lenByteOffset - 1
+	if l > 255 {
+		return offset, &Error{err: "string exceeded 255 bytes in txt"}
+	}
+	msg[lenByteOffset] = byte(l)
+	return offset, nil
+}
+
+func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
+	if offset >= len(msg) {
+		return offset, ErrBuf
+	}
+	bs := tmp[:len(s)]
+	copy(bs, s)
+	for i := 0; i < len(bs); i++ {
+		if len(msg) <= offset {
+			return offset, ErrBuf
+		}
+		if bs[i] == '\\' {
+			i++
+			if i == len(bs) {
+				break
+			}
+			// check for \DDD
+			if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+				msg[offset] = dddToByte(bs[i:])
+				i += 2
+			} else {
+				msg[offset] = bs[i]
+			}
+		} else {
+			msg[offset] = bs[i]
+		}
+		offset++
+	}
+	return offset, nil
+}
+
+func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
+	off = off0
+	var s string
+	for off < len(msg) && err == nil {
+		s, off, err = unpackTxtString(msg, off)
+		if err == nil {
+			ss = append(ss, s)
+		}
+	}
+	return
+}
+
+func unpackTxtString(msg []byte, offset int) (string, int, error) {
+	if offset+1 > len(msg) {
+		return "", offset, &Error{err: "overflow unpacking txt"}
+	}
+	l := int(msg[offset])
+	if offset+l+1 > len(msg) {
+		return "", offset, &Error{err: "overflow unpacking txt"}
+	}
+	s := make([]byte, 0, l)
+	for _, b := range msg[offset+1 : offset+1+l] {
+		switch b {
+		case '"', '\\':
+			s = append(s, '\\', b)
+		case '\t':
+			s = append(s, `\t`...)
+		case '\r':
+			s = append(s, `\r`...)
+		case '\n':
+			s = append(s, `\n`...)
+		default:
+			if b < 32 || b > 127 { // unprintable
+				var buf [3]byte
+				bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+				s = append(s, '\\')
+				for i := 0; i < 3-len(bufs); i++ {
+					s = append(s, '0')
+				}
+				for _, r := range bufs {
+					s = append(s, r)
+				}
+			} else {
+				s = append(s, b)
+			}
+		}
+	}
+	offset += 1 + l
+	return string(s), offset, nil
+}
+
+// Pack a reflect.StructValue into msg.  Struct members can only be uint8, uint16, uint32, string,
+// slices and other (often anonymous) structs.
+func packStructValue(val reflect.Value, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+	var txtTmp []byte
+	lenmsg := len(msg)
+	numfield := val.NumField()
+	for i := 0; i < numfield; i++ {
+		typefield := val.Type().Field(i)
+		if typefield.Tag == `dns:"-"` {
+			continue
+		}
+		switch fv := val.Field(i); fv.Kind() {
+		default:
+			return lenmsg, &Error{err: "bad kind packing"}
+		case reflect.Interface:
+			// PrivateRR is the only RR implementation that has interface field.
+			// therefore it's expected that this interface would be PrivateRdata
+			switch data := fv.Interface().(type) {
+			case PrivateRdata:
+				n, err := data.Pack(msg[off:])
+				if err != nil {
+					return lenmsg, err
+				}
+				off += n
+			default:
+				return lenmsg, &Error{err: "bad kind interface packing"}
+			}
+		case reflect.Slice:
+			switch typefield.Tag {
+			default:
+				return lenmsg, &Error{"bad tag packing slice: " + typefield.Tag.Get("dns")}
+			case `dns:"domain-name"`:
+				for j := 0; j < val.Field(i).Len(); j++ {
+					element := val.Field(i).Index(j).String()
+					off, err = PackDomainName(element, msg, off, compression, false && compress)
+					if err != nil {
+						return lenmsg, err
+					}
+				}
+			case `dns:"txt"`:
+				if txtTmp == nil {
+					txtTmp = make([]byte, 256*4+1)
+				}
+				off, err = packTxt(fv.Interface().([]string), msg, off, txtTmp)
+				if err != nil {
+					return lenmsg, err
+				}
+			case `dns:"opt"`: // edns
+				for j := 0; j < val.Field(i).Len(); j++ {
+					element := val.Field(i).Index(j).Interface()
+					b, e := element.(EDNS0).pack()
+					if e != nil {
+						return lenmsg, &Error{err: "overflow packing opt"}
+					}
+					// Option code
+					msg[off], msg[off+1] = packUint16(element.(EDNS0).Option())
+					// Length
+					msg[off+2], msg[off+3] = packUint16(uint16(len(b)))
+					off += 4
+					if off+len(b) > lenmsg {
+						copy(msg[off:], b)
+						off = lenmsg
+						continue
+					}
+					// Actual data
+					copy(msg[off:off+len(b)], b)
+					off += len(b)
+				}
+			case `dns:"a"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, must be 1
+					if val.Field(2).Uint() != 1 {
+						continue
+					}
+				}
+				// It must be a slice of 4, even if it is 16, we encode
+				// only the first 4
+				if off+net.IPv4len > lenmsg {
+					return lenmsg, &Error{err: "overflow packing a"}
+				}
+				switch fv.Len() {
+				case net.IPv6len:
+					msg[off] = byte(fv.Index(12).Uint())
+					msg[off+1] = byte(fv.Index(13).Uint())
+					msg[off+2] = byte(fv.Index(14).Uint())
+					msg[off+3] = byte(fv.Index(15).Uint())
+					off += net.IPv4len
+				case net.IPv4len:
+					msg[off] = byte(fv.Index(0).Uint())
+					msg[off+1] = byte(fv.Index(1).Uint())
+					msg[off+2] = byte(fv.Index(2).Uint())
+					msg[off+3] = byte(fv.Index(3).Uint())
+					off += net.IPv4len
+				case 0:
+					// Allowed, for dynamic updates
+				default:
+					return lenmsg, &Error{err: "overflow packing a"}
+				}
+			case `dns:"aaaa"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, must be 2
+					if val.Field(2).Uint() != 2 {
+						continue
+					}
+				}
+				if fv.Len() == 0 {
+					break
+				}
+				if fv.Len() > net.IPv6len || off+fv.Len() > lenmsg {
+					return lenmsg, &Error{err: "overflow packing aaaa"}
+				}
+				for j := 0; j < net.IPv6len; j++ {
+					msg[off] = byte(fv.Index(j).Uint())
+					off++
+				}
+			case `dns:"wks"`:
+				// TODO(miek): this is wrong should be lenrd
+				if off == lenmsg {
+					break // dyn. updates
+				}
+				if val.Field(i).Len() == 0 {
+					break
+				}
+				off1 := off
+				for j := 0; j < val.Field(i).Len(); j++ {
+					serv := int(fv.Index(j).Uint())
+					if off+serv/8+1 > len(msg) {
+						return len(msg), &Error{err: "overflow packing wks"}
+					}
+					msg[off+serv/8] |= byte(1 << (7 - uint(serv%8)))
+					if off+serv/8+1 > off1 {
+						off1 = off + serv/8 + 1
+					}
+				}
+				off = off1
+			case `dns:"nsec"`: // NSEC/NSEC3
+				// This is the uint16 type bitmap
+				if val.Field(i).Len() == 0 {
+					// Do absolutely nothing
+					break
+				}
+				var lastwindow, lastlength uint16
+				for j := 0; j < val.Field(i).Len(); j++ {
+					t := uint16(fv.Index(j).Uint())
+					window := t / 256
+					length := (t-window*256)/8 + 1
+					if window > lastwindow && lastlength != 0 {
+						// New window, jump to the new offset
+						off += int(lastlength) + 2
+						lastlength = 0
+					}
+					if window < lastwindow || length < lastlength {
+						return len(msg), &Error{err: "nsec bits out of order"}
+					}
+					if off+2+int(length) > len(msg) {
+						return len(msg), &Error{err: "overflow packing nsec"}
+					}
+					// Setting the window #
+					msg[off] = byte(window)
+					// Setting the octets length
+					msg[off+1] = byte(length)
+					// Setting the bit value for the type in the right octet
+					msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
+					lastwindow, lastlength = window, length
+				}
+				off += int(lastlength) + 2
+			}
+		case reflect.Struct:
+			off, err = packStructValue(fv, msg, off, compression, compress)
+			if err != nil {
+				return lenmsg, err
+			}
+		case reflect.Uint8:
+			if off+1 > lenmsg {
+				return lenmsg, &Error{err: "overflow packing uint8"}
+			}
+			msg[off] = byte(fv.Uint())
+			off++
+		case reflect.Uint16:
+			if off+2 > lenmsg {
+				return lenmsg, &Error{err: "overflow packing uint16"}
+			}
+			i := fv.Uint()
+			msg[off] = byte(i >> 8)
+			msg[off+1] = byte(i)
+			off += 2
+		case reflect.Uint32:
+			if off+4 > lenmsg {
+				return lenmsg, &Error{err: "overflow packing uint32"}
+			}
+			i := fv.Uint()
+			msg[off] = byte(i >> 24)
+			msg[off+1] = byte(i >> 16)
+			msg[off+2] = byte(i >> 8)
+			msg[off+3] = byte(i)
+			off += 4
+		case reflect.Uint64:
+			switch typefield.Tag {
+			default:
+				if off+8 > lenmsg {
+					return lenmsg, &Error{err: "overflow packing uint64"}
+				}
+				i := fv.Uint()
+				msg[off] = byte(i >> 56)
+				msg[off+1] = byte(i >> 48)
+				msg[off+2] = byte(i >> 40)
+				msg[off+3] = byte(i >> 32)
+				msg[off+4] = byte(i >> 24)
+				msg[off+5] = byte(i >> 16)
+				msg[off+6] = byte(i >> 8)
+				msg[off+7] = byte(i)
+				off += 8
+			case `dns:"uint48"`:
+				// Used in TSIG, where it stops at 48 bits, so we discard the upper 16
+				if off+6 > lenmsg {
+					return lenmsg, &Error{err: "overflow packing uint64 as uint48"}
+				}
+				i := fv.Uint()
+				msg[off] = byte(i >> 40)
+				msg[off+1] = byte(i >> 32)
+				msg[off+2] = byte(i >> 24)
+				msg[off+3] = byte(i >> 16)
+				msg[off+4] = byte(i >> 8)
+				msg[off+5] = byte(i)
+				off += 6
+			}
+		case reflect.String:
+			// There are multiple string encodings.
+			// The tag distinguishes ordinary strings from domain names.
+			s := fv.String()
+			switch typefield.Tag {
+			default:
+				return lenmsg, &Error{"bad tag packing string: " + typefield.Tag.Get("dns")}
+			case `dns:"base64"`:
+				b64, e := fromBase64([]byte(s))
+				if e != nil {
+					return lenmsg, e
+				}
+				copy(msg[off:off+len(b64)], b64)
+				off += len(b64)
+			case `dns:"domain-name"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, 1 and 2 or used for addresses
+					x := val.Field(2).Uint()
+					if x == 1 || x == 2 {
+						continue
+					}
+				}
+				if off, err = PackDomainName(s, msg, off, compression, false && compress); err != nil {
+					return lenmsg, err
+				}
+			case `dns:"cdomain-name"`:
+				if off, err = PackDomainName(s, msg, off, compression, true && compress); err != nil {
+					return lenmsg, err
+				}
+			case `dns:"size-base32"`:
+				// This is purely for NSEC3 atm, the previous byte must
+				// holds the length of the encoded string. As NSEC3
+				// is only defined to SHA1, the hashlength is 20 (160 bits)
+				msg[off-1] = 20
+				fallthrough
+			case `dns:"base32"`:
+				b32, e := fromBase32([]byte(s))
+				if e != nil {
+					return lenmsg, e
+				}
+				copy(msg[off:off+len(b32)], b32)
+				off += len(b32)
+			case `dns:"size-hex"`:
+				fallthrough
+			case `dns:"hex"`:
+				// There is no length encoded here
+				h, e := hex.DecodeString(s)
+				if e != nil {
+					return lenmsg, e
+				}
+				if off+hex.DecodedLen(len(s)) > lenmsg {
+					return lenmsg, &Error{err: "overflow packing hex"}
+				}
+				copy(msg[off:off+hex.DecodedLen(len(s))], h)
+				off += hex.DecodedLen(len(s))
+			case `dns:"size"`:
+				// the size is already encoded in the RR, we can safely use the
+				// length of string. String is RAW (not encoded in hex, nor base64)
+				copy(msg[off:off+len(s)], s)
+				off += len(s)
+			case `dns:"octet"`:
+				bytesTmp := make([]byte, 256)
+				off, err = packOctetString(fv.String(), msg, off, bytesTmp)
+				if err != nil {
+					return lenmsg, err
+				}
+			case `dns:"txt"`:
+				fallthrough
+			case "":
+				if txtTmp == nil {
+					txtTmp = make([]byte, 256*4+1)
+				}
+				off, err = packTxtString(fv.String(), msg, off, txtTmp)
+				if err != nil {
+					return lenmsg, err
+				}
+			}
+		}
+	}
+	return off, nil
+}
+
+func structValue(any interface{}) reflect.Value {
+	return reflect.ValueOf(any).Elem()
+}
+
+// PackStruct packs any structure to wire format.
+func PackStruct(any interface{}, msg []byte, off int) (off1 int, err error) {
+	off, err = packStructValue(structValue(any), msg, off, nil, false)
+	return off, err
+}
+
+func packStructCompress(any interface{}, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+	off, err = packStructValue(structValue(any), msg, off, compression, compress)
+	return off, err
+}
+
+// Unpack a reflect.StructValue from msg.
+// Same restrictions as packStructValue.
+func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err error) {
+	lenmsg := len(msg)
+	for i := 0; i < val.NumField(); i++ {
+		if off > lenmsg {
+			return lenmsg, &Error{"bad offset unpacking"}
+		}
+		switch fv := val.Field(i); fv.Kind() {
+		default:
+			return lenmsg, &Error{err: "bad kind unpacking"}
+		case reflect.Interface:
+			// PrivateRR is the only RR implementation that has interface field.
+			// therefore it's expected that this interface would be PrivateRdata
+			switch data := fv.Interface().(type) {
+			case PrivateRdata:
+				n, err := data.Unpack(msg[off:])
+				if err != nil {
+					return lenmsg, err
+				}
+				off += n
+			default:
+				return lenmsg, &Error{err: "bad kind interface unpacking"}
+			}
+		case reflect.Slice:
+			switch val.Type().Field(i).Tag {
+			default:
+				return lenmsg, &Error{"bad tag unpacking slice: " + val.Type().Field(i).Tag.Get("dns")}
+			case `dns:"domain-name"`:
+				// HIP record slice of name (or none)
+				var servers []string
+				var s string
+				for off < lenmsg {
+					s, off, err = UnpackDomainName(msg, off)
+					if err != nil {
+						return lenmsg, err
+					}
+					servers = append(servers, s)
+				}
+				fv.Set(reflect.ValueOf(servers))
+			case `dns:"txt"`:
+				if off == lenmsg {
+					break
+				}
+				var txt []string
+				txt, off, err = unpackTxt(msg, off)
+				if err != nil {
+					return lenmsg, err
+				}
+				fv.Set(reflect.ValueOf(txt))
+			case `dns:"opt"`: // edns0
+				if off == lenmsg {
+					// This is an EDNS0 (OPT Record) with no rdata
+					// We can safely return here.
+					break
+				}
+				var edns []EDNS0
+			Option:
+				code := uint16(0)
+				if off+4 > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking opt"}
+				}
+				code, off = unpackUint16(msg, off)
+				optlen, off1 := unpackUint16(msg, off)
+				if off1+int(optlen) > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking opt"}
+				}
+				switch code {
+				case EDNS0NSID:
+					e := new(EDNS0_NSID)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				case EDNS0SUBNET, EDNS0SUBNETDRAFT:
+					e := new(EDNS0_SUBNET)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+					if code == EDNS0SUBNETDRAFT {
+						e.DraftOption = true
+					}
+				case EDNS0UL:
+					e := new(EDNS0_UL)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				case EDNS0LLQ:
+					e := new(EDNS0_LLQ)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				case EDNS0DAU:
+					e := new(EDNS0_DAU)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				case EDNS0DHU:
+					e := new(EDNS0_DHU)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				case EDNS0N3U:
+					e := new(EDNS0_N3U)
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				default:
+					e := new(EDNS0_LOCAL)
+					e.Code = code
+					if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
+						return lenmsg, err
+					}
+					edns = append(edns, e)
+					off = off1 + int(optlen)
+				}
+				if off < lenmsg {
+					goto Option
+				}
+				fv.Set(reflect.ValueOf(edns))
+			case `dns:"a"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, must be 1
+					if val.Field(2).Uint() != 1 {
+						continue
+					}
+				}
+				if off == lenmsg {
+					break // dyn. update
+				}
+				if off+net.IPv4len > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking a"}
+				}
+				fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
+				off += net.IPv4len
+			case `dns:"aaaa"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, must be 2
+					if val.Field(2).Uint() != 2 {
+						continue
+					}
+				}
+				if off == lenmsg {
+					break
+				}
+				if off+net.IPv6len > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking aaaa"}
+				}
+				fv.Set(reflect.ValueOf(net.IP{msg[off], msg[off+1], msg[off+2], msg[off+3], msg[off+4],
+					msg[off+5], msg[off+6], msg[off+7], msg[off+8], msg[off+9], msg[off+10],
+					msg[off+11], msg[off+12], msg[off+13], msg[off+14], msg[off+15]}))
+				off += net.IPv6len
+			case `dns:"wks"`:
+				// Rest of the record is the bitmap
+				var serv []uint16
+				j := 0
+				for off < lenmsg {
+					if off+1 > lenmsg {
+						return lenmsg, &Error{err: "overflow unpacking wks"}
+					}
+					b := msg[off]
+					// Check the bits one by one, and set the type
+					if b&0x80 == 0x80 {
+						serv = append(serv, uint16(j*8+0))
+					}
+					if b&0x40 == 0x40 {
+						serv = append(serv, uint16(j*8+1))
+					}
+					if b&0x20 == 0x20 {
+						serv = append(serv, uint16(j*8+2))
+					}
+					if b&0x10 == 0x10 {
+						serv = append(serv, uint16(j*8+3))
+					}
+					if b&0x8 == 0x8 {
+						serv = append(serv, uint16(j*8+4))
+					}
+					if b&0x4 == 0x4 {
+						serv = append(serv, uint16(j*8+5))
+					}
+					if b&0x2 == 0x2 {
+						serv = append(serv, uint16(j*8+6))
+					}
+					if b&0x1 == 0x1 {
+						serv = append(serv, uint16(j*8+7))
+					}
+					j++
+					off++
+				}
+				fv.Set(reflect.ValueOf(serv))
+			case `dns:"nsec"`: // NSEC/NSEC3
+				if off == len(msg) {
+					break
+				}
+				// Rest of the record is the type bitmap
+				var nsec []uint16
+				length := 0
+				window := 0
+				lastwindow := -1
+				for off < len(msg) {
+					if off+2 > len(msg) {
+						return len(msg), &Error{err: "overflow unpacking nsecx"}
+					}
+					window = int(msg[off])
+					length = int(msg[off+1])
+					off += 2
+					if window <= lastwindow {
+						// RFC 4034: Blocks are present in the NSEC RR RDATA in
+						// increasing numerical order.
+						return len(msg), &Error{err: "out of order NSEC block"}
+					}
+					if length == 0 {
+						// RFC 4034: Blocks with no types present MUST NOT be included.
+						return len(msg), &Error{err: "empty NSEC block"}
+					}
+					if length > 32 {
+						return len(msg), &Error{err: "NSEC block too long"}
+					}
+					if off+length > len(msg) {
+						return len(msg), &Error{err: "overflowing NSEC block"}
+					}
+
+					// Walk the bytes in the window and extract the type bits
+					for j := 0; j < length; j++ {
+						b := msg[off+j]
+						// Check the bits one by one, and set the type
+						if b&0x80 == 0x80 {
+							nsec = append(nsec, uint16(window*256+j*8+0))
+						}
+						if b&0x40 == 0x40 {
+							nsec = append(nsec, uint16(window*256+j*8+1))
+						}
+						if b&0x20 == 0x20 {
+							nsec = append(nsec, uint16(window*256+j*8+2))
+						}
+						if b&0x10 == 0x10 {
+							nsec = append(nsec, uint16(window*256+j*8+3))
+						}
+						if b&0x8 == 0x8 {
+							nsec = append(nsec, uint16(window*256+j*8+4))
+						}
+						if b&0x4 == 0x4 {
+							nsec = append(nsec, uint16(window*256+j*8+5))
+						}
+						if b&0x2 == 0x2 {
+							nsec = append(nsec, uint16(window*256+j*8+6))
+						}
+						if b&0x1 == 0x1 {
+							nsec = append(nsec, uint16(window*256+j*8+7))
+						}
+					}
+					off += length
+					lastwindow = window
+				}
+				fv.Set(reflect.ValueOf(nsec))
+			}
+		case reflect.Struct:
+			off, err = unpackStructValue(fv, msg, off)
+			if err != nil {
+				return lenmsg, err
+			}
+			if val.Type().Field(i).Name == "Hdr" {
+				lenrd := off + int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
+				if lenrd > lenmsg {
+					return lenmsg, &Error{err: "overflowing header size"}
+				}
+				msg = msg[:lenrd]
+				lenmsg = len(msg)
+			}
+		case reflect.Uint8:
+			if off == lenmsg {
+				break
+			}
+			if off+1 > lenmsg {
+				return lenmsg, &Error{err: "overflow unpacking uint8"}
+			}
+			fv.SetUint(uint64(uint8(msg[off])))
+			off++
+		case reflect.Uint16:
+			if off == lenmsg {
+				break
+			}
+			var i uint16
+			if off+2 > lenmsg {
+				return lenmsg, &Error{err: "overflow unpacking uint16"}
+			}
+			i, off = unpackUint16(msg, off)
+			fv.SetUint(uint64(i))
+		case reflect.Uint32:
+			if off == lenmsg {
+				break
+			}
+			if off+4 > lenmsg {
+				return lenmsg, &Error{err: "overflow unpacking uint32"}
+			}
+			fv.SetUint(uint64(uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])))
+			off += 4
+		case reflect.Uint64:
+			if off == lenmsg {
+				break
+			}
+			switch val.Type().Field(i).Tag {
+			default:
+				if off+8 > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking uint64"}
+				}
+				fv.SetUint(uint64(uint64(msg[off])<<56 | uint64(msg[off+1])<<48 | uint64(msg[off+2])<<40 |
+					uint64(msg[off+3])<<32 | uint64(msg[off+4])<<24 | uint64(msg[off+5])<<16 | uint64(msg[off+6])<<8 | uint64(msg[off+7])))
+				off += 8
+			case `dns:"uint48"`:
+				// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
+				if off+6 > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking uint64 as uint48"}
+				}
+				fv.SetUint(uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
+					uint64(msg[off+4])<<8 | uint64(msg[off+5])))
+				off += 6
+			}
+		case reflect.String:
+			var s string
+			if off == lenmsg {
+				break
+			}
+			switch val.Type().Field(i).Tag {
+			default:
+				return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")}
+			case `dns:"octet"`:
+				s = string(msg[off:])
+				off = lenmsg
+			case `dns:"hex"`:
+				hexend := lenmsg
+				if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
+					hexend = off + int(val.FieldByName("HitLength").Uint())
+				}
+				if hexend > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking HIP hex"}
+				}
+				s = hex.EncodeToString(msg[off:hexend])
+				off = hexend
+			case `dns:"base64"`:
+				// Rest of the RR is base64 encoded value
+				b64end := lenmsg
+				if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
+					b64end = off + int(val.FieldByName("PublicKeyLength").Uint())
+				}
+				if b64end > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking HIP base64"}
+				}
+				s = toBase64(msg[off:b64end])
+				off = b64end
+			case `dns:"cdomain-name"`:
+				fallthrough
+			case `dns:"domain-name"`:
+				if val.Type().String() == "dns.IPSECKEY" {
+					// Field(2) is GatewayType, 1 and 2 or used for addresses
+					x := val.Field(2).Uint()
+					if x == 1 || x == 2 {
+						continue
+					}
+				}
+				if off == lenmsg {
+					// zero rdata foo, OK for dyn. updates
+					break
+				}
+				s, off, err = UnpackDomainName(msg, off)
+				if err != nil {
+					return lenmsg, err
+				}
+			case `dns:"size-base32"`:
+				var size int
+				switch val.Type().Name() {
+				case "NSEC3":
+					switch val.Type().Field(i).Name {
+					case "NextDomain":
+						name := val.FieldByName("HashLength")
+						size = int(name.Uint())
+					}
+				}
+				if off+size > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking base32"}
+				}
+				s = toBase32(msg[off : off+size])
+				off += size
+			case `dns:"size-hex"`:
+				// a "size" string, but it must be encoded in hex in the string
+				var size int
+				switch val.Type().Name() {
+				case "NSEC3":
+					switch val.Type().Field(i).Name {
+					case "Salt":
+						name := val.FieldByName("SaltLength")
+						size = int(name.Uint())
+					case "NextDomain":
+						name := val.FieldByName("HashLength")
+						size = int(name.Uint())
+					}
+				case "TSIG":
+					switch val.Type().Field(i).Name {
+					case "MAC":
+						name := val.FieldByName("MACSize")
+						size = int(name.Uint())
+					case "OtherData":
+						name := val.FieldByName("OtherLen")
+						size = int(name.Uint())
+					}
+				}
+				if off+size > lenmsg {
+					return lenmsg, &Error{err: "overflow unpacking hex"}
+				}
+				s = hex.EncodeToString(msg[off : off+size])
+				off += size
+			case `dns:"txt"`:
+				fallthrough
+			case "":
+				s, off, err = unpackTxtString(msg, off)
+			}
+			fv.SetString(s)
+		}
+	}
+	return off, nil
+}
+
+// Helpers for dealing with escaped bytes
+func isDigit(b byte) bool { return b >= '0' && b <= '9' }
+
+func dddToByte(s []byte) byte {
+	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
+}
+
+// UnpackStruct unpacks a binary message from offset off to the interface
+// value given.
+func UnpackStruct(any interface{}, msg []byte, off int) (int, error) {
+	return unpackStructValue(structValue(any), msg, off)
+}
+
+// Helper function for packing and unpacking
+func intToBytes(i *big.Int, length int) []byte {
+	buf := i.Bytes()
+	if len(buf) < length {
+		b := make([]byte, length)
+		copy(b[length-len(buf):], buf)
+		return b
+	}
+	return buf
+}
+
+func unpackUint16(msg []byte, off int) (uint16, int) {
+	return uint16(msg[off])<<8 | uint16(msg[off+1]), off + 2
+}
+
+func packUint16(i uint16) (byte, byte) {
+	return byte(i >> 8), byte(i)
+}
+
+func toBase32(b []byte) string {
+	return base32.HexEncoding.EncodeToString(b)
+}
+
+func fromBase32(s []byte) (buf []byte, err error) {
+	buflen := base32.HexEncoding.DecodedLen(len(s))
+	buf = make([]byte, buflen)
+	n, err := base32.HexEncoding.Decode(buf, s)
+	buf = buf[:n]
+	return
+}
+
+func toBase64(b []byte) string {
+	return base64.StdEncoding.EncodeToString(b)
+}
+
+func fromBase64(s []byte) (buf []byte, err error) {
+	buflen := base64.StdEncoding.DecodedLen(len(s))
+	buf = make([]byte, buflen)
+	n, err := base64.StdEncoding.Decode(buf, s)
+	buf = buf[:n]
+	return
+}
+
+// PackRR packs a resource record rr into msg[off:].
+// See PackDomainName for documentation about the compression.
+func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+	if rr == nil {
+		return len(msg), &Error{err: "nil rr"}
+	}
+
+	off1, err = packStructCompress(rr, msg, off, compression, compress)
+	if err != nil {
+		return len(msg), err
+	}
+	if rawSetRdlength(msg, off, off1) {
+		return off1, nil
+	}
+	return off, ErrRdata
+}
+
+// UnpackRR unpacks msg[off:] into an RR.
+func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
+	// unpack just the header, to find the rr type and length
+	var h RR_Header
+	off0 := off
+	if off, err = UnpackStruct(&h, msg, off); err != nil {
+		return nil, len(msg), err
+	}
+	end := off + int(h.Rdlength)
+	// make an rr of that type and re-unpack.
+	mk, known := typeToRR[h.Rrtype]
+	if !known {
+		rr = new(RFC3597)
+	} else {
+		rr = mk()
+	}
+	off, err = UnpackStruct(rr, msg, off0)
+	if off != end {
+		return &h, end, &Error{err: "bad rdlength"}
+	}
+	return rr, off, err
+}
+
+// Reverse a map
+func reverseInt8(m map[uint8]string) map[string]uint8 {
+	n := make(map[string]uint8)
+	for u, s := range m {
+		n[s] = u
+	}
+	return n
+}
+
+func reverseInt16(m map[uint16]string) map[string]uint16 {
+	n := make(map[string]uint16)
+	for u, s := range m {
+		n[s] = u
+	}
+	return n
+}
+
+func reverseInt(m map[int]string) map[string]int {
+	n := make(map[string]int)
+	for u, s := range m {
+		n[s] = u
+	}
+	return n
+}
+
+// Convert a MsgHdr to a string, with dig-like headers:
+//
+//;; opcode: QUERY, status: NOERROR, id: 48404
+//
+//;; flags: qr aa rd ra;
+func (h *MsgHdr) String() string {
+	if h == nil {
+		return "<nil> MsgHdr"
+	}
+
+	s := ";; opcode: " + OpcodeToString[h.Opcode]
+	s += ", status: " + RcodeToString[h.Rcode]
+	s += ", id: " + strconv.Itoa(int(h.Id)) + "\n"
+
+	s += ";; flags:"
+	if h.Response {
+		s += " qr"
+	}
+	if h.Authoritative {
+		s += " aa"
+	}
+	if h.Truncated {
+		s += " tc"
+	}
+	if h.RecursionDesired {
+		s += " rd"
+	}
+	if h.RecursionAvailable {
+		s += " ra"
+	}
+	if h.Zero { // Hmm
+		s += " z"
+	}
+	if h.AuthenticatedData {
+		s += " ad"
+	}
+	if h.CheckingDisabled {
+		s += " cd"
+	}
+
+	s += ";"
+	return s
+}
+
+// Pack packs a Msg: it is converted to to wire format.
+// If the dns.Compress is true the message will be in compressed wire format.
+func (dns *Msg) Pack() (msg []byte, err error) {
+	return dns.PackBuffer(nil)
+}
+
+// PackBuffer packs a Msg, using the given buffer buf. If buf is too small
+// a new buffer is allocated.
+func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
+	var dh Header
+	var compression map[string]int
+	if dns.Compress {
+		compression = make(map[string]int) // Compression pointer mappings
+	}
+
+	if dns.Rcode < 0 || dns.Rcode > 0xFFF {
+		return nil, ErrRcode
+	}
+	if dns.Rcode > 0xF {
+		// Regular RCODE field is 4 bits
+		opt := dns.IsEdns0()
+		if opt == nil {
+			return nil, ErrExtendedRcode
+		}
+		opt.SetExtendedRcode(uint8(dns.Rcode >> 4))
+		dns.Rcode &= 0xF
+	}
+
+	// Convert convenient Msg into wire-like Header.
+	dh.Id = dns.Id
+	dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode)
+	if dns.Response {
+		dh.Bits |= _QR
+	}
+	if dns.Authoritative {
+		dh.Bits |= _AA
+	}
+	if dns.Truncated {
+		dh.Bits |= _TC
+	}
+	if dns.RecursionDesired {
+		dh.Bits |= _RD
+	}
+	if dns.RecursionAvailable {
+		dh.Bits |= _RA
+	}
+	if dns.Zero {
+		dh.Bits |= _Z
+	}
+	if dns.AuthenticatedData {
+		dh.Bits |= _AD
+	}
+	if dns.CheckingDisabled {
+		dh.Bits |= _CD
+	}
+
+	// Prepare variable sized arrays.
+	question := dns.Question
+	answer := dns.Answer
+	ns := dns.Ns
+	extra := dns.Extra
+
+	dh.Qdcount = uint16(len(question))
+	dh.Ancount = uint16(len(answer))
+	dh.Nscount = uint16(len(ns))
+	dh.Arcount = uint16(len(extra))
+
+	// We need the uncompressed length here, because we first pack it and then compress it.
+	msg = buf
+	compress := dns.Compress
+	dns.Compress = false
+	if packLen := dns.Len() + 1; len(msg) < packLen {
+		msg = make([]byte, packLen)
+	}
+	dns.Compress = compress
+
+	// Pack it in: header and then the pieces.
+	off := 0
+	off, err = packStructCompress(&dh, msg, off, compression, dns.Compress)
+	if err != nil {
+		return nil, err
+	}
+	for i := 0; i < len(question); i++ {
+		off, err = packStructCompress(&question[i], msg, off, compression, dns.Compress)
+		if err != nil {
+			return nil, err
+		}
+	}
+	for i := 0; i < len(answer); i++ {
+		off, err = PackRR(answer[i], msg, off, compression, dns.Compress)
+		if err != nil {
+			return nil, err
+		}
+	}
+	for i := 0; i < len(ns); i++ {
+		off, err = PackRR(ns[i], msg, off, compression, dns.Compress)
+		if err != nil {
+			return nil, err
+		}
+	}
+	for i := 0; i < len(extra); i++ {
+		off, err = PackRR(extra[i], msg, off, compression, dns.Compress)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return msg[:off], nil
+}
+
+// Unpack unpacks a binary message to a Msg structure.
+func (dns *Msg) Unpack(msg []byte) (err error) {
+	// Header.
+	var dh Header
+	off := 0
+	if off, err = UnpackStruct(&dh, msg, off); err != nil {
+		return err
+	}
+	dns.Id = dh.Id
+	dns.Response = (dh.Bits & _QR) != 0
+	dns.Opcode = int(dh.Bits>>11) & 0xF
+	dns.Authoritative = (dh.Bits & _AA) != 0
+	dns.Truncated = (dh.Bits & _TC) != 0
+	dns.RecursionDesired = (dh.Bits & _RD) != 0
+	dns.RecursionAvailable = (dh.Bits & _RA) != 0
+	dns.Zero = (dh.Bits & _Z) != 0
+	dns.AuthenticatedData = (dh.Bits & _AD) != 0
+	dns.CheckingDisabled = (dh.Bits & _CD) != 0
+	dns.Rcode = int(dh.Bits & 0xF)
+
+	// Don't pre-alloc these arrays, the incoming lengths are from the network.
+	dns.Question = make([]Question, 0, 1)
+	dns.Answer = make([]RR, 0, 10)
+	dns.Ns = make([]RR, 0, 10)
+	dns.Extra = make([]RR, 0, 10)
+
+	var q Question
+	for i := 0; i < int(dh.Qdcount); i++ {
+		off1 := off
+		off, err = UnpackStruct(&q, msg, off)
+		if err != nil {
+			return err
+		}
+		if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
+			dh.Qdcount = uint16(i)
+			break
+		}
+
+		dns.Question = append(dns.Question, q)
+
+	}
+	// If we see a TC bit being set we return here, without
+	// an error, because technically it isn't an error. So return
+	// without parsing the potentially corrupt packet and hitting an error.
+	// TODO(miek): this isn't the best strategy!
+	// Better stragey would be: set boolean indicating truncated message, go forth and parse
+	// until we hit an error, return the message without the latest parsed rr if this boolean
+	// is true.
+	if dns.Truncated {
+		dns.Answer = nil
+		dns.Ns = nil
+		dns.Extra = nil
+		return nil
+	}
+
+	var r RR
+	for i := 0; i < int(dh.Ancount); i++ {
+		off1 := off
+		r, off, err = UnpackRR(msg, off)
+		if err != nil {
+			return err
+		}
+		if off1 == off { // Offset does not increase anymore, dh.Ancount is a lie!
+			dh.Ancount = uint16(i)
+			break
+		}
+		dns.Answer = append(dns.Answer, r)
+	}
+	for i := 0; i < int(dh.Nscount); i++ {
+		off1 := off
+		r, off, err = UnpackRR(msg, off)
+		if err != nil {
+			return err
+		}
+		if off1 == off { // Offset does not increase anymore, dh.Nscount is a lie!
+			dh.Nscount = uint16(i)
+			break
+		}
+		dns.Ns = append(dns.Ns, r)
+	}
+	for i := 0; i < int(dh.Arcount); i++ {
+		off1 := off
+		r, off, err = UnpackRR(msg, off)
+		if err != nil {
+			return err
+		}
+		if off1 == off { // Offset does not increase anymore, dh.Arcount is a lie!
+			dh.Arcount = uint16(i)
+			break
+		}
+		dns.Extra = append(dns.Extra, r)
+	}
+	if off != len(msg) {
+		// TODO(miek) make this an error?
+		// use PackOpt to let people tell how detailed the error reporting should be?
+		// println("dns: extra bytes in dns packet", off, "<", len(msg))
+	}
+	return nil
+}
+
+// Convert a complete message to a string with dig-like output.
+func (dns *Msg) String() string {
+	if dns == nil {
+		return "<nil> MsgHdr"
+	}
+	s := dns.MsgHdr.String() + " "
+	s += "QUERY: " + strconv.Itoa(len(dns.Question)) + ", "
+	s += "ANSWER: " + strconv.Itoa(len(dns.Answer)) + ", "
+	s += "AUTHORITY: " + strconv.Itoa(len(dns.Ns)) + ", "
+	s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
+	if len(dns.Question) > 0 {
+		s += "\n;; QUESTION SECTION:\n"
+		for i := 0; i < len(dns.Question); i++ {
+			s += dns.Question[i].String() + "\n"
+		}
+	}
+	if len(dns.Answer) > 0 {
+		s += "\n;; ANSWER SECTION:\n"
+		for i := 0; i < len(dns.Answer); i++ {
+			if dns.Answer[i] != nil {
+				s += dns.Answer[i].String() + "\n"
+			}
+		}
+	}
+	if len(dns.Ns) > 0 {
+		s += "\n;; AUTHORITY SECTION:\n"
+		for i := 0; i < len(dns.Ns); i++ {
+			if dns.Ns[i] != nil {
+				s += dns.Ns[i].String() + "\n"
+			}
+		}
+	}
+	if len(dns.Extra) > 0 {
+		s += "\n;; ADDITIONAL SECTION:\n"
+		for i := 0; i < len(dns.Extra); i++ {
+			if dns.Extra[i] != nil {
+				s += dns.Extra[i].String() + "\n"
+			}
+		}
+	}
+	return s
+}
+
+// Len returns the message length when in (un)compressed wire format.
+// 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,
+// than packing it, measuring the size and discarding the buffer.
+func (dns *Msg) Len() int {
+	// We always return one more than needed.
+	l := 12 // Message header is always 12 bytes
+	var compression map[string]int
+	if dns.Compress {
+		compression = make(map[string]int)
+	}
+	for i := 0; i < len(dns.Question); i++ {
+		l += dns.Question[i].len()
+		if dns.Compress {
+			compressionLenHelper(compression, dns.Question[i].Name)
+		}
+	}
+	for i := 0; i < len(dns.Answer); i++ {
+		l += dns.Answer[i].len()
+		if dns.Compress {
+			k, ok := compressionLenSearch(compression, dns.Answer[i].Header().Name)
+			if ok {
+				l += 1 - k
+			}
+			compressionLenHelper(compression, dns.Answer[i].Header().Name)
+			k, ok = compressionLenSearchType(compression, dns.Answer[i])
+			if ok {
+				l += 1 - k
+			}
+			compressionLenHelperType(compression, dns.Answer[i])
+		}
+	}
+	for i := 0; i < len(dns.Ns); i++ {
+		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++ {
+		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
+}
+
+// Put the parts of the name in the compression map.
+func compressionLenHelper(c map[string]int, s string) {
+	pref := ""
+	lbs := Split(s)
+	for j := len(lbs) - 1; j >= 0; j-- {
+		pref = s[lbs[j]:]
+		if _, ok := c[pref]; !ok {
+			c[pref] = len(pref)
+		}
+	}
+}
+
+// Look for each part in the compression map and returns its length,
+// keep on searching so we get the longest match.
+func compressionLenSearch(c map[string]int, s string) (int, bool) {
+	off := 0
+	end := false
+	if s == "" { // don't bork on bogus data
+		return 0, false
+	}
+	for {
+		if _, ok := c[s[off:]]; ok {
+			return len(s[off:]), true
+		}
+		if end {
+			break
+		}
+		off, end = NextLabel(s, off)
+	}
+	return 0, false
+}
+
+// TODO(miek): should add all types, because the all can be *used* for compression.
+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 *MINFO:
+		compressionLenHelper(c, x.Rmail)
+		compressionLenHelper(c, x.Email)
+	case *AFSDB:
+		compressionLenHelper(c, x.Hostname)
+	}
+}
+
+// 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 *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
+}
+
+// id returns a 16 bits random number to be used as a
+// message id. The random provided should be good enough.
+func id() uint16 {
+	return uint16(rand.Int()) ^ uint16(time.Now().Nanosecond())
+}
+
+// Copy returns a new RR which is a deep-copy of r.
+func Copy(r RR) RR {
+	r1 := r.copy()
+	return r1
+}
+
+// Copy returns a new *Msg which is a deep-copy of dns.
+func (dns *Msg) Copy() *Msg {
+	return dns.CopyTo(new(Msg))
+}
+
+// CopyTo copies the contents to the provided message using a deep-copy and returns the copy.
+func (dns *Msg) CopyTo(r1 *Msg) *Msg {
+	r1.MsgHdr = dns.MsgHdr
+	r1.Compress = dns.Compress
+
+	if len(dns.Question) > 0 {
+		r1.Question = make([]Question, len(dns.Question))
+		copy(r1.Question, dns.Question) // TODO(miek): Question is an immutable value, ok to do a shallow-copy
+	}
+
+	rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
+	var rri int
+
+	if len(dns.Answer) > 0 {
+		rrbegin := rri
+		for i := 0; i < len(dns.Answer); i++ {
+			rrArr[rri] = dns.Answer[i].copy()
+			rri++
+		}
+		r1.Answer = rrArr[rrbegin:rri:rri]
+	}
+
+	if len(dns.Ns) > 0 {
+		rrbegin := rri
+		for i := 0; i < len(dns.Ns); i++ {
+			rrArr[rri] = dns.Ns[i].copy()
+			rri++
+		}
+		r1.Ns = rrArr[rrbegin:rri:rri]
+	}
+
+	if len(dns.Extra) > 0 {
+		rrbegin := rri
+		for i := 0; i < len(dns.Extra); i++ {
+			rrArr[rri] = dns.Extra[i].copy()
+			rri++
+		}
+		r1.Extra = rrArr[rrbegin:rri:rri]
+	}
+
+	return r1
+}
diff --git a/vendor/github.com/miekg/dns/nsecx.go b/vendor/github.com/miekg/dns/nsecx.go
new file mode 100644
index 0000000000000000000000000000000000000000..d2392c6ec60c22211024723bb001703fbaeaf0ba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/nsecx.go
@@ -0,0 +1,112 @@
+package dns
+
+import (
+	"crypto/sha1"
+	"hash"
+	"io"
+	"strings"
+)
+
+type saltWireFmt struct {
+	Salt string `dns:"size-hex"`
+}
+
+// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in
+// uppercase.
+func HashName(label string, ha uint8, iter uint16, salt string) string {
+	saltwire := new(saltWireFmt)
+	saltwire.Salt = salt
+	wire := make([]byte, DefaultMsgSize)
+	n, err := PackStruct(saltwire, wire, 0)
+	if err != nil {
+		return ""
+	}
+	wire = wire[:n]
+	name := make([]byte, 255)
+	off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
+	if err != nil {
+		return ""
+	}
+	name = name[:off]
+	var s hash.Hash
+	switch ha {
+	case SHA1:
+		s = sha1.New()
+	default:
+		return ""
+	}
+
+	// k = 0
+	name = append(name, wire...)
+	io.WriteString(s, string(name))
+	nsec3 := s.Sum(nil)
+	// k > 0
+	for k := uint16(0); k < iter; k++ {
+		s.Reset()
+		nsec3 = append(nsec3, wire...)
+		io.WriteString(s, string(nsec3))
+		nsec3 = s.Sum(nil)
+	}
+	return toBase32(nsec3)
+}
+
+// Denialer is an interface that should be implemented by types that are used to denial
+// 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 {
+	// FIXME(miek): check if the zones match
+	// FIXME(miek): check if we're not dealing with parent nsec3
+	hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
+	labels := Split(rr.Hdr.Name)
+	if len(labels) < 2 {
+		return false
+	}
+	hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
+	if hash == rr.NextDomain {
+		return false // empty interval
+	}
+	if hash > rr.NextDomain { // last name, points to apex
+		// hname > hash
+		// hname > rr.NextDomain
+		// TODO(miek)
+	}
+	if hname <= hash {
+		return false
+	}
+	if hname >= rr.NextDomain {
+		return false
+	}
+	return true
+}
+
+// Match implements the Denialer interface.
+func (rr *NSEC3) Match(name string) bool {
+	// FIXME(miek): Check if we are in the same zone
+	hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
+	labels := Split(rr.Hdr.Name)
+	if len(labels) < 2 {
+		return false
+	}
+	hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
+	if hash == hname {
+		return true
+	}
+	return false
+}
diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go
new file mode 100644
index 0000000000000000000000000000000000000000..7290791be35bf59ba917bba1dc3bd7f41bb70c52
--- /dev/null
+++ b/vendor/github.com/miekg/dns/privaterr.go
@@ -0,0 +1,117 @@
+package dns
+
+import (
+	"fmt"
+	"strings"
+)
+
+// PrivateRdata is an interface used for implementing "Private Use" RR types, see
+// RFC 6895. This allows one to experiment with new RR types, without requesting an
+// official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove.
+type PrivateRdata interface {
+	// String returns the text presentaton of the Rdata of the Private RR.
+	String() string
+	// Parse parses the Rdata of the private RR.
+	Parse([]string) error
+	// Pack is used when packing a private RR into a buffer.
+	Pack([]byte) (int, error)
+	// Unpack is used when unpacking a private RR from a buffer.
+	// TODO(miek): diff. signature than Pack, see edns0.go for instance.
+	Unpack([]byte) (int, error)
+	// Copy copies the Rdata.
+	Copy(PrivateRdata) error
+	// Len returns the length in octets of the Rdata.
+	Len() int
+}
+
+// PrivateRR represents an RR that uses a PrivateRdata user-defined type.
+// It mocks normal RRs and implements dns.RR interface.
+type PrivateRR struct {
+	Hdr  RR_Header
+	Data PrivateRdata
+}
+
+func mkPrivateRR(rrtype uint16) *PrivateRR {
+	// Panics if RR is not an instance of PrivateRR.
+	rrfunc, ok := typeToRR[rrtype]
+	if !ok {
+		panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
+	}
+
+	anyrr := rrfunc()
+	switch rr := anyrr.(type) {
+	case *PrivateRR:
+		return rr
+	}
+	panic(fmt.Sprintf("dns: RR is not a PrivateRR, typeToRR[%d] generator returned %T", rrtype, anyrr))
+}
+
+// Header return the RR header of r.
+func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
+
+func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
+
+// Private len and copy parts to satisfy RR interface.
+func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
+func (r *PrivateRR) copy() RR {
+	// make new RR like this:
+	rr := mkPrivateRR(r.Hdr.Rrtype)
+	newh := r.Hdr.copyHeader()
+	rr.Hdr = *newh
+
+	err := r.Data.Copy(rr.Data)
+	if err != nil {
+		panic("dns: got value that could not be used to copy Private rdata")
+	}
+	return rr
+}
+
+// PrivateHandle registers a private resource record type. It requires
+// string and numeric representation of private RR type and generator function as argument.
+func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
+	rtypestr = strings.ToUpper(rtypestr)
+
+	typeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
+	TypeToString[rtype] = rtypestr
+	StringToType[rtypestr] = rtype
+
+	setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+		rr := mkPrivateRR(h.Rrtype)
+		rr.Hdr = h
+
+		var l lex
+		text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
+	FETCH:
+		for {
+			// TODO(miek): we could also be returning _QUOTE, this might or might not
+			// be an issue (basically parsing TXT becomes hard)
+			switch l = <-c; l.value {
+			case zNewline, zEOF:
+				break FETCH
+			case zString:
+				text = append(text, l.token)
+			}
+		}
+
+		err := rr.Data.Parse(text)
+		if err != nil {
+			return nil, &ParseError{f, err.Error(), l}, ""
+		}
+
+		return rr, nil, ""
+	}
+
+	typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
+}
+
+// PrivateHandleRemove removes defenitions required to support private RR type.
+func PrivateHandleRemove(rtype uint16) {
+	rtypestr, ok := TypeToString[rtype]
+	if ok {
+		delete(typeToRR, rtype)
+		delete(TypeToString, rtype)
+		delete(typeToparserFunc, rtype)
+		delete(StringToType, rtypestr)
+	}
+	return
+}
diff --git a/vendor/github.com/miekg/dns/rawmsg.go b/vendor/github.com/miekg/dns/rawmsg.go
new file mode 100644
index 0000000000000000000000000000000000000000..f138b7761dfd5cfcdc3fb8911de870126f1c1b0e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/rawmsg.go
@@ -0,0 +1,95 @@
+package dns
+
+// These raw* functions do not use reflection, they directly set the values
+// in the buffer. There are faster than their reflection counterparts.
+
+// RawSetId sets the message id in buf.
+func rawSetId(msg []byte, i uint16) bool {
+	if len(msg) < 2 {
+		return false
+	}
+	msg[0], msg[1] = packUint16(i)
+	return true
+}
+
+// rawSetQuestionLen sets the length of the question section.
+func rawSetQuestionLen(msg []byte, i uint16) bool {
+	if len(msg) < 6 {
+		return false
+	}
+	msg[4], msg[5] = packUint16(i)
+	return true
+}
+
+// rawSetAnswerLen sets the lenght of the answer section.
+func rawSetAnswerLen(msg []byte, i uint16) bool {
+	if len(msg) < 8 {
+		return false
+	}
+	msg[6], msg[7] = packUint16(i)
+	return true
+}
+
+// rawSetsNsLen sets the lenght of the authority section.
+func rawSetNsLen(msg []byte, i uint16) bool {
+	if len(msg) < 10 {
+		return false
+	}
+	msg[8], msg[9] = packUint16(i)
+	return true
+}
+
+// rawSetExtraLen sets the lenght of the additional section.
+func rawSetExtraLen(msg []byte, i uint16) bool {
+	if len(msg) < 12 {
+		return false
+	}
+	msg[10], msg[11] = packUint16(i)
+	return true
+}
+
+// rawSetRdlength sets the rdlength in the header of
+// the RR. The offset 'off' must be positioned at the
+// start of the header of the RR, 'end' must be the
+// end of the RR.
+func rawSetRdlength(msg []byte, off, end int) bool {
+	l := len(msg)
+Loop:
+	for {
+		if off+1 > l {
+			return false
+		}
+		c := int(msg[off])
+		off++
+		switch c & 0xC0 {
+		case 0x00:
+			if c == 0x00 {
+				// End of the domainname
+				break Loop
+			}
+			if off+c > l {
+				return false
+			}
+			off += c
+
+		case 0xC0:
+			// pointer, next byte included, ends domainname
+			off++
+			break Loop
+		}
+	}
+	// The domainname has been seen, we at the start of the fixed part in the header.
+	// Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
+	off += 2 + 2 + 4
+	if off+2 > l {
+		return false
+	}
+	//off+1 is the end of the header, 'end' is the end of the rr
+	//so 'end' - 'off+2' is the length of the rdata
+	rdatalen := end - (off + 2)
+	if rdatalen > 0xFFFF {
+		return false
+	}
+	msg[off], msg[off+1] = packUint16(uint16(rdatalen))
+	return true
+}
diff --git a/vendor/github.com/miekg/dns/sanitize.go b/vendor/github.com/miekg/dns/sanitize.go
new file mode 100644
index 0000000000000000000000000000000000000000..b489f3f050bfa9b2d3a0a1bd1928660e65c56d39
--- /dev/null
+++ b/vendor/github.com/miekg/dns/sanitize.go
@@ -0,0 +1,84 @@
+package dns
+
+// 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
+// rrs.
+// m is used to store the RRs temporay. If it is nil a new map will be allocated.
+func Dedup(rrs []RR, m map[string]RR) []RR {
+	if m == nil {
+		m = make(map[string]RR)
+	}
+	// Save the keys, so we don't have to call normalizedString twice.
+	keys := make([]*string, 0, len(rrs))
+
+	for _, r := range rrs {
+		key := normalizedString(r)
+		keys = append(keys, &key)
+		if _, ok := m[key]; ok {
+			// Shortest TTL wins.
+			if m[key].Header().Ttl > r.Header().Ttl {
+				m[key].Header().Ttl = r.Header().Ttl
+			}
+			continue
+		}
+
+		m[key] = r
+	}
+	// If the length of the result map equals the amount of RRs we got,
+	// it means they were all different. We can then just return the original rrset.
+	if len(m) == len(rrs) {
+		return rrs
+	}
+
+	j := 0
+	for i, r := range rrs {
+		// If keys[i] lives in the map, we should copy and remove it.
+		if _, ok := m[*keys[i]]; ok {
+			delete(m, *keys[i])
+			rrs[j] = r
+			j++
+		}
+
+		if len(m) == 0 {
+			break
+		}
+	}
+
+	return rrs[:j]
+}
+
+// normalizedString returns a normalized string from r. The TTL
+// is removed and the domain name is lowercased. We go from this:
+// DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to:
+// lowercasename<TAB>CLASS<TAB>TYPE...
+func normalizedString(r RR) string {
+	// A string Go DNS makes has: domainname<TAB>TTL<TAB>...
+	b := []byte(r.String())
+
+	// find the first non-escaped tab, then another, so we capture where the TTL lives.
+	esc := false
+	ttlStart, ttlEnd := 0, 0
+	for i := 0; i < len(b) && ttlEnd == 0; i++ {
+		switch {
+		case b[i] == '\\':
+			esc = !esc
+		case b[i] == '\t' && !esc:
+			if ttlStart == 0 {
+				ttlStart = i
+				continue
+			}
+			if ttlEnd == 0 {
+				ttlEnd = i
+			}
+		case b[i] >= 'A' && b[i] <= 'Z' && !esc:
+			b[i] += 32
+		default:
+			esc = false
+		}
+	}
+
+	// remove TTL.
+	copy(b[ttlStart:], b[ttlEnd:])
+	cut := ttlEnd - ttlStart
+	return string(b[:len(b)-cut])
+}
diff --git a/vendor/github.com/miekg/dns/scanner.go b/vendor/github.com/miekg/dns/scanner.go
new file mode 100644
index 0000000000000000000000000000000000000000..c29bc2f388e84c292ceb3ec58431c4f03abf3b6b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/scanner.go
@@ -0,0 +1,43 @@
+package dns
+
+// Implement a simple scanner, return a byte stream from an io reader.
+
+import (
+	"bufio"
+	"io"
+	"text/scanner"
+)
+
+type scan struct {
+	src      *bufio.Reader
+	position scanner.Position
+	eof      bool // Have we just seen a eof
+}
+
+func scanInit(r io.Reader) *scan {
+	s := new(scan)
+	s.src = bufio.NewReader(r)
+	s.position.Line = 1
+	return s
+}
+
+// tokenText returns the next byte from the input
+func (s *scan) tokenText() (byte, error) {
+	c, err := s.src.ReadByte()
+	if err != nil {
+		return c, err
+	}
+	// delay the newline handling until the next token is delivered,
+	// fixes off-by-one errors when reporting a parse error.
+	if s.eof == true {
+		s.position.Line++
+		s.position.Column = 0
+		s.eof = false
+	}
+	if c == '\n' {
+		s.eof = true
+		return c, nil
+	}
+	s.position.Column++
+	return c, nil
+}
diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..48584f5ba0d2fb04dae3d83449342c206beb1894
--- /dev/null
+++ b/vendor/github.com/miekg/dns/server.go
@@ -0,0 +1,717 @@
+// DNS server implementation.
+
+package dns
+
+import (
+	"bytes"
+	"io"
+	"net"
+	"sync"
+	"time"
+)
+
+// Maximum number of TCP queries before we close the socket.
+const maxTCPQueries = 128
+
+// Handler is implemented by any value that implements ServeDNS.
+type Handler interface {
+	ServeDNS(w ResponseWriter, r *Msg)
+}
+
+// A ResponseWriter interface is used by an DNS handler to
+// construct an DNS response.
+type ResponseWriter interface {
+	// LocalAddr returns the net.Addr of the server
+	LocalAddr() net.Addr
+	// RemoteAddr returns the net.Addr of the client that sent the current request.
+	RemoteAddr() net.Addr
+	// WriteMsg writes a reply back to the client.
+	WriteMsg(*Msg) error
+	// Write writes a raw buffer back to the client.
+	Write([]byte) (int, error)
+	// Close closes the connection.
+	Close() error
+	// TsigStatus returns the status of the Tsig.
+	TsigStatus() error
+	// TsigTimersOnly sets the tsig timers only boolean.
+	TsigTimersOnly(bool)
+	// Hijack lets the caller take over the connection.
+	// After a call to Hijack(), the DNS package will not do anything with the connection.
+	Hijack()
+}
+
+type response struct {
+	hijacked       bool // connection has been hijacked by handler
+	tsigStatus     error
+	tsigTimersOnly bool
+	tsigRequestMAC string
+	tsigSecret     map[string]string // the tsig secrets
+	udp            *net.UDPConn      // i/o connection if UDP was used
+	tcp            *net.TCPConn      // i/o connection if TCP was used
+	udpSession     *SessionUDP       // oob data to get egress interface right
+	remoteAddr     net.Addr          // address of the client
+	writer         Writer            // writer to output the raw DNS bits
+}
+
+// ServeMux is an DNS request multiplexer. It matches the
+// zone name of each incoming request against a list of
+// registered patterns add calls the handler for the pattern
+// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
+// that queries for the DS record are redirected to the parent zone (if that
+// is also registered), otherwise the child gets the query.
+// ServeMux is also safe for concurrent access from multiple goroutines.
+type ServeMux struct {
+	z map[string]Handler
+	m *sync.RWMutex
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as DNS handlers.  If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Msg)
+
+// ServeDNS calls f(w, r).
+func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
+	f(w, r)
+}
+
+// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
+func HandleFailed(w ResponseWriter, r *Msg) {
+	m := new(Msg)
+	m.SetRcode(r, RcodeServerFailure)
+	// does not matter if this write fails
+	w.WriteMsg(m)
+}
+
+func failedHandler() Handler { return HandlerFunc(HandleFailed) }
+
+// ListenAndServe Starts a server on addresss and network speficied. Invoke handler
+// for incoming queries.
+func ListenAndServe(addr string, network string, handler Handler) error {
+	server := &Server{Addr: addr, Net: network, Handler: handler}
+	return server.ListenAndServe()
+}
+
+// ActivateAndServe activates a server with a listener from systemd,
+// l and p should not both be non-nil.
+// If both l and p are not nil only p will be used.
+// Invoke handler for incoming queries.
+func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error {
+	server := &Server{Listener: l, PacketConn: p, Handler: handler}
+	return server.ActivateAndServe()
+}
+
+func (mux *ServeMux) match(q string, t uint16) Handler {
+	mux.m.RLock()
+	defer mux.m.RUnlock()
+	var handler Handler
+	b := make([]byte, len(q)) // worst case, one label of length q
+	off := 0
+	end := false
+	for {
+		l := len(q[off:])
+		for i := 0; i < l; i++ {
+			b[i] = q[off+i]
+			if b[i] >= 'A' && b[i] <= 'Z' {
+				b[i] |= ('a' - 'A')
+			}
+		}
+		if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key
+			if t != TypeDS {
+				return h
+			}
+			// Continue for DS to see if we have a parent too, if so delegeate to the parent
+			handler = h
+		}
+		off, end = NextLabel(q, off)
+		if end {
+			break
+		}
+	}
+	// Wildcard match, if we have found nothing try the root zone as a last resort.
+	if h, ok := mux.z["."]; ok {
+		return h
+	}
+	return handler
+}
+
+// Handle adds a handler to the ServeMux for pattern.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+	if pattern == "" {
+		panic("dns: invalid pattern " + pattern)
+	}
+	mux.m.Lock()
+	mux.z[Fqdn(pattern)] = handler
+	mux.m.Unlock()
+}
+
+// HandleFunc adds a handler function to the ServeMux for pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+	mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
+func (mux *ServeMux) HandleRemove(pattern string) {
+	if pattern == "" {
+		panic("dns: invalid pattern " + pattern)
+	}
+	mux.m.Lock()
+	delete(mux.z, Fqdn(pattern))
+	mux.m.Unlock()
+}
+
+// ServeDNS dispatches the request to the handler whose
+// pattern most closely matches the request message. If DefaultServeMux
+// is used the correct thing for DS queries is done: a possible parent
+// is sought.
+// If no handler is found a standard SERVFAIL message is returned
+// If the request message does not have exactly one question in the
+// question section a SERVFAIL is returned, unlesss Unsafe is true.
+func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) {
+	var h Handler
+	if len(request.Question) < 1 { // allow more than one question
+		h = failedHandler()
+	} else {
+		if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil {
+			h = failedHandler()
+		}
+	}
+	h.ServeDNS(w, request)
+}
+
+// Handle registers the handler with the given pattern
+// in the DefaultServeMux. The documentation for
+// ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleRemove deregisters the handle with the given pattern
+// in the DefaultServeMux.
+func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
+
+// HandleFunc registers the handler function with the given pattern
+// in the DefaultServeMux.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+	DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// Writer writes raw DNS messages; each call to Write should send an entire message.
+type Writer interface {
+	io.Writer
+}
+
+// Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message.
+type Reader interface {
+	// ReadTCP reads a raw message from a TCP connection. Implementations may alter
+	// connection properties, for example the read-deadline.
+	ReadTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error)
+	// ReadUDP reads a raw message from a UDP connection. Implementations may alter
+	// connection properties, for example the read-deadline.
+	ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
+}
+
+// defaultReader is an adapter for the Server struct that implements the Reader interface
+// using the readTCP and readUDP func of the embedded Server.
+type defaultReader struct {
+	*Server
+}
+
+func (dr *defaultReader) ReadTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) {
+	return dr.readTCP(conn, timeout)
+}
+
+func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+	return dr.readUDP(conn, timeout)
+}
+
+// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
+// Implementations should never return a nil Reader.
+type DecorateReader func(Reader) Reader
+
+// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
+// Implementations should never return a nil Writer.
+type DecorateWriter func(Writer) Writer
+
+// A Server defines parameters for running an DNS server.
+type Server struct {
+	// Address to listen on, ":dns" if empty.
+	Addr string
+	// if "tcp" it will invoke a TCP listener, otherwise an UDP one.
+	Net string
+	// TCP Listener to use, this is to aid in systemd's socket activation.
+	Listener net.Listener
+	// UDP "Listener" to use, this is to aid in systemd's socket activation.
+	PacketConn net.PacketConn
+	// Handler to invoke, dns.DefaultServeMux if nil.
+	Handler Handler
+	// Default buffer size to use to read incoming UDP messages. If not set
+	// it defaults to MinMsgSize (512 B).
+	UDPSize int
+	// The net.Conn.SetReadTimeout value for new connections, defaults to 2 * time.Second.
+	ReadTimeout time.Duration
+	// The net.Conn.SetWriteTimeout value for new connections, defaults to 2 * time.Second.
+	WriteTimeout time.Duration
+	// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
+	IdleTimeout func() time.Duration
+	// Secret(s) for Tsig map[<zonename>]<base64 secret>.
+	TsigSecret map[string]string
+	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
+	// the handler. It will specfically not check if the query has the QR bit not set.
+	Unsafe bool
+	// If NotifyStartedFunc is set it is called once the server has started listening.
+	NotifyStartedFunc func()
+	// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
+	DecorateReader DecorateReader
+	// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
+	DecorateWriter DecorateWriter
+
+	// For graceful shutdown.
+	stopUDP chan bool
+	stopTCP chan bool
+	wgUDP   sync.WaitGroup
+	wgTCP   sync.WaitGroup
+
+	// make start/shutdown not racy
+	lock    sync.Mutex
+	started bool
+}
+
+// ListenAndServe starts a nameserver on the configured address in *Server.
+func (srv *Server) ListenAndServe() error {
+	srv.lock.Lock()
+	// We can't use defer() becasue serveTCP/serveUDP don't return.
+	if srv.started {
+		srv.lock.Unlock()
+		return &Error{err: "server already started"}
+	}
+	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
+	srv.started = true
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":domain"
+	}
+	if srv.UDPSize == 0 {
+		srv.UDPSize = MinMsgSize
+	}
+	switch srv.Net {
+	case "tcp", "tcp4", "tcp6":
+		a, e := net.ResolveTCPAddr(srv.Net, addr)
+		if e != nil {
+			srv.lock.Unlock()
+			srv.started = false
+			return e
+		}
+		l, e := net.ListenTCP(srv.Net, a)
+		if e != nil {
+			srv.lock.Unlock()
+			srv.started = false
+			return e
+		}
+		srv.Listener = l
+		srv.lock.Unlock()
+		return srv.serveTCP(l)
+	case "udp", "udp4", "udp6":
+		a, e := net.ResolveUDPAddr(srv.Net, addr)
+		if e != nil {
+			srv.lock.Unlock()
+			srv.started = false
+			return e
+		}
+		l, e := net.ListenUDP(srv.Net, a)
+		if e != nil {
+			srv.lock.Unlock()
+			srv.started = false
+			return e
+		}
+		if e := setUDPSocketOptions(l); e != nil {
+			srv.lock.Unlock()
+			srv.started = false
+			return e
+		}
+		srv.PacketConn = l
+		srv.lock.Unlock()
+		return srv.serveUDP(l)
+	}
+	srv.lock.Unlock()
+	srv.started = false
+	return &Error{err: "bad network"}
+}
+
+// ActivateAndServe starts a nameserver with the PacketConn or Listener
+// configured in *Server. Its main use is to start a server from systemd.
+func (srv *Server) ActivateAndServe() error {
+	srv.lock.Lock()
+	if srv.started {
+		srv.lock.Unlock()
+		return &Error{err: "server already started"}
+	}
+	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
+	srv.started = true
+	pConn := srv.PacketConn
+	l := srv.Listener
+	if pConn != nil {
+		if srv.UDPSize == 0 {
+			srv.UDPSize = MinMsgSize
+		}
+		if t, ok := pConn.(*net.UDPConn); ok {
+			if e := setUDPSocketOptions(t); e != nil {
+				srv.lock.Unlock()
+				srv.started = false
+				return e
+			}
+			srv.lock.Unlock()
+			return srv.serveUDP(t)
+		}
+	}
+	if l != nil {
+		if t, ok := l.(*net.TCPListener); ok {
+			srv.lock.Unlock()
+			return srv.serveTCP(t)
+		}
+	}
+	srv.lock.Unlock()
+	srv.started = false
+	return &Error{err: "bad listeners"}
+}
+
+// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
+// ActivateAndServe will return. All in progress queries are completed before the server
+// is taken down. If the Shutdown is taking longer than the reading timeout an error
+// is returned.
+func (srv *Server) Shutdown() error {
+	srv.lock.Lock()
+	if !srv.started {
+		srv.lock.Unlock()
+		return &Error{err: "server not started"}
+	}
+	srv.started = false
+	net, addr := srv.Net, srv.Addr
+	switch {
+	case srv.Listener != nil:
+		a := srv.Listener.Addr()
+		net, addr = a.Network(), a.String()
+	case srv.PacketConn != nil:
+		a := srv.PacketConn.LocalAddr()
+		net, addr = a.Network(), a.String()
+	}
+	srv.lock.Unlock()
+
+	fin := make(chan bool)
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		go func() {
+			srv.stopTCP <- true
+			srv.wgTCP.Wait()
+			fin <- true
+		}()
+
+	case "udp", "udp4", "udp6":
+		go func() {
+			srv.stopUDP <- true
+			srv.wgUDP.Wait()
+			fin <- true
+		}()
+	}
+
+	c := &Client{Net: net}
+	go c.Exchange(new(Msg), addr) // extra query to help ReadXXX loop to pass
+
+	select {
+	case <-time.After(srv.getReadTimeout()):
+		return &Error{err: "server shutdown is pending"}
+	case <-fin:
+		return nil
+	}
+}
+
+// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
+func (srv *Server) getReadTimeout() time.Duration {
+	rtimeout := dnsTimeout
+	if srv.ReadTimeout != 0 {
+		rtimeout = srv.ReadTimeout
+	}
+	return rtimeout
+}
+
+// serveTCP starts a TCP listener for the server.
+// Each request is handled in a separate goroutine.
+func (srv *Server) serveTCP(l *net.TCPListener) error {
+	defer l.Close()
+
+	if srv.NotifyStartedFunc != nil {
+		srv.NotifyStartedFunc()
+	}
+
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
+
+	handler := srv.Handler
+	if handler == nil {
+		handler = DefaultServeMux
+	}
+	rtimeout := srv.getReadTimeout()
+	// deadline is not used here
+	for {
+		rw, e := l.AcceptTCP()
+		if e != nil {
+			continue
+		}
+		m, e := reader.ReadTCP(rw, rtimeout)
+		select {
+		case <-srv.stopTCP:
+			return nil
+		default:
+		}
+		if e != nil {
+			continue
+		}
+		srv.wgTCP.Add(1)
+		go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
+	}
+}
+
+// serveUDP starts a UDP listener for the server.
+// Each request is handled in a separate goroutine.
+func (srv *Server) serveUDP(l *net.UDPConn) error {
+	defer l.Close()
+
+	if srv.NotifyStartedFunc != nil {
+		srv.NotifyStartedFunc()
+	}
+
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
+
+	handler := srv.Handler
+	if handler == nil {
+		handler = DefaultServeMux
+	}
+	rtimeout := srv.getReadTimeout()
+	// deadline is not used here
+	for {
+		m, s, e := reader.ReadUDP(l, rtimeout)
+		select {
+		case <-srv.stopUDP:
+			return nil
+		default:
+		}
+		if e != nil {
+			continue
+		}
+		srv.wgUDP.Add(1)
+		go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
+	}
+}
+
+// Serve a new connection.
+func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t *net.TCPConn) {
+	w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
+	if srv.DecorateWriter != nil {
+		w.writer = srv.DecorateWriter(w)
+	} else {
+		w.writer = w
+	}
+
+	q := 0 // counter for the amount of TCP queries we get
+
+	defer func() {
+		if u != nil {
+			srv.wgUDP.Done()
+		}
+		if t != nil {
+			srv.wgTCP.Done()
+		}
+	}()
+
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
+Redo:
+	req := new(Msg)
+	err := req.Unpack(m)
+	if err != nil { // Send a FormatError back
+		x := new(Msg)
+		x.SetRcodeFormatError(req)
+		w.WriteMsg(x)
+		goto Exit
+	}
+	if !srv.Unsafe && req.Response {
+		goto Exit
+	}
+
+	w.tsigStatus = nil
+	if w.tsigSecret != nil {
+		if t := req.IsTsig(); t != nil {
+			secret := t.Hdr.Name
+			if _, ok := w.tsigSecret[secret]; !ok {
+				w.tsigStatus = ErrKeyAlg
+			}
+			w.tsigStatus = TsigVerify(m, w.tsigSecret[secret], "", false)
+			w.tsigTimersOnly = false
+			w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
+		}
+	}
+	h.ServeDNS(w, req) // Writes back to the client
+
+Exit:
+	// TODO(miek): make this number configurable?
+	if q > maxTCPQueries { // close socket after this many queries
+		w.Close()
+		return
+	}
+
+	if w.hijacked {
+		return // client calls Close()
+	}
+	if u != nil { // UDP, "close" and return
+		w.Close()
+		return
+	}
+	idleTimeout := tcpIdleTimeout
+	if srv.IdleTimeout != nil {
+		idleTimeout = srv.IdleTimeout()
+	}
+	m, e := reader.ReadTCP(w.tcp, idleTimeout)
+	if e == nil {
+		q++
+		goto Redo
+	}
+	w.Close()
+	return
+}
+
+func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) {
+	conn.SetReadDeadline(time.Now().Add(timeout))
+	l := make([]byte, 2)
+	n, err := conn.Read(l)
+	if err != nil || n != 2 {
+		if err != nil {
+			return nil, err
+		}
+		return nil, ErrShortRead
+	}
+	length, _ := unpackUint16(l, 0)
+	if length == 0 {
+		return nil, ErrShortRead
+	}
+	m := make([]byte, int(length))
+	n, err = conn.Read(m[:int(length)])
+	if err != nil || n == 0 {
+		if err != nil {
+			return nil, err
+		}
+		return nil, ErrShortRead
+	}
+	i := n
+	for i < int(length) {
+		j, err := conn.Read(m[i:int(length)])
+		if err != nil {
+			return nil, err
+		}
+		i += j
+	}
+	n = i
+	m = m[:n]
+	return m, nil
+}
+
+func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+	conn.SetReadDeadline(time.Now().Add(timeout))
+	m := make([]byte, srv.UDPSize)
+	n, s, e := ReadFromSessionUDP(conn, m)
+	if e != nil || n == 0 {
+		if e != nil {
+			return nil, nil, e
+		}
+		return nil, nil, ErrShortRead
+	}
+	m = m[:n]
+	return m, s, nil
+}
+
+// WriteMsg implements the ResponseWriter.WriteMsg method.
+func (w *response) WriteMsg(m *Msg) (err error) {
+	var data []byte
+	if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
+		if t := m.IsTsig(); t != nil {
+			data, w.tsigRequestMAC, err = TsigGenerate(m, w.tsigSecret[t.Hdr.Name], w.tsigRequestMAC, w.tsigTimersOnly)
+			if err != nil {
+				return err
+			}
+			_, err = w.writer.Write(data)
+			return err
+		}
+	}
+	data, err = m.Pack()
+	if err != nil {
+		return err
+	}
+	_, err = w.writer.Write(data)
+	return err
+}
+
+// Write implements the ResponseWriter.Write method.
+func (w *response) Write(m []byte) (int, error) {
+	switch {
+	case w.udp != nil:
+		n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
+		return n, err
+	case w.tcp != nil:
+		lm := len(m)
+		if lm < 2 {
+			return 0, io.ErrShortBuffer
+		}
+		if lm > MaxMsgSize {
+			return 0, &Error{err: "message too large"}
+		}
+		l := make([]byte, 2, 2+lm)
+		l[0], l[1] = packUint16(uint16(lm))
+		m = append(l, m...)
+
+		n, err := io.Copy(w.tcp, bytes.NewReader(m))
+		return int(n), err
+	}
+	panic("not reached")
+}
+
+// LocalAddr implements the ResponseWriter.LocalAddr method.
+func (w *response) LocalAddr() net.Addr {
+	if w.tcp != nil {
+		return w.tcp.LocalAddr()
+	}
+	return w.udp.LocalAddr()
+}
+
+// RemoteAddr implements the ResponseWriter.RemoteAddr method.
+func (w *response) RemoteAddr() net.Addr { return w.remoteAddr }
+
+// TsigStatus implements the ResponseWriter.TsigStatus method.
+func (w *response) TsigStatus() error { return w.tsigStatus }
+
+// TsigTimersOnly implements the ResponseWriter.TsigTimersOnly method.
+func (w *response) TsigTimersOnly(b bool) { w.tsigTimersOnly = b }
+
+// Hijack implements the ResponseWriter.Hijack method.
+func (w *response) Hijack() { w.hijacked = true }
+
+// Close implements the ResponseWriter.Close method
+func (w *response) Close() error {
+	// Can't close the udp conn, as that is actually the listener.
+	if w.tcp != nil {
+		e := w.tcp.Close()
+		w.tcp = nil
+		return e
+	}
+	return nil
+}
diff --git a/vendor/github.com/miekg/dns/sig0.go b/vendor/github.com/miekg/dns/sig0.go
new file mode 100644
index 0000000000000000000000000000000000000000..0fccddbc150ad6ce2c18854989c0a087d4bbef4a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/sig0.go
@@ -0,0 +1,216 @@
+package dns
+
+import (
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"math/big"
+	"strings"
+	"time"
+)
+
+// Sign signs a dns.Msg. It fills the signature with the appropriate data.
+// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
+// and Expiration set.
+func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
+	if k == nil {
+		return nil, ErrPrivKey
+	}
+	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+		return nil, ErrKey
+	}
+	rr.Header().Rrtype = TypeSIG
+	rr.Header().Class = ClassANY
+	rr.Header().Ttl = 0
+	rr.Header().Name = "."
+	rr.OrigTtl = 0
+	rr.TypeCovered = 0
+	rr.Labels = 0
+
+	buf := make([]byte, m.Len()+rr.len())
+	mbuf, err := m.PackBuffer(buf)
+	if err != nil {
+		return nil, err
+	}
+	if &buf[0] != &mbuf[0] {
+		return nil, ErrBuf
+	}
+	off, err := PackRR(rr, buf, len(mbuf), nil, false)
+	if err != nil {
+		return nil, err
+	}
+	buf = buf[:off:cap(buf)]
+
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
+		return nil, ErrAlg
+	}
+
+	hasher := hash.New()
+	// Write SIG rdata
+	hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
+	// Write message
+	hasher.Write(buf[:len(mbuf)])
+
+	signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
+	if err != nil {
+		return nil, err
+	}
+
+	rr.Signature = toBase64(signature)
+	sig := string(signature)
+
+	buf = append(buf, sig...)
+	if len(buf) > int(^uint16(0)) {
+		return nil, ErrBuf
+	}
+	// Adjust sig data length
+	rdoff := len(mbuf) + 1 + 2 + 2 + 4
+	rdlen, _ := unpackUint16(buf, rdoff)
+	rdlen += uint16(len(sig))
+	buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
+	// Adjust additional count
+	adc, _ := unpackUint16(buf, 10)
+	adc++
+	buf[10], buf[11] = packUint16(adc)
+	return buf, nil
+}
+
+// Verify validates the message buf using the key k.
+// It's assumed that buf is a valid message from which rr was unpacked.
+func (rr *SIG) Verify(k *KEY, buf []byte) error {
+	if k == nil {
+		return ErrKey
+	}
+	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+		return ErrKey
+	}
+
+	var hash crypto.Hash
+	switch rr.Algorithm {
+	case DSA, RSASHA1:
+		hash = crypto.SHA1
+	case RSASHA256, ECDSAP256SHA256:
+		hash = crypto.SHA256
+	case ECDSAP384SHA384:
+		hash = crypto.SHA384
+	case RSASHA512:
+		hash = crypto.SHA512
+	default:
+		return ErrAlg
+	}
+	hasher := hash.New()
+
+	buflen := len(buf)
+	qdc, _ := unpackUint16(buf, 4)
+	anc, _ := unpackUint16(buf, 6)
+	auc, _ := unpackUint16(buf, 8)
+	adc, offset := unpackUint16(buf, 10)
+	var err error
+	for i := uint16(0); i < qdc && offset < buflen; i++ {
+		_, offset, err = UnpackDomainName(buf, offset)
+		if err != nil {
+			return err
+		}
+		// Skip past Type and Class
+		offset += 2 + 2
+	}
+	for i := uint16(1); i < anc+auc+adc && offset < buflen; i++ {
+		_, offset, err = UnpackDomainName(buf, offset)
+		if err != nil {
+			return err
+		}
+		// Skip past Type, Class and TTL
+		offset += 2 + 2 + 4
+		if offset+1 >= buflen {
+			continue
+		}
+		var rdlen uint16
+		rdlen, offset = unpackUint16(buf, offset)
+		offset += int(rdlen)
+	}
+	if offset >= buflen {
+		return &Error{err: "overflowing unpacking signed message"}
+	}
+
+	// offset should be just prior to SIG
+	bodyend := offset
+	// owner name SHOULD be root
+	_, offset, err = UnpackDomainName(buf, offset)
+	if err != nil {
+		return err
+	}
+	// Skip Type, Class, TTL, RDLen
+	offset += 2 + 2 + 4 + 2
+	sigstart := offset
+	// Skip Type Covered, Algorithm, Labels, Original TTL
+	offset += 2 + 1 + 1 + 4
+	if offset+4+4 >= buflen {
+		return &Error{err: "overflow unpacking signed message"}
+	}
+	expire := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
+	offset += 4
+	incept := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
+	offset += 4
+	now := uint32(time.Now().Unix())
+	if now < incept || now > expire {
+		return ErrTime
+	}
+	// Skip key tag
+	offset += 2
+	var signername string
+	signername, offset, err = UnpackDomainName(buf, offset)
+	if err != nil {
+		return err
+	}
+	// If key has come from the DNS name compression might
+	// have mangled the case of the name
+	if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
+		return &Error{err: "signer name doesn't match key name"}
+	}
+	sigend := offset
+	hasher.Write(buf[sigstart:sigend])
+	hasher.Write(buf[:10])
+	hasher.Write([]byte{
+		byte((adc - 1) << 8),
+		byte(adc - 1),
+	})
+	hasher.Write(buf[12:bodyend])
+
+	hashed := hasher.Sum(nil)
+	sig := buf[sigend:]
+	switch k.Algorithm {
+	case DSA:
+		pk := k.publicKeyDSA()
+		sig = sig[1:]
+		r := big.NewInt(0)
+		r.SetBytes(sig[:len(sig)/2])
+		s := big.NewInt(0)
+		s.SetBytes(sig[len(sig)/2:])
+		if pk != nil {
+			if dsa.Verify(pk, hashed, r, s) {
+				return nil
+			}
+			return ErrSig
+		}
+	case RSASHA1, RSASHA256, RSASHA512:
+		pk := k.publicKeyRSA()
+		if pk != nil {
+			return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
+		}
+	case ECDSAP256SHA256, ECDSAP384SHA384:
+		pk := k.publicKeyECDSA()
+		r := big.NewInt(0)
+		r.SetBytes(sig[:len(sig)/2])
+		s := big.NewInt(0)
+		s.SetBytes(sig[len(sig)/2:])
+		if pk != nil {
+			if ecdsa.Verify(pk, hashed, r, s) {
+				return nil
+			}
+			return ErrSig
+		}
+	}
+	return ErrKeyAlg
+}
diff --git a/vendor/github.com/miekg/dns/singleinflight.go b/vendor/github.com/miekg/dns/singleinflight.go
new file mode 100644
index 0000000000000000000000000000000000000000..9573c7d0b8c25225662ee7909af985cc7bf607e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/singleinflight.go
@@ -0,0 +1,57 @@
+// 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.
+
+// Adapted for dns package usage by Miek Gieben.
+
+package dns
+
+import "sync"
+import "time"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+	wg   sync.WaitGroup
+	val  *Msg
+	rtt  time.Duration
+	err  error
+	dups int
+}
+
+// singleflight represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type singleflight struct {
+	sync.Mutex                  // protects m
+	m          map[string]*call // lazily initialized
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) {
+	g.Lock()
+	if g.m == nil {
+		g.m = make(map[string]*call)
+	}
+	if c, ok := g.m[key]; ok {
+		c.dups++
+		g.Unlock()
+		c.wg.Wait()
+		return c.val, c.rtt, c.err, true
+	}
+	c := new(call)
+	c.wg.Add(1)
+	g.m[key] = c
+	g.Unlock()
+
+	c.val, c.rtt, c.err = fn()
+	c.wg.Done()
+
+	g.Lock()
+	delete(g.m, key)
+	g.Unlock()
+
+	return c.val, c.rtt, c.err, c.dups > 0
+}
diff --git a/vendor/github.com/miekg/dns/tlsa.go b/vendor/github.com/miekg/dns/tlsa.go
new file mode 100644
index 0000000000000000000000000000000000000000..f027787df30b3bf1931ecc473aa678ae89f7f824
--- /dev/null
+++ b/vendor/github.com/miekg/dns/tlsa.go
@@ -0,0 +1,86 @@
+package dns
+
+import (
+	"crypto/sha256"
+	"crypto/sha512"
+	"crypto/x509"
+	"encoding/hex"
+	"errors"
+	"io"
+	"net"
+	"strconv"
+)
+
+// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
+func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
+	switch matchingType {
+	case 0:
+		switch selector {
+		case 0:
+			return hex.EncodeToString(cert.Raw), nil
+		case 1:
+			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
+		}
+	case 1:
+		h := sha256.New()
+		switch selector {
+		case 0:
+			io.WriteString(h, string(cert.Raw))
+			return hex.EncodeToString(h.Sum(nil)), nil
+		case 1:
+			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
+			return hex.EncodeToString(h.Sum(nil)), nil
+		}
+	case 2:
+		h := sha512.New()
+		switch selector {
+		case 0:
+			io.WriteString(h, string(cert.Raw))
+			return hex.EncodeToString(h.Sum(nil)), nil
+		case 1:
+			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
+			return hex.EncodeToString(h.Sum(nil)), nil
+		}
+	}
+	return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
+}
+
+// Sign creates a TLSA record from an SSL certificate.
+func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
+	r.Hdr.Rrtype = TypeTLSA
+	r.Usage = uint8(usage)
+	r.Selector = uint8(selector)
+	r.MatchingType = uint8(matchingType)
+
+	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Verify verifies a TLSA record against an SSL certificate. If it is OK
+// a nil error is returned.
+func (r *TLSA) Verify(cert *x509.Certificate) error {
+	c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
+	if err != nil {
+		return err // Not also ErrSig?
+	}
+	if r.Certificate == c {
+		return nil
+	}
+	return ErrSig // ErrSig, really?
+}
+
+// TLSAName returns the ownername of a TLSA resource record as per the
+// rules specified in RFC 6698, Section 3.
+func TLSAName(name, service, network string) (string, error) {
+	if !IsFqdn(name) {
+		return "", ErrFqdn
+	}
+	p, e := net.LookupPort(network, service)
+	if e != nil {
+		return "", e
+	}
+	return "_" + strconv.Itoa(p) + "_" + network + "." + name, nil
+}
diff --git a/vendor/github.com/miekg/dns/tsig.go b/vendor/github.com/miekg/dns/tsig.go
new file mode 100644
index 0000000000000000000000000000000000000000..d7bc25056c6c950b0ab63764eb558e7331fbb9f9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/tsig.go
@@ -0,0 +1,333 @@
+package dns
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"encoding/hex"
+	"hash"
+	"io"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// HMAC hashing codes. These are transmitted as domain names.
+const (
+	HmacMD5    = "hmac-md5.sig-alg.reg.int."
+	HmacSHA1   = "hmac-sha1."
+	HmacSHA256 = "hmac-sha256."
+	HmacSHA512 = "hmac-sha512."
+)
+
+// TSIG is the RR the holds the transaction signature of a message.
+// See RFC 2845 and RFC 4635.
+type TSIG struct {
+	Hdr        RR_Header
+	Algorithm  string `dns:"domain-name"`
+	TimeSigned uint64 `dns:"uint48"`
+	Fudge      uint16
+	MACSize    uint16
+	MAC        string `dns:"size-hex"`
+	OrigId     uint16
+	Error      uint16
+	OtherLen   uint16
+	OtherData  string `dns:"size-hex"`
+}
+
+func (rr *TSIG) Header() *RR_Header {
+	return &rr.Hdr
+}
+
+// TSIG has no official presentation format, but this will suffice.
+
+func (rr *TSIG) String() string {
+	s := "\n;; TSIG PSEUDOSECTION:\n"
+	s += rr.Hdr.String() +
+		" " + rr.Algorithm +
+		" " + tsigTimeToString(rr.TimeSigned) +
+		" " + strconv.Itoa(int(rr.Fudge)) +
+		" " + strconv.Itoa(int(rr.MACSize)) +
+		" " + strings.ToUpper(rr.MAC) +
+		" " + strconv.Itoa(int(rr.OrigId)) +
+		" " + strconv.Itoa(int(rr.Error)) + // BIND prints NOERROR
+		" " + strconv.Itoa(int(rr.OtherLen)) +
+		" " + rr.OtherData
+	return s
+}
+
+func (rr *TSIG) len() int {
+	return rr.Hdr.len() + len(rr.Algorithm) + 1 + 6 +
+		4 + len(rr.MAC)/2 + 1 + 6 + len(rr.OtherData)/2 + 1
+}
+
+func (rr *TSIG) copy() RR {
+	return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
+}
+
+// The following values must be put in wireformat, so that the MAC can be calculated.
+// RFC 2845, section 3.4.2. TSIG Variables.
+type tsigWireFmt struct {
+	// From RR_Header
+	Name  string `dns:"domain-name"`
+	Class uint16
+	Ttl   uint32
+	// Rdata of the TSIG
+	Algorithm  string `dns:"domain-name"`
+	TimeSigned uint64 `dns:"uint48"`
+	Fudge      uint16
+	// MACSize, MAC and OrigId excluded
+	Error     uint16
+	OtherLen  uint16
+	OtherData string `dns:"size-hex"`
+}
+
+// If we have the MAC use this type to convert it to wiredata.
+// Section 3.4.3. Request MAC
+type macWireFmt struct {
+	MACSize uint16
+	MAC     string `dns:"size-hex"`
+}
+
+// 3.3. Time values used in TSIG calculations
+type timerWireFmt struct {
+	TimeSigned uint64 `dns:"uint48"`
+	Fudge      uint16
+}
+
+// TsigGenerate fills out the TSIG record attached to the message.
+// The message should contain
+// a "stub" TSIG RR with the algorithm, key name (owner name of the RR),
+// time fudge (defaults to 300 seconds) and the current time
+// The TSIG MAC is saved in that Tsig RR.
+// When TsigGenerate is called for the first time requestMAC is set to the empty string and
+// timersOnly is false.
+// If something goes wrong an error is returned, otherwise it is nil.
+func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
+	if m.IsTsig() == nil {
+		panic("dns: TSIG not last RR in additional")
+	}
+	// If we barf here, the caller is to blame
+	rawsecret, err := fromBase64([]byte(secret))
+	if err != nil {
+		return nil, "", err
+	}
+
+	rr := m.Extra[len(m.Extra)-1].(*TSIG)
+	m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg
+	mbuf, err := m.Pack()
+	if err != nil {
+		return nil, "", err
+	}
+	buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
+
+	t := new(TSIG)
+	var h hash.Hash
+	switch rr.Algorithm {
+	case HmacMD5:
+		h = hmac.New(md5.New, []byte(rawsecret))
+	case HmacSHA1:
+		h = hmac.New(sha1.New, []byte(rawsecret))
+	case HmacSHA256:
+		h = hmac.New(sha256.New, []byte(rawsecret))
+	case HmacSHA512:
+		h = hmac.New(sha512.New, []byte(rawsecret))
+	default:
+		return nil, "", ErrKeyAlg
+	}
+	io.WriteString(h, string(buf))
+	t.MAC = hex.EncodeToString(h.Sum(nil))
+	t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
+
+	t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0}
+	t.Fudge = rr.Fudge
+	t.TimeSigned = rr.TimeSigned
+	t.Algorithm = rr.Algorithm
+	t.OrigId = m.Id
+
+	tbuf := make([]byte, t.len())
+	if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
+		tbuf = tbuf[:off] // reset to actual size used
+	} else {
+		return nil, "", err
+	}
+	mbuf = append(mbuf, tbuf...)
+	rawSetExtraLen(mbuf, uint16(len(m.Extra)+1))
+	return mbuf, t.MAC, nil
+}
+
+// TsigVerify verifies the TSIG on a message.
+// If the signature does not validate err contains the
+// error, otherwise it is nil.
+func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
+	rawsecret, err := fromBase64([]byte(secret))
+	if err != nil {
+		return err
+	}
+	// Strip the TSIG from the incoming msg
+	stripped, tsig, err := stripTsig(msg)
+	if err != nil {
+		return err
+	}
+
+	msgMAC, err := hex.DecodeString(tsig.MAC)
+	if err != nil {
+		return err
+	}
+
+	buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
+
+	// Fudge factor works both ways. A message can arrive before it was signed because
+	// of clock skew.
+	now := uint64(time.Now().Unix())
+	ti := now - tsig.TimeSigned
+	if now < tsig.TimeSigned {
+		ti = tsig.TimeSigned - now
+	}
+	if uint64(tsig.Fudge) < ti {
+		return ErrTime
+	}
+
+	var h hash.Hash
+	switch tsig.Algorithm {
+	case HmacMD5:
+		h = hmac.New(md5.New, rawsecret)
+	case HmacSHA1:
+		h = hmac.New(sha1.New, rawsecret)
+	case HmacSHA256:
+		h = hmac.New(sha256.New, rawsecret)
+	case HmacSHA512:
+		h = hmac.New(sha512.New, rawsecret)
+	default:
+		return ErrKeyAlg
+	}
+	h.Write(buf)
+	if !hmac.Equal(h.Sum(nil), msgMAC) {
+		return ErrSig
+	}
+	return nil
+}
+
+// Create a wiredata buffer for the MAC calculation.
+func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []byte {
+	var buf []byte
+	if rr.TimeSigned == 0 {
+		rr.TimeSigned = uint64(time.Now().Unix())
+	}
+	if rr.Fudge == 0 {
+		rr.Fudge = 300 // Standard (RFC) default.
+	}
+
+	if requestMAC != "" {
+		m := new(macWireFmt)
+		m.MACSize = uint16(len(requestMAC) / 2)
+		m.MAC = requestMAC
+		buf = make([]byte, len(requestMAC)) // long enough
+		n, _ := PackStruct(m, buf, 0)
+		buf = buf[:n]
+	}
+
+	tsigvar := make([]byte, DefaultMsgSize)
+	if timersOnly {
+		tsig := new(timerWireFmt)
+		tsig.TimeSigned = rr.TimeSigned
+		tsig.Fudge = rr.Fudge
+		n, _ := PackStruct(tsig, tsigvar, 0)
+		tsigvar = tsigvar[:n]
+	} else {
+		tsig := new(tsigWireFmt)
+		tsig.Name = strings.ToLower(rr.Hdr.Name)
+		tsig.Class = ClassANY
+		tsig.Ttl = rr.Hdr.Ttl
+		tsig.Algorithm = strings.ToLower(rr.Algorithm)
+		tsig.TimeSigned = rr.TimeSigned
+		tsig.Fudge = rr.Fudge
+		tsig.Error = rr.Error
+		tsig.OtherLen = rr.OtherLen
+		tsig.OtherData = rr.OtherData
+		n, _ := PackStruct(tsig, tsigvar, 0)
+		tsigvar = tsigvar[:n]
+	}
+
+	if requestMAC != "" {
+		x := append(buf, msgbuf...)
+		buf = append(x, tsigvar...)
+	} else {
+		buf = append(msgbuf, tsigvar...)
+	}
+	return buf
+}
+
+// Strip the TSIG from the raw message.
+func stripTsig(msg []byte) ([]byte, *TSIG, error) {
+	// Copied from msg.go's Unpack()
+	// Header.
+	var dh Header
+	var err error
+	dns := new(Msg)
+	rr := new(TSIG)
+	off := 0
+	tsigoff := 0
+	if off, err = UnpackStruct(&dh, msg, off); err != nil {
+		return nil, nil, err
+	}
+	if dh.Arcount == 0 {
+		return nil, nil, ErrNoSig
+	}
+	// Rcode, see msg.go Unpack()
+	if int(dh.Bits&0xF) == RcodeNotAuth {
+		return nil, nil, ErrAuth
+	}
+
+	// Arrays.
+	dns.Question = make([]Question, dh.Qdcount)
+	dns.Answer = make([]RR, dh.Ancount)
+	dns.Ns = make([]RR, dh.Nscount)
+	dns.Extra = make([]RR, dh.Arcount)
+
+	for i := 0; i < len(dns.Question); i++ {
+		off, err = UnpackStruct(&dns.Question[i], msg, off)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	for i := 0; i < len(dns.Answer); i++ {
+		dns.Answer[i], off, err = UnpackRR(msg, off)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	for i := 0; i < len(dns.Ns); i++ {
+		dns.Ns[i], off, err = UnpackRR(msg, off)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	for i := 0; i < len(dns.Extra); i++ {
+		tsigoff = off
+		dns.Extra[i], off, err = UnpackRR(msg, off)
+		if err != nil {
+			return nil, nil, err
+		}
+		if dns.Extra[i].Header().Rrtype == TypeTSIG {
+			rr = dns.Extra[i].(*TSIG)
+			// Adjust Arcount.
+			arcount, _ := unpackUint16(msg, 10)
+			msg[10], msg[11] = packUint16(arcount - 1)
+			break
+		}
+	}
+	if rr == nil {
+		return nil, nil, ErrNoSig
+	}
+	return msg[:tsigoff], rr, nil
+}
+
+// Translate the TSIG time signed into a date. There is no
+// need for RFC1982 calculations as this date is 48 bits.
+func tsigTimeToString(t uint64) string {
+	ti := time.Unix(int64(t), 0).UTC()
+	return ti.Format("20060102150405")
+}
diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go
new file mode 100644
index 0000000000000000000000000000000000000000..55a50b811df9325b5fe5fc284051585119912ba7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/types.go
@@ -0,0 +1,1741 @@
+package dns
+
+import (
+	"encoding/base64"
+	"fmt"
+	"net"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type (
+	// Type is a DNS type.
+	Type uint16
+	// Class is a DNS class.
+	Class uint16
+	// Name is a DNS domain name.
+	Name string
+)
+
+// Packet formats
+
+// Wire constants and supported types.
+const (
+	// valid RR_Header.Rrtype and Question.qtype
+
+	TypeNone       uint16 = 0
+	TypeA          uint16 = 1
+	TypeNS         uint16 = 2
+	TypeMD         uint16 = 3
+	TypeMF         uint16 = 4
+	TypeCNAME      uint16 = 5
+	TypeSOA        uint16 = 6
+	TypeMB         uint16 = 7
+	TypeMG         uint16 = 8
+	TypeMR         uint16 = 9
+	TypeNULL       uint16 = 10
+	TypeWKS        uint16 = 11
+	TypePTR        uint16 = 12
+	TypeHINFO      uint16 = 13
+	TypeMINFO      uint16 = 14
+	TypeMX         uint16 = 15
+	TypeTXT        uint16 = 16
+	TypeRP         uint16 = 17
+	TypeAFSDB      uint16 = 18
+	TypeX25        uint16 = 19
+	TypeISDN       uint16 = 20
+	TypeRT         uint16 = 21
+	TypeNSAPPTR    uint16 = 23
+	TypeSIG        uint16 = 24
+	TypeKEY        uint16 = 25
+	TypePX         uint16 = 26
+	TypeGPOS       uint16 = 27
+	TypeAAAA       uint16 = 28
+	TypeLOC        uint16 = 29
+	TypeNXT        uint16 = 30
+	TypeEID        uint16 = 31
+	TypeNIMLOC     uint16 = 32
+	TypeSRV        uint16 = 33
+	TypeATMA       uint16 = 34
+	TypeNAPTR      uint16 = 35
+	TypeKX         uint16 = 36
+	TypeCERT       uint16 = 37
+	TypeDNAME      uint16 = 39
+	TypeOPT        uint16 = 41 // EDNS
+	TypeDS         uint16 = 43
+	TypeSSHFP      uint16 = 44
+	TypeIPSECKEY   uint16 = 45
+	TypeRRSIG      uint16 = 46
+	TypeNSEC       uint16 = 47
+	TypeDNSKEY     uint16 = 48
+	TypeDHCID      uint16 = 49
+	TypeNSEC3      uint16 = 50
+	TypeNSEC3PARAM uint16 = 51
+	TypeTLSA       uint16 = 52
+	TypeHIP        uint16 = 55
+	TypeNINFO      uint16 = 56
+	TypeRKEY       uint16 = 57
+	TypeTALINK     uint16 = 58
+	TypeCDS        uint16 = 59
+	TypeCDNSKEY    uint16 = 60
+	TypeOPENPGPKEY uint16 = 61
+	TypeSPF        uint16 = 99
+	TypeUINFO      uint16 = 100
+	TypeUID        uint16 = 101
+	TypeGID        uint16 = 102
+	TypeUNSPEC     uint16 = 103
+	TypeNID        uint16 = 104
+	TypeL32        uint16 = 105
+	TypeL64        uint16 = 106
+	TypeLP         uint16 = 107
+	TypeEUI48      uint16 = 108
+	TypeEUI64      uint16 = 109
+	TypeURI        uint16 = 256
+	TypeCAA        uint16 = 257
+
+	TypeTKEY uint16 = 249
+	TypeTSIG uint16 = 250
+
+	// valid Question.Qtype only
+	TypeIXFR  uint16 = 251
+	TypeAXFR  uint16 = 252
+	TypeMAILB uint16 = 253
+	TypeMAILA uint16 = 254
+	TypeANY   uint16 = 255
+
+	TypeTA       uint16 = 32768
+	TypeDLV      uint16 = 32769
+	TypeReserved uint16 = 65535
+
+	// valid Question.Qclass
+	ClassINET   = 1
+	ClassCSNET  = 2
+	ClassCHAOS  = 3
+	ClassHESIOD = 4
+	ClassNONE   = 254
+	ClassANY    = 255
+
+	// Message Response Codes.
+	RcodeSuccess        = 0
+	RcodeFormatError    = 1
+	RcodeServerFailure  = 2
+	RcodeNameError      = 3
+	RcodeNotImplemented = 4
+	RcodeRefused        = 5
+	RcodeYXDomain       = 6
+	RcodeYXRrset        = 7
+	RcodeNXRrset        = 8
+	RcodeNotAuth        = 9
+	RcodeNotZone        = 10
+	RcodeBadSig         = 16 // TSIG
+	RcodeBadVers        = 16 // EDNS0
+	RcodeBadKey         = 17
+	RcodeBadTime        = 18
+	RcodeBadMode        = 19 // TKEY
+	RcodeBadName        = 20
+	RcodeBadAlg         = 21
+	RcodeBadTrunc       = 22 // TSIG
+
+	// Message Opcodes. There is no 3.
+	OpcodeQuery  = 0
+	OpcodeIQuery = 1
+	OpcodeStatus = 2
+	OpcodeNotify = 4
+	OpcodeUpdate = 5
+)
+
+// Headers is the wire format for the DNS packet header.
+type Header struct {
+	Id                                 uint16
+	Bits                               uint16
+	Qdcount, Ancount, Nscount, Arcount uint16
+}
+
+const (
+	headerSize = 12
+
+	// Header.Bits
+	_QR = 1 << 15 // query/response (response=1)
+	_AA = 1 << 10 // authoritative
+	_TC = 1 << 9  // truncated
+	_RD = 1 << 8  // recursion desired
+	_RA = 1 << 7  // recursion available
+	_Z  = 1 << 6  // Z
+	_AD = 1 << 5  // authticated data
+	_CD = 1 << 4  // checking disabled
+
+	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
+	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
+
+	LOC_HOURS   = 60 * 1000
+	LOC_DEGREES = 60 * LOC_HOURS
+
+	LOC_ALTITUDEBASE = 100000
+)
+
+// Different Certificate Types, see RFC 4398, Section 2.1
+const (
+	CertPKIX = 1 + iota
+	CertSPKI
+	CertPGP
+	CertIPIX
+	CertISPKI
+	CertIPGP
+	CertACPKIX
+	CertIACPKIX
+	CertURI = 253
+	CertOID = 254
+)
+
+// CertTypeToString converts the Cert Type to its string representation.
+// See RFC 4398 and RFC 6944.
+var CertTypeToString = map[uint16]string{
+	CertPKIX:    "PKIX",
+	CertSPKI:    "SPKI",
+	CertPGP:     "PGP",
+	CertIPIX:    "IPIX",
+	CertISPKI:   "ISPKI",
+	CertIPGP:    "IPGP",
+	CertACPKIX:  "ACPKIX",
+	CertIACPKIX: "IACPKIX",
+	CertURI:     "URI",
+	CertOID:     "OID",
+}
+
+// StringToCertType is the reverseof CertTypeToString.
+var StringToCertType = reverseInt16(CertTypeToString)
+
+// Question holds a DNS question. There can be multiple questions in the
+// question section of a message. Usually there is just one.
+type Question struct {
+	Name   string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
+	Qtype  uint16
+	Qclass uint16
+}
+
+func (q *Question) String() (s string) {
+	// prefix with ; (as in dig)
+	s = ";" + sprintName(q.Name) + "\t"
+	s += Class(q.Qclass).String() + "\t"
+	s += " " + Type(q.Qtype).String()
+	return s
+}
+
+func (q *Question) len() int {
+	l := len(q.Name) + 1
+	return l + 4
+}
+
+// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY
+// is named "*" there.
+type ANY struct {
+	Hdr RR_Header
+	// Does not have any rdata
+}
+
+func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
+func (rr *ANY) copy() RR           { return &ANY{*rr.Hdr.copyHeader()} }
+func (rr *ANY) String() string     { return rr.Hdr.String() }
+func (rr *ANY) len() int           { return rr.Hdr.len() }
+
+type CNAME struct {
+	Hdr    RR_Header
+	Target string `dns:"cdomain-name"`
+}
+
+func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
+func (rr *CNAME) copy() RR           { return &CNAME{*rr.Hdr.copyHeader(), sprintName(rr.Target)} }
+func (rr *CNAME) String() string     { return rr.Hdr.String() + rr.Target }
+func (rr *CNAME) len() int           { return rr.Hdr.len() + len(rr.Target) + 1 }
+
+type HINFO struct {
+	Hdr RR_Header
+	Cpu string
+	Os  string
+}
+
+func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *HINFO) copy() RR           { return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os} }
+func (rr *HINFO) String() string {
+	return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
+}
+func (rr *HINFO) len() int { return rr.Hdr.len() + len(rr.Cpu) + len(rr.Os) }
+
+type MB struct {
+	Hdr RR_Header
+	Mb  string `dns:"cdomain-name"`
+}
+
+func (rr *MB) Header() *RR_Header { return &rr.Hdr }
+func (rr *MB) copy() RR           { return &MB{*rr.Hdr.copyHeader(), sprintName(rr.Mb)} }
+
+func (rr *MB) String() string { return rr.Hdr.String() + rr.Mb }
+func (rr *MB) len() int       { return rr.Hdr.len() + len(rr.Mb) + 1 }
+
+type MG struct {
+	Hdr RR_Header
+	Mg  string `dns:"cdomain-name"`
+}
+
+func (rr *MG) Header() *RR_Header { return &rr.Hdr }
+func (rr *MG) copy() RR           { return &MG{*rr.Hdr.copyHeader(), rr.Mg} }
+func (rr *MG) len() int           { l := len(rr.Mg) + 1; return rr.Hdr.len() + l }
+func (rr *MG) String() string     { return rr.Hdr.String() + sprintName(rr.Mg) }
+
+type MINFO struct {
+	Hdr   RR_Header
+	Rmail string `dns:"cdomain-name"`
+	Email string `dns:"cdomain-name"`
+}
+
+func (rr *MINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *MINFO) copy() RR           { return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email} }
+
+func (rr *MINFO) String() string {
+	return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
+}
+
+func (rr *MINFO) len() int {
+	l := len(rr.Rmail) + 1
+	n := len(rr.Email) + 1
+	return rr.Hdr.len() + l + n
+}
+
+type MR struct {
+	Hdr RR_Header
+	Mr  string `dns:"cdomain-name"`
+}
+
+func (rr *MR) Header() *RR_Header { return &rr.Hdr }
+func (rr *MR) copy() RR           { return &MR{*rr.Hdr.copyHeader(), rr.Mr} }
+func (rr *MR) len() int           { l := len(rr.Mr) + 1; return rr.Hdr.len() + l }
+
+func (rr *MR) String() string {
+	return rr.Hdr.String() + sprintName(rr.Mr)
+}
+
+type MF struct {
+	Hdr RR_Header
+	Mf  string `dns:"cdomain-name"`
+}
+
+func (rr *MF) Header() *RR_Header { return &rr.Hdr }
+func (rr *MF) copy() RR           { return &MF{*rr.Hdr.copyHeader(), rr.Mf} }
+func (rr *MF) len() int           { return rr.Hdr.len() + len(rr.Mf) + 1 }
+
+func (rr *MF) String() string {
+	return rr.Hdr.String() + sprintName(rr.Mf)
+}
+
+type MD struct {
+	Hdr RR_Header
+	Md  string `dns:"cdomain-name"`
+}
+
+func (rr *MD) Header() *RR_Header { return &rr.Hdr }
+func (rr *MD) copy() RR           { return &MD{*rr.Hdr.copyHeader(), rr.Md} }
+func (rr *MD) len() int           { return rr.Hdr.len() + len(rr.Md) + 1 }
+
+func (rr *MD) String() string {
+	return rr.Hdr.String() + sprintName(rr.Md)
+}
+
+type MX struct {
+	Hdr        RR_Header
+	Preference uint16
+	Mx         string `dns:"cdomain-name"`
+}
+
+func (rr *MX) Header() *RR_Header { return &rr.Hdr }
+func (rr *MX) copy() RR           { return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx} }
+func (rr *MX) len() int           { l := len(rr.Mx) + 1; return rr.Hdr.len() + l + 2 }
+
+func (rr *MX) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
+}
+
+type AFSDB struct {
+	Hdr      RR_Header
+	Subtype  uint16
+	Hostname string `dns:"cdomain-name"`
+}
+
+func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
+func (rr *AFSDB) copy() RR           { return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname} }
+func (rr *AFSDB) len() int           { l := len(rr.Hostname) + 1; return rr.Hdr.len() + l + 2 }
+
+func (rr *AFSDB) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
+}
+
+type X25 struct {
+	Hdr         RR_Header
+	PSDNAddress string
+}
+
+func (rr *X25) Header() *RR_Header { return &rr.Hdr }
+func (rr *X25) copy() RR           { return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress} }
+func (rr *X25) len() int           { return rr.Hdr.len() + len(rr.PSDNAddress) + 1 }
+
+func (rr *X25) String() string {
+	return rr.Hdr.String() + rr.PSDNAddress
+}
+
+type RT struct {
+	Hdr        RR_Header
+	Preference uint16
+	Host       string `dns:"cdomain-name"`
+}
+
+func (rr *RT) Header() *RR_Header { return &rr.Hdr }
+func (rr *RT) copy() RR           { return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host} }
+func (rr *RT) len() int           { l := len(rr.Host) + 1; return rr.Hdr.len() + l + 2 }
+
+func (rr *RT) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
+}
+
+type NS struct {
+	Hdr RR_Header
+	Ns  string `dns:"cdomain-name"`
+}
+
+func (rr *NS) Header() *RR_Header { return &rr.Hdr }
+func (rr *NS) len() int           { l := len(rr.Ns) + 1; return rr.Hdr.len() + l }
+func (rr *NS) copy() RR           { return &NS{*rr.Hdr.copyHeader(), rr.Ns} }
+
+func (rr *NS) String() string {
+	return rr.Hdr.String() + sprintName(rr.Ns)
+}
+
+type PTR struct {
+	Hdr RR_Header
+	Ptr string `dns:"cdomain-name"`
+}
+
+func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *PTR) copy() RR           { return &PTR{*rr.Hdr.copyHeader(), rr.Ptr} }
+func (rr *PTR) len() int           { l := len(rr.Ptr) + 1; return rr.Hdr.len() + l }
+
+func (rr *PTR) String() string {
+	return rr.Hdr.String() + sprintName(rr.Ptr)
+}
+
+type RP struct {
+	Hdr  RR_Header
+	Mbox string `dns:"domain-name"`
+	Txt  string `dns:"domain-name"`
+}
+
+func (rr *RP) Header() *RR_Header { return &rr.Hdr }
+func (rr *RP) copy() RR           { return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt} }
+func (rr *RP) len() int           { return rr.Hdr.len() + len(rr.Mbox) + 1 + len(rr.Txt) + 1 }
+
+func (rr *RP) String() string {
+	return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
+}
+
+type SOA struct {
+	Hdr     RR_Header
+	Ns      string `dns:"cdomain-name"`
+	Mbox    string `dns:"cdomain-name"`
+	Serial  uint32
+	Refresh uint32
+	Retry   uint32
+	Expire  uint32
+	Minttl  uint32
+}
+
+func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
+func (rr *SOA) copy() RR {
+	return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
+}
+
+func (rr *SOA) String() string {
+	return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
+		" " + strconv.FormatInt(int64(rr.Serial), 10) +
+		" " + strconv.FormatInt(int64(rr.Refresh), 10) +
+		" " + strconv.FormatInt(int64(rr.Retry), 10) +
+		" " + strconv.FormatInt(int64(rr.Expire), 10) +
+		" " + strconv.FormatInt(int64(rr.Minttl), 10)
+}
+
+func (rr *SOA) len() int {
+	l := len(rr.Ns) + 1
+	n := len(rr.Mbox) + 1
+	return rr.Hdr.len() + l + n + 20
+}
+
+type TXT struct {
+	Hdr RR_Header
+	Txt []string `dns:"txt"`
+}
+
+func (rr *TXT) Header() *RR_Header { return &rr.Hdr }
+func (rr *TXT) copy() RR {
+	cp := make([]string, len(rr.Txt), cap(rr.Txt))
+	copy(cp, rr.Txt)
+	return &TXT{*rr.Hdr.copyHeader(), cp}
+}
+
+func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
+func sprintName(s string) string {
+	src := []byte(s)
+	dst := make([]byte, 0, len(src))
+	for i := 0; i < len(src); {
+		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
+			dst = append(dst, src[i:i+2]...)
+			i += 2
+		} else {
+			b, n := nextByte(src, i)
+			if n == 0 {
+				i++ // dangling back slash
+			} else if b == '.' {
+				dst = append(dst, b)
+			} else {
+				dst = appendDomainNameByte(dst, b)
+			}
+			i += n
+		}
+	}
+	return string(dst)
+}
+
+func sprintTxtOctet(s string) string {
+	src := []byte(s)
+	dst := make([]byte, 0, len(src))
+	dst = append(dst, '"')
+	for i := 0; i < len(src); {
+		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
+			dst = append(dst, src[i:i+2]...)
+			i += 2
+		} else {
+			b, n := nextByte(src, i)
+			if n == 0 {
+				i++ // dangling back slash
+			} else if b == '.' {
+				dst = append(dst, b)
+			} else {
+				if b < ' ' || b > '~' {
+					dst = appendByte(dst, b)
+				} else {
+					dst = append(dst, b)
+				}
+			}
+			i += n
+		}
+	}
+	dst = append(dst, '"')
+	return string(dst)
+}
+
+func sprintTxt(txt []string) string {
+	var out []byte
+	for i, s := range txt {
+		if i > 0 {
+			out = append(out, ` "`...)
+		} else {
+			out = append(out, '"')
+		}
+		bs := []byte(s)
+		for j := 0; j < len(bs); {
+			b, n := nextByte(bs, j)
+			if n == 0 {
+				break
+			}
+			out = appendTXTStringByte(out, b)
+			j += n
+		}
+		out = append(out, '"')
+	}
+	return string(out)
+}
+
+func appendDomainNameByte(s []byte, b byte) []byte {
+	switch b {
+	case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
+		return append(s, '\\', b)
+	}
+	return appendTXTStringByte(s, b)
+}
+
+func appendTXTStringByte(s []byte, b byte) []byte {
+	switch b {
+	case '\t':
+		return append(s, '\\', 't')
+	case '\r':
+		return append(s, '\\', 'r')
+	case '\n':
+		return append(s, '\\', 'n')
+	case '"', '\\':
+		return append(s, '\\', b)
+	}
+	if b < ' ' || b > '~' {
+		return appendByte(s, b)
+	}
+	return append(s, b)
+}
+
+func appendByte(s []byte, b byte) []byte {
+	var buf [3]byte
+	bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+	s = append(s, '\\')
+	for i := 0; i < 3-len(bufs); i++ {
+		s = append(s, '0')
+	}
+	for _, r := range bufs {
+		s = append(s, r)
+	}
+	return s
+}
+
+func nextByte(b []byte, offset int) (byte, int) {
+	if offset >= len(b) {
+		return 0, 0
+	}
+	if b[offset] != '\\' {
+		// not an escape sequence
+		return b[offset], 1
+	}
+	switch len(b) - offset {
+	case 1: // dangling escape
+		return 0, 0
+	case 2, 3: // too short to be \ddd
+	default: // maybe \ddd
+		if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
+			return dddToByte(b[offset+1:]), 4
+		}
+	}
+	// not \ddd, maybe a control char
+	switch b[offset+1] {
+	case 't':
+		return '\t', 2
+	case 'r':
+		return '\r', 2
+	case 'n':
+		return '\n', 2
+	default:
+		return b[offset+1], 2
+	}
+}
+
+func (rr *TXT) len() int {
+	l := rr.Hdr.len()
+	for _, t := range rr.Txt {
+		l += len(t) + 1
+	}
+	return l
+}
+
+type SPF struct {
+	Hdr RR_Header
+	Txt []string `dns:"txt"`
+}
+
+func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
+func (rr *SPF) copy() RR {
+	cp := make([]string, len(rr.Txt), cap(rr.Txt))
+	copy(cp, rr.Txt)
+	return &SPF{*rr.Hdr.copyHeader(), cp}
+}
+
+func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
+func (rr *SPF) len() int {
+	l := rr.Hdr.len()
+	for _, t := range rr.Txt {
+		l += len(t) + 1
+	}
+	return l
+}
+
+type SRV struct {
+	Hdr      RR_Header
+	Priority uint16
+	Weight   uint16
+	Port     uint16
+	Target   string `dns:"domain-name"`
+}
+
+func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
+func (rr *SRV) len() int           { l := len(rr.Target) + 1; return rr.Hdr.len() + l + 6 }
+func (rr *SRV) copy() RR {
+	return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
+}
+
+func (rr *SRV) String() string {
+	return rr.Hdr.String() +
+		strconv.Itoa(int(rr.Priority)) + " " +
+		strconv.Itoa(int(rr.Weight)) + " " +
+		strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
+}
+
+type NAPTR struct {
+	Hdr         RR_Header
+	Order       uint16
+	Preference  uint16
+	Flags       string
+	Service     string
+	Regexp      string
+	Replacement string `dns:"domain-name"`
+}
+
+func (rr *NAPTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *NAPTR) copy() RR {
+	return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
+}
+
+func (rr *NAPTR) String() string {
+	return rr.Hdr.String() +
+		strconv.Itoa(int(rr.Order)) + " " +
+		strconv.Itoa(int(rr.Preference)) + " " +
+		"\"" + rr.Flags + "\" " +
+		"\"" + rr.Service + "\" " +
+		"\"" + rr.Regexp + "\" " +
+		rr.Replacement
+}
+
+func (rr *NAPTR) len() int {
+	return rr.Hdr.len() + 4 + len(rr.Flags) + 1 + len(rr.Service) + 1 +
+		len(rr.Regexp) + 1 + len(rr.Replacement) + 1
+}
+
+// The CERT resource record, see RFC 4398.
+type CERT struct {
+	Hdr         RR_Header
+	Type        uint16
+	KeyTag      uint16
+	Algorithm   uint8
+	Certificate string `dns:"base64"`
+}
+
+func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
+func (rr *CERT) copy() RR {
+	return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
+}
+
+func (rr *CERT) String() string {
+	var (
+		ok                  bool
+		certtype, algorithm string
+	)
+	if certtype, ok = CertTypeToString[rr.Type]; !ok {
+		certtype = strconv.Itoa(int(rr.Type))
+	}
+	if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok {
+		algorithm = strconv.Itoa(int(rr.Algorithm))
+	}
+	return rr.Hdr.String() + certtype +
+		" " + strconv.Itoa(int(rr.KeyTag)) +
+		" " + algorithm +
+		" " + rr.Certificate
+}
+
+func (rr *CERT) len() int {
+	return rr.Hdr.len() + 5 +
+		base64.StdEncoding.DecodedLen(len(rr.Certificate))
+}
+
+// The DNAME resource record, see RFC 2672.
+type DNAME struct {
+	Hdr    RR_Header
+	Target string `dns:"domain-name"`
+}
+
+func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
+func (rr *DNAME) copy() RR           { return &DNAME{*rr.Hdr.copyHeader(), rr.Target} }
+func (rr *DNAME) len() int           { l := len(rr.Target) + 1; return rr.Hdr.len() + l }
+
+func (rr *DNAME) String() string {
+	return rr.Hdr.String() + sprintName(rr.Target)
+}
+
+type A struct {
+	Hdr RR_Header
+	A   net.IP `dns:"a"`
+}
+
+func (rr *A) Header() *RR_Header { return &rr.Hdr }
+func (rr *A) copy() RR           { return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)} }
+func (rr *A) len() int           { return rr.Hdr.len() + net.IPv4len }
+
+func (rr *A) String() string {
+	if rr.A == nil {
+		return rr.Hdr.String()
+	}
+	return rr.Hdr.String() + rr.A.String()
+}
+
+type AAAA struct {
+	Hdr  RR_Header
+	AAAA net.IP `dns:"aaaa"`
+}
+
+func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
+func (rr *AAAA) copy() RR           { return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)} }
+func (rr *AAAA) len() int           { return rr.Hdr.len() + net.IPv6len }
+
+func (rr *AAAA) String() string {
+	if rr.AAAA == nil {
+		return rr.Hdr.String()
+	}
+	return rr.Hdr.String() + rr.AAAA.String()
+}
+
+type PX struct {
+	Hdr        RR_Header
+	Preference uint16
+	Map822     string `dns:"domain-name"`
+	Mapx400    string `dns:"domain-name"`
+}
+
+func (rr *PX) Header() *RR_Header { return &rr.Hdr }
+func (rr *PX) copy() RR           { return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400} }
+func (rr *PX) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
+}
+func (rr *PX) len() int { return rr.Hdr.len() + 2 + len(rr.Map822) + 1 + len(rr.Mapx400) + 1 }
+
+type GPOS struct {
+	Hdr       RR_Header
+	Longitude string
+	Latitude  string
+	Altitude  string
+}
+
+func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
+func (rr *GPOS) copy() RR           { return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude} }
+func (rr *GPOS) len() int {
+	return rr.Hdr.len() + len(rr.Longitude) + len(rr.Latitude) + len(rr.Altitude) + 3
+}
+func (rr *GPOS) String() string {
+	return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
+}
+
+type LOC struct {
+	Hdr       RR_Header
+	Version   uint8
+	Size      uint8
+	HorizPre  uint8
+	VertPre   uint8
+	Latitude  uint32
+	Longitude uint32
+	Altitude  uint32
+}
+
+func (rr *LOC) Header() *RR_Header { return &rr.Hdr }
+func (rr *LOC) len() int           { return rr.Hdr.len() + 4 + 12 }
+func (rr *LOC) copy() RR {
+	return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
+}
+
+// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent
+// format and returns a string in m (two decimals for the cm)
+func cmToM(m, e uint8) string {
+	if e < 2 {
+		if e == 1 {
+			m *= 10
+		}
+
+		return fmt.Sprintf("0.%02d", m)
+	}
+
+	s := fmt.Sprintf("%d", m)
+	for e > 2 {
+		s += "0"
+		e--
+	}
+	return s
+}
+
+func (rr *LOC) String() string {
+	s := rr.Hdr.String()
+
+	lat := rr.Latitude
+	ns := "N"
+	if lat > LOC_EQUATOR {
+		lat = lat - LOC_EQUATOR
+	} else {
+		ns = "S"
+		lat = LOC_EQUATOR - lat
+	}
+	h := lat / LOC_DEGREES
+	lat = lat % LOC_DEGREES
+	m := lat / LOC_HOURS
+	lat = lat % LOC_HOURS
+	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
+
+	lon := rr.Longitude
+	ew := "E"
+	if lon > LOC_PRIMEMERIDIAN {
+		lon = lon - LOC_PRIMEMERIDIAN
+	} else {
+		ew = "W"
+		lon = LOC_PRIMEMERIDIAN - lon
+	}
+	h = lon / LOC_DEGREES
+	lon = lon % LOC_DEGREES
+	m = lon / LOC_HOURS
+	lon = lon % LOC_HOURS
+	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
+
+	var alt = float64(rr.Altitude) / 100
+	alt -= LOC_ALTITUDEBASE
+	if rr.Altitude%100 != 0 {
+		s += fmt.Sprintf("%.2fm ", alt)
+	} else {
+		s += fmt.Sprintf("%.0fm ", alt)
+	}
+
+	s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
+	s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
+	s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
+
+	return s
+}
+
+// SIG is identical to RRSIG and nowadays only used for SIG(0), RFC2931.
+type SIG struct {
+	RRSIG
+}
+
+type RRSIG struct {
+	Hdr         RR_Header
+	TypeCovered uint16
+	Algorithm   uint8
+	Labels      uint8
+	OrigTtl     uint32
+	Expiration  uint32
+	Inception   uint32
+	KeyTag      uint16
+	SignerName  string `dns:"domain-name"`
+	Signature   string `dns:"base64"`
+}
+
+func (rr *RRSIG) Header() *RR_Header { return &rr.Hdr }
+func (rr *RRSIG) copy() RR {
+	return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
+}
+
+func (rr *RRSIG) String() string {
+	s := rr.Hdr.String()
+	s += Type(rr.TypeCovered).String()
+	s += " " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + strconv.Itoa(int(rr.Labels)) +
+		" " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
+		" " + TimeToString(rr.Expiration) +
+		" " + TimeToString(rr.Inception) +
+		" " + strconv.Itoa(int(rr.KeyTag)) +
+		" " + sprintName(rr.SignerName) +
+		" " + rr.Signature
+	return s
+}
+
+func (rr *RRSIG) len() int {
+	return rr.Hdr.len() + len(rr.SignerName) + 1 +
+		base64.StdEncoding.DecodedLen(len(rr.Signature)) + 18
+}
+
+type NSEC struct {
+	Hdr        RR_Header
+	NextDomain string   `dns:"domain-name"`
+	TypeBitMap []uint16 `dns:"nsec"`
+}
+
+func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC) copy() RR {
+	cp := make([]uint16, len(rr.TypeBitMap), cap(rr.TypeBitMap))
+	copy(cp, rr.TypeBitMap)
+	return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, cp}
+}
+
+func (rr *NSEC) String() string {
+	s := rr.Hdr.String() + sprintName(rr.NextDomain)
+	for i := 0; i < len(rr.TypeBitMap); i++ {
+		s += " " + Type(rr.TypeBitMap[i]).String()
+	}
+	return s
+}
+
+func (rr *NSEC) len() int {
+	l := rr.Hdr.len() + len(rr.NextDomain) + 1
+	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
+}
+
+type DLV struct {
+	DS
+}
+
+type CDS struct {
+	DS
+}
+
+type DS struct {
+	Hdr        RR_Header
+	KeyTag     uint16
+	Algorithm  uint8
+	DigestType uint8
+	Digest     string `dns:"hex"`
+}
+
+func (rr *DS) Header() *RR_Header { return &rr.Hdr }
+func (rr *DS) len() int           { return rr.Hdr.len() + 4 + len(rr.Digest)/2 }
+func (rr *DS) copy() RR {
+	return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+}
+
+func (rr *DS) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
+		" " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + strconv.Itoa(int(rr.DigestType)) +
+		" " + strings.ToUpper(rr.Digest)
+}
+
+type KX struct {
+	Hdr        RR_Header
+	Preference uint16
+	Exchanger  string `dns:"domain-name"`
+}
+
+func (rr *KX) Header() *RR_Header { return &rr.Hdr }
+func (rr *KX) len() int           { return rr.Hdr.len() + 2 + len(rr.Exchanger) + 1 }
+func (rr *KX) copy() RR           { return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger} }
+
+func (rr *KX) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
+		" " + sprintName(rr.Exchanger)
+}
+
+type TA struct {
+	Hdr        RR_Header
+	KeyTag     uint16
+	Algorithm  uint8
+	DigestType uint8
+	Digest     string `dns:"hex"`
+}
+
+func (rr *TA) Header() *RR_Header { return &rr.Hdr }
+func (rr *TA) len() int           { return rr.Hdr.len() + 4 + len(rr.Digest)/2 }
+func (rr *TA) copy() RR {
+	return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+}
+
+func (rr *TA) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
+		" " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + strconv.Itoa(int(rr.DigestType)) +
+		" " + strings.ToUpper(rr.Digest)
+}
+
+type TALINK struct {
+	Hdr          RR_Header
+	PreviousName string `dns:"domain-name"`
+	NextName     string `dns:"domain-name"`
+}
+
+func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
+func (rr *TALINK) copy() RR           { return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName} }
+func (rr *TALINK) len() int           { return rr.Hdr.len() + len(rr.PreviousName) + len(rr.NextName) + 2 }
+
+func (rr *TALINK) String() string {
+	return rr.Hdr.String() +
+		sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
+}
+
+type SSHFP struct {
+	Hdr         RR_Header
+	Algorithm   uint8
+	Type        uint8
+	FingerPrint string `dns:"hex"`
+}
+
+func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
+func (rr *SSHFP) len() int           { return rr.Hdr.len() + 2 + len(rr.FingerPrint)/2 }
+func (rr *SSHFP) copy() RR {
+	return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
+}
+
+func (rr *SSHFP) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
+		" " + strconv.Itoa(int(rr.Type)) +
+		" " + strings.ToUpper(rr.FingerPrint)
+}
+
+type IPSECKEY struct {
+	Hdr        RR_Header
+	Precedence uint8
+	// GatewayType: 1: A record, 2: AAAA record, 3: domainname.
+	// 0 is use for no type and GatewayName should be "." then.
+	GatewayType uint8
+	Algorithm   uint8
+	// Gateway can be an A record, AAAA record or a domain name.
+	GatewayA    net.IP `dns:"a"`
+	GatewayAAAA net.IP `dns:"aaaa"`
+	GatewayName string `dns:"domain-name"`
+	PublicKey   string `dns:"base64"`
+}
+
+func (rr *IPSECKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *IPSECKEY) copy() RR {
+	return &IPSECKEY{*rr.Hdr.copyHeader(), rr.Precedence, rr.GatewayType, rr.Algorithm, rr.GatewayA, rr.GatewayAAAA, rr.GatewayName, rr.PublicKey}
+}
+
+func (rr *IPSECKEY) String() string {
+	s := rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
+		" " + strconv.Itoa(int(rr.GatewayType)) +
+		" " + strconv.Itoa(int(rr.Algorithm))
+	switch rr.GatewayType {
+	case 0:
+		fallthrough
+	case 3:
+		s += " " + rr.GatewayName
+	case 1:
+		s += " " + rr.GatewayA.String()
+	case 2:
+		s += " " + rr.GatewayAAAA.String()
+	default:
+		s += " ."
+	}
+	s += " " + rr.PublicKey
+	return s
+}
+
+func (rr *IPSECKEY) len() int {
+	l := rr.Hdr.len() + 3 + 1
+	switch rr.GatewayType {
+	default:
+		fallthrough
+	case 0:
+		fallthrough
+	case 3:
+		l += len(rr.GatewayName)
+	case 1:
+		l += 4
+	case 2:
+		l += 16
+	}
+	return l + base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+}
+
+type KEY struct {
+	DNSKEY
+}
+
+type CDNSKEY struct {
+	DNSKEY
+}
+
+type DNSKEY struct {
+	Hdr       RR_Header
+	Flags     uint16
+	Protocol  uint8
+	Algorithm uint8
+	PublicKey string `dns:"base64"`
+}
+
+func (rr *DNSKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *DNSKEY) len() int {
+	return rr.Hdr.len() + 4 + base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+}
+func (rr *DNSKEY) copy() RR {
+	return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+}
+
+func (rr *DNSKEY) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
+		" " + strconv.Itoa(int(rr.Protocol)) +
+		" " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + rr.PublicKey
+}
+
+type RKEY struct {
+	Hdr       RR_Header
+	Flags     uint16
+	Protocol  uint8
+	Algorithm uint8
+	PublicKey string `dns:"base64"`
+}
+
+func (rr *RKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *RKEY) len() int           { return rr.Hdr.len() + 4 + base64.StdEncoding.DecodedLen(len(rr.PublicKey)) }
+func (rr *RKEY) copy() RR {
+	return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+}
+
+func (rr *RKEY) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
+		" " + strconv.Itoa(int(rr.Protocol)) +
+		" " + strconv.Itoa(int(rr.Algorithm)) +
+		" " + rr.PublicKey
+}
+
+type NSAPPTR struct {
+	Hdr RR_Header
+	Ptr string `dns:"domain-name"`
+}
+
+func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSAPPTR) copy() RR           { return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr} }
+func (rr *NSAPPTR) String() string     { return rr.Hdr.String() + sprintName(rr.Ptr) }
+func (rr *NSAPPTR) len() int           { return rr.Hdr.len() + len(rr.Ptr) }
+
+type NSEC3 struct {
+	Hdr        RR_Header
+	Hash       uint8
+	Flags      uint8
+	Iterations uint16
+	SaltLength uint8
+	Salt       string `dns:"size-hex"`
+	HashLength uint8
+	NextDomain string   `dns:"size-base32"`
+	TypeBitMap []uint16 `dns:"nsec"`
+}
+
+func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC3) copy() RR {
+	cp := make([]uint16, len(rr.TypeBitMap), cap(rr.TypeBitMap))
+	copy(cp, rr.TypeBitMap)
+	return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, cp}
+}
+
+func (rr *NSEC3) String() string {
+	s := rr.Hdr.String()
+	s += strconv.Itoa(int(rr.Hash)) +
+		" " + strconv.Itoa(int(rr.Flags)) +
+		" " + strconv.Itoa(int(rr.Iterations)) +
+		" " + saltToString(rr.Salt) +
+		" " + rr.NextDomain
+	for i := 0; i < len(rr.TypeBitMap); i++ {
+		s += " " + Type(rr.TypeBitMap[i]).String()
+	}
+	return s
+}
+
+func (rr *NSEC3) len() int {
+	l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
+	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
+}
+
+type NSEC3PARAM struct {
+	Hdr        RR_Header
+	Hash       uint8
+	Flags      uint8
+	Iterations uint16
+	SaltLength uint8
+	Salt       string `dns:"hex"`
+}
+
+func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC3PARAM) len() int           { return rr.Hdr.len() + 2 + 4 + 1 + len(rr.Salt)/2 }
+func (rr *NSEC3PARAM) copy() RR {
+	return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
+}
+
+func (rr *NSEC3PARAM) String() string {
+	s := rr.Hdr.String()
+	s += strconv.Itoa(int(rr.Hash)) +
+		" " + strconv.Itoa(int(rr.Flags)) +
+		" " + strconv.Itoa(int(rr.Iterations)) +
+		" " + saltToString(rr.Salt)
+	return s
+}
+
+type TKEY struct {
+	Hdr        RR_Header
+	Algorithm  string `dns:"domain-name"`
+	Inception  uint32
+	Expiration uint32
+	Mode       uint16
+	Error      uint16
+	KeySize    uint16
+	Key        string
+	OtherLen   uint16
+	OtherData  string
+}
+
+func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *TKEY) copy() RR {
+	return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
+}
+
+func (rr *TKEY) String() string {
+	// It has no presentation format
+	return ""
+}
+
+func (rr *TKEY) len() int {
+	return rr.Hdr.len() + len(rr.Algorithm) + 1 + 4 + 4 + 6 +
+		len(rr.Key) + 2 + len(rr.OtherData)
+}
+
+// RFC3597 represents an unknown/generic RR.
+type RFC3597 struct {
+	Hdr   RR_Header
+	Rdata string `dns:"hex"`
+}
+
+func (rr *RFC3597) Header() *RR_Header { return &rr.Hdr }
+func (rr *RFC3597) copy() RR           { return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata} }
+func (rr *RFC3597) len() int           { return rr.Hdr.len() + len(rr.Rdata)/2 + 2 }
+
+func (rr *RFC3597) String() string {
+	// Let's call it a hack
+	s := rfc3597Header(rr.Hdr)
+
+	s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
+	return s
+}
+
+func rfc3597Header(h RR_Header) string {
+	var s string
+
+	s += sprintName(h.Name) + "\t"
+	s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
+	s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t"
+	s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t"
+	return s
+}
+
+type URI struct {
+	Hdr      RR_Header
+	Priority uint16
+	Weight   uint16
+	Target   string `dns:"octet"`
+}
+
+func (rr *URI) Header() *RR_Header { return &rr.Hdr }
+func (rr *URI) copy() RR           { return &URI{*rr.Hdr.copyHeader(), rr.Weight, rr.Priority, rr.Target} }
+func (rr *URI) len() int           { return rr.Hdr.len() + 4 + len(rr.Target) }
+func (rr *URI) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
+		" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
+}
+
+type DHCID struct {
+	Hdr    RR_Header
+	Digest string `dns:"base64"`
+}
+
+func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
+func (rr *DHCID) copy() RR           { return &DHCID{*rr.Hdr.copyHeader(), rr.Digest} }
+func (rr *DHCID) String() string     { return rr.Hdr.String() + rr.Digest }
+func (rr *DHCID) len() int           { return rr.Hdr.len() + base64.StdEncoding.DecodedLen(len(rr.Digest)) }
+
+type TLSA struct {
+	Hdr          RR_Header
+	Usage        uint8
+	Selector     uint8
+	MatchingType uint8
+	Certificate  string `dns:"hex"`
+}
+
+func (rr *TLSA) Header() *RR_Header { return &rr.Hdr }
+func (rr *TLSA) len() int           { return rr.Hdr.len() + 3 + len(rr.Certificate)/2 }
+
+func (rr *TLSA) copy() RR {
+	return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
+}
+
+func (rr *TLSA) String() string {
+	return rr.Hdr.String() +
+		strconv.Itoa(int(rr.Usage)) +
+		" " + strconv.Itoa(int(rr.Selector)) +
+		" " + strconv.Itoa(int(rr.MatchingType)) +
+		" " + rr.Certificate
+}
+
+type HIP struct {
+	Hdr                RR_Header
+	HitLength          uint8
+	PublicKeyAlgorithm uint8
+	PublicKeyLength    uint16
+	Hit                string   `dns:"hex"`
+	PublicKey          string   `dns:"base64"`
+	RendezvousServers  []string `dns:"domain-name"`
+}
+
+func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
+func (rr *HIP) copy() RR {
+	cp := make([]string, len(rr.RendezvousServers), cap(rr.RendezvousServers))
+	copy(cp, rr.RendezvousServers)
+	return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, cp}
+}
+
+func (rr *HIP) String() string {
+	s := rr.Hdr.String() +
+		strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
+		" " + rr.Hit +
+		" " + rr.PublicKey
+	for _, d := range rr.RendezvousServers {
+		s += " " + sprintName(d)
+	}
+	return s
+}
+
+func (rr *HIP) len() int {
+	l := rr.Hdr.len() + 4 +
+		len(rr.Hit)/2 +
+		base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+	for _, d := range rr.RendezvousServers {
+		l += len(d) + 1
+	}
+	return l
+}
+
+type NINFO struct {
+	Hdr    RR_Header
+	ZSData []string `dns:"txt"`
+}
+
+func (rr *NINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *NINFO) copy() RR {
+	cp := make([]string, len(rr.ZSData), cap(rr.ZSData))
+	copy(cp, rr.ZSData)
+	return &NINFO{*rr.Hdr.copyHeader(), cp}
+}
+
+func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
+
+func (rr *NINFO) len() int {
+	l := rr.Hdr.len()
+	for _, t := range rr.ZSData {
+		l += len(t) + 1
+	}
+	return l
+}
+
+type WKS struct {
+	Hdr      RR_Header
+	Address  net.IP `dns:"a"`
+	Protocol uint8
+	BitMap   []uint16 `dns:"wks"`
+}
+
+func (rr *WKS) Header() *RR_Header { return &rr.Hdr }
+func (rr *WKS) len() int           { return rr.Hdr.len() + net.IPv4len + 1 }
+
+func (rr *WKS) copy() RR {
+	cp := make([]uint16, len(rr.BitMap), cap(rr.BitMap))
+	copy(cp, rr.BitMap)
+	return &WKS{*rr.Hdr.copyHeader(), copyIP(rr.Address), rr.Protocol, cp}
+}
+
+func (rr *WKS) String() (s string) {
+	s = rr.Hdr.String()
+	if rr.Address != nil {
+		s += rr.Address.String()
+	}
+	// TODO(miek): missing protocol here, see /etc/protocols
+	for i := 0; i < len(rr.BitMap); i++ {
+		// should lookup the port
+		s += " " + strconv.Itoa(int(rr.BitMap[i]))
+	}
+	return s
+}
+
+type NID struct {
+	Hdr        RR_Header
+	Preference uint16
+	NodeID     uint64
+}
+
+func (rr *NID) Header() *RR_Header { return &rr.Hdr }
+func (rr *NID) copy() RR           { return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID} }
+func (rr *NID) len() int           { return rr.Hdr.len() + 2 + 8 }
+
+func (rr *NID) String() string {
+	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+	node := fmt.Sprintf("%0.16x", rr.NodeID)
+	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
+	return s
+}
+
+type L32 struct {
+	Hdr        RR_Header
+	Preference uint16
+	Locator32  net.IP `dns:"a"`
+}
+
+func (rr *L32) Header() *RR_Header { return &rr.Hdr }
+func (rr *L32) copy() RR           { return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)} }
+func (rr *L32) len() int           { return rr.Hdr.len() + net.IPv4len }
+
+func (rr *L32) String() string {
+	if rr.Locator32 == nil {
+		return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+	}
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
+		" " + rr.Locator32.String()
+}
+
+type L64 struct {
+	Hdr        RR_Header
+	Preference uint16
+	Locator64  uint64
+}
+
+func (rr *L64) Header() *RR_Header { return &rr.Hdr }
+func (rr *L64) copy() RR           { return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64} }
+func (rr *L64) len() int           { return rr.Hdr.len() + 2 + 8 }
+
+func (rr *L64) String() string {
+	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+	node := fmt.Sprintf("%0.16X", rr.Locator64)
+	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
+	return s
+}
+
+type LP struct {
+	Hdr        RR_Header
+	Preference uint16
+	Fqdn       string `dns:"domain-name"`
+}
+
+func (rr *LP) Header() *RR_Header { return &rr.Hdr }
+func (rr *LP) copy() RR           { return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn} }
+func (rr *LP) len() int           { return rr.Hdr.len() + 2 + len(rr.Fqdn) + 1 }
+
+func (rr *LP) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
+}
+
+type EUI48 struct {
+	Hdr     RR_Header
+	Address uint64 `dns:"uint48"`
+}
+
+func (rr *EUI48) Header() *RR_Header { return &rr.Hdr }
+func (rr *EUI48) copy() RR           { return &EUI48{*rr.Hdr.copyHeader(), rr.Address} }
+func (rr *EUI48) String() string     { return rr.Hdr.String() + euiToString(rr.Address, 48) }
+func (rr *EUI48) len() int           { return rr.Hdr.len() + 6 }
+
+type EUI64 struct {
+	Hdr     RR_Header
+	Address uint64
+}
+
+func (rr *EUI64) Header() *RR_Header { return &rr.Hdr }
+func (rr *EUI64) copy() RR           { return &EUI64{*rr.Hdr.copyHeader(), rr.Address} }
+func (rr *EUI64) String() string     { return rr.Hdr.String() + euiToString(rr.Address, 64) }
+func (rr *EUI64) len() int           { return rr.Hdr.len() + 8 }
+
+type CAA struct {
+	Hdr   RR_Header
+	Flag  uint8
+	Tag   string
+	Value string `dns:"octet"`
+}
+
+func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
+func (rr *CAA) copy() RR           { return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value} }
+func (rr *CAA) len() int           { return rr.Hdr.len() + 2 + len(rr.Tag) + len(rr.Value) }
+func (rr *CAA) String() string {
+	return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
+}
+
+type UID struct {
+	Hdr RR_Header
+	Uid uint32
+}
+
+func (rr *UID) Header() *RR_Header { return &rr.Hdr }
+func (rr *UID) copy() RR           { return &UID{*rr.Hdr.copyHeader(), rr.Uid} }
+func (rr *UID) String() string     { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
+func (rr *UID) len() int           { return rr.Hdr.len() + 4 }
+
+type GID struct {
+	Hdr RR_Header
+	Gid uint32
+}
+
+func (rr *GID) Header() *RR_Header { return &rr.Hdr }
+func (rr *GID) copy() RR           { return &GID{*rr.Hdr.copyHeader(), rr.Gid} }
+func (rr *GID) String() string     { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
+func (rr *GID) len() int           { return rr.Hdr.len() + 4 }
+
+type UINFO struct {
+	Hdr   RR_Header
+	Uinfo string
+}
+
+func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *UINFO) copy() RR           { return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo} }
+func (rr *UINFO) String() string     { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
+func (rr *UINFO) len() int           { return rr.Hdr.len() + len(rr.Uinfo) + 1 }
+
+type EID struct {
+	Hdr      RR_Header
+	Endpoint string `dns:"hex"`
+}
+
+func (rr *EID) Header() *RR_Header { return &rr.Hdr }
+func (rr *EID) copy() RR           { return &EID{*rr.Hdr.copyHeader(), rr.Endpoint} }
+func (rr *EID) String() string     { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
+func (rr *EID) len() int           { return rr.Hdr.len() + len(rr.Endpoint)/2 }
+
+type NIMLOC struct {
+	Hdr     RR_Header
+	Locator string `dns:"hex"`
+}
+
+func (rr *NIMLOC) Header() *RR_Header { return &rr.Hdr }
+func (rr *NIMLOC) copy() RR           { return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator} }
+func (rr *NIMLOC) String() string     { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
+func (rr *NIMLOC) len() int           { return rr.Hdr.len() + len(rr.Locator)/2 }
+
+type OPENPGPKEY struct {
+	Hdr       RR_Header
+	PublicKey string `dns:"base64"`
+}
+
+func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *OPENPGPKEY) copy() RR           { return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey} }
+func (rr *OPENPGPKEY) String() string     { return rr.Hdr.String() + rr.PublicKey }
+func (rr *OPENPGPKEY) len() int {
+	return rr.Hdr.len() + base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+}
+
+// TimeToString translates the RRSIG's incep. and expir. times to the
+// string representation used when printing the record.
+// It takes serial arithmetic (RFC 1982) into account.
+func TimeToString(t uint32) string {
+	mod := ((int64(t) - time.Now().Unix()) / year68) - 1
+	if mod < 0 {
+		mod = 0
+	}
+	ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
+	return ti.Format("20060102150405")
+}
+
+// StringToTime translates the RRSIG's incep. and expir. times from
+// string values like "20110403154150" to an 32 bit integer.
+// It takes serial arithmetic (RFC 1982) into account.
+func StringToTime(s string) (uint32, error) {
+	t, e := time.Parse("20060102150405", s)
+	if e != nil {
+		return 0, e
+	}
+	mod := (t.Unix() / year68) - 1
+	if mod < 0 {
+		mod = 0
+	}
+	return uint32(t.Unix() - (mod * year68)), nil
+}
+
+// saltToString converts a NSECX salt to uppercase and
+// returns "-" when it is empty
+func saltToString(s string) string {
+	if len(s) == 0 {
+		return "-"
+	}
+	return strings.ToUpper(s)
+}
+
+func euiToString(eui uint64, bits int) (hex string) {
+	switch bits {
+	case 64:
+		hex = fmt.Sprintf("%16.16x", eui)
+		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
+			"-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16]
+	case 48:
+		hex = fmt.Sprintf("%12.12x", eui)
+		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
+			"-" + hex[8:10] + "-" + hex[10:12]
+	}
+	return
+}
+
+// copyIP returns a copy of ip.
+func copyIP(ip net.IP) net.IP {
+	p := make(net.IP, len(ip))
+	copy(p, ip)
+	return p
+}
+
+// Map of constructors for each RR type.
+var typeToRR = map[uint16]func() RR{
+	TypeA:          func() RR { return new(A) },
+	TypeAAAA:       func() RR { return new(AAAA) },
+	TypeAFSDB:      func() RR { return new(AFSDB) },
+	TypeCAA:        func() RR { return new(CAA) },
+	TypeCDS:        func() RR { return new(CDS) },
+	TypeCERT:       func() RR { return new(CERT) },
+	TypeCNAME:      func() RR { return new(CNAME) },
+	TypeDHCID:      func() RR { return new(DHCID) },
+	TypeDLV:        func() RR { return new(DLV) },
+	TypeDNAME:      func() RR { return new(DNAME) },
+	TypeKEY:        func() RR { return new(KEY) },
+	TypeDNSKEY:     func() RR { return new(DNSKEY) },
+	TypeDS:         func() RR { return new(DS) },
+	TypeEUI48:      func() RR { return new(EUI48) },
+	TypeEUI64:      func() RR { return new(EUI64) },
+	TypeGID:        func() RR { return new(GID) },
+	TypeGPOS:       func() RR { return new(GPOS) },
+	TypeEID:        func() RR { return new(EID) },
+	TypeHINFO:      func() RR { return new(HINFO) },
+	TypeHIP:        func() RR { return new(HIP) },
+	TypeIPSECKEY:   func() RR { return new(IPSECKEY) },
+	TypeKX:         func() RR { return new(KX) },
+	TypeL32:        func() RR { return new(L32) },
+	TypeL64:        func() RR { return new(L64) },
+	TypeLOC:        func() RR { return new(LOC) },
+	TypeLP:         func() RR { return new(LP) },
+	TypeMB:         func() RR { return new(MB) },
+	TypeMD:         func() RR { return new(MD) },
+	TypeMF:         func() RR { return new(MF) },
+	TypeMG:         func() RR { return new(MG) },
+	TypeMINFO:      func() RR { return new(MINFO) },
+	TypeMR:         func() RR { return new(MR) },
+	TypeMX:         func() RR { return new(MX) },
+	TypeNAPTR:      func() RR { return new(NAPTR) },
+	TypeNID:        func() RR { return new(NID) },
+	TypeNINFO:      func() RR { return new(NINFO) },
+	TypeNIMLOC:     func() RR { return new(NIMLOC) },
+	TypeNS:         func() RR { return new(NS) },
+	TypeNSAPPTR:    func() RR { return new(NSAPPTR) },
+	TypeNSEC3:      func() RR { return new(NSEC3) },
+	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
+	TypeNSEC:       func() RR { return new(NSEC) },
+	TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
+	TypeOPT:        func() RR { return new(OPT) },
+	TypePTR:        func() RR { return new(PTR) },
+	TypeRKEY:       func() RR { return new(RKEY) },
+	TypeRP:         func() RR { return new(RP) },
+	TypePX:         func() RR { return new(PX) },
+	TypeSIG:        func() RR { return new(SIG) },
+	TypeRRSIG:      func() RR { return new(RRSIG) },
+	TypeRT:         func() RR { return new(RT) },
+	TypeSOA:        func() RR { return new(SOA) },
+	TypeSPF:        func() RR { return new(SPF) },
+	TypeSRV:        func() RR { return new(SRV) },
+	TypeSSHFP:      func() RR { return new(SSHFP) },
+	TypeTA:         func() RR { return new(TA) },
+	TypeTALINK:     func() RR { return new(TALINK) },
+	TypeTKEY:       func() RR { return new(TKEY) },
+	TypeTLSA:       func() RR { return new(TLSA) },
+	TypeTSIG:       func() RR { return new(TSIG) },
+	TypeTXT:        func() RR { return new(TXT) },
+	TypeUID:        func() RR { return new(UID) },
+	TypeUINFO:      func() RR { return new(UINFO) },
+	TypeURI:        func() RR { return new(URI) },
+	TypeWKS:        func() RR { return new(WKS) },
+	TypeX25:        func() RR { return new(X25) },
+}
diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go
new file mode 100644
index 0000000000000000000000000000000000000000..fc86563744e27433bc40f454d8d79e4bf6eae840
--- /dev/null
+++ b/vendor/github.com/miekg/dns/udp.go
@@ -0,0 +1,58 @@
+// +build !windows
+
+package dns
+
+import (
+	"net"
+	"syscall"
+)
+
+// 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 }
+
+// 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
+// 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
+}
diff --git a/vendor/github.com/miekg/dns/udp_linux.go b/vendor/github.com/miekg/dns/udp_linux.go
new file mode 100644
index 0000000000000000000000000000000000000000..7a107857e13338f356410720bedcf9617714cefe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/udp_linux.go
@@ -0,0 +1,63 @@
+// +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 {
+		return err
+	}
+	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 {
+		return err
+	}
+	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 {
+		return false, err
+	}
+	return v6only == 1, nil
+}
+
+func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
+	file, err := conn.File()
+	if err != nil {
+		return nil, err
+	}
+	return syscall.Getsockname(int(file.Fd()))
+}
diff --git a/vendor/github.com/miekg/dns/udp_other.go b/vendor/github.com/miekg/dns/udp_other.go
new file mode 100644
index 0000000000000000000000000000000000000000..c38dd3e7f0edf4d39dec9b684bf4179bc75a69fd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/udp_other.go
@@ -0,0 +1,17 @@
+// +build !linux
+
+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 }
diff --git a/vendor/github.com/miekg/dns/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go
new file mode 100644
index 0000000000000000000000000000000000000000..2ce4b3300287bd11de3873d55c09b05c6d3f0be1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/udp_windows.go
@@ -0,0 +1,34 @@
+// +build windows
+
+package dns
+
+import "net"
+
+type SessionUDP struct {
+	raddr *net.UDPAddr
+}
+
+// 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) {
+	n, raddr, err := conn.ReadFrom(b)
+	if err != nil {
+		return n, nil, err
+	}
+	session := &SessionUDP{raddr.(*net.UDPAddr)}
+	return n, session, 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.WriteTo(b, session.raddr)
+	return n, err
+}
+
+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 {
+	return nil
+}
diff --git a/vendor/github.com/miekg/dns/update.go b/vendor/github.com/miekg/dns/update.go
new file mode 100644
index 0000000000000000000000000000000000000000..3539987ccb0b77558d1946647da81f865f287f27
--- /dev/null
+++ b/vendor/github.com/miekg/dns/update.go
@@ -0,0 +1,94 @@
+package dns
+
+// NameUsed sets the RRs in the prereq section to
+// "Name is in use" RRs. RFC 2136 section 2.4.4.
+func (u *Msg) NameUsed(rr []RR) {
+	u.Answer = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
+	}
+}
+
+// NameNotUsed sets the RRs in the prereq section to
+// "Name is in not use" RRs. RFC 2136 section 2.4.5.
+func (u *Msg) NameNotUsed(rr []RR) {
+	u.Answer = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}
+	}
+}
+
+// Used sets the RRs in the prereq section to
+// "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.
+func (u *Msg) Used(rr []RR) {
+	if len(u.Question) == 0 {
+		panic("dns: empty question section")
+	}
+	u.Answer = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Answer[i] = r
+		u.Answer[i].Header().Class = u.Question[0].Qclass
+	}
+}
+
+// RRsetUsed sets the RRs in the prereq section to
+// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
+func (u *Msg) RRsetUsed(rr []RR) {
+	u.Answer = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Answer[i] = r
+		u.Answer[i].Header().Class = ClassANY
+		u.Answer[i].Header().Ttl = 0
+		u.Answer[i].Header().Rdlength = 0
+	}
+}
+
+// RRsetNotUsed sets the RRs in the prereq section to
+// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
+func (u *Msg) RRsetNotUsed(rr []RR) {
+	u.Answer = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Answer[i] = r
+		u.Answer[i].Header().Class = ClassNONE
+		u.Answer[i].Header().Rdlength = 0
+		u.Answer[i].Header().Ttl = 0
+	}
+}
+
+// Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.
+func (u *Msg) Insert(rr []RR) {
+	if len(u.Question) == 0 {
+		panic("dns: empty question section")
+	}
+	u.Ns = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Ns[i] = r
+		u.Ns[i].Header().Class = u.Question[0].Qclass
+	}
+}
+
+// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
+func (u *Msg) RemoveRRset(rr []RR) {
+	u.Ns = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}}
+	}
+}
+
+// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
+func (u *Msg) RemoveName(rr []RR) {
+	u.Ns = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
+	}
+}
+
+// Remove creates a dynamic update packet deletes RR from the RRSset, see RFC 2136 section 2.5.4
+func (u *Msg) Remove(rr []RR) {
+	u.Ns = make([]RR, len(rr))
+	for i, r := range rr {
+		u.Ns[i] = r
+		u.Ns[i].Header().Class = ClassNONE
+		u.Ns[i].Header().Ttl = 0
+	}
+}
diff --git a/vendor/github.com/miekg/dns/xfr.go b/vendor/github.com/miekg/dns/xfr.go
new file mode 100644
index 0000000000000000000000000000000000000000..7d3a67b8e4516f9b71b8d277b6ff3e07a0bff48c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/xfr.go
@@ -0,0 +1,244 @@
+package dns
+
+import (
+	"time"
+)
+
+// Envelope is used when doing a zone transfer with a remote server.
+type Envelope struct {
+	RR    []RR  // The set of RRs in the answer section of the xfr reply message.
+	Error error // If something went wrong, this contains the error.
+}
+
+// A Transfer defines parameters that are used during a zone transfer.
+type Transfer struct {
+	*Conn
+	DialTimeout    time.Duration     // net.DialTimeout, 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
+	TsigSecret     map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+	tsigTimersOnly bool
+}
+
+// Think we need to away to stop the transfer
+
+// In performs an incoming transfer with the server in a.
+// If you would like to set the source IP, or some other attribute
+// of a Dialer for a Transfer, you can do so by specifying the attributes
+// in the Transfer.Conn:
+//
+//	d := net.Dialer{LocalAddr: transfer_source}
+//	con, err := d.Dial("tcp", master)
+//	dnscon := &dns.Conn{Conn:con}
+//	transfer = &dns.Transfer{Conn: dnscon}
+//	channel, err := transfer.In(message, master)
+//
+func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
+	timeout := dnsTimeout
+	if t.DialTimeout != 0 {
+		timeout = t.DialTimeout
+	}
+	if t.Conn == nil {
+		t.Conn, err = DialTimeout("tcp", a, timeout)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if err := t.WriteMsg(q); err != nil {
+		return nil, err
+	}
+	env = make(chan *Envelope)
+	go func() {
+		if q.Question[0].Qtype == TypeAXFR {
+			go t.inAxfr(q.Id, env)
+			return
+		}
+		if q.Question[0].Qtype == TypeIXFR {
+			go t.inIxfr(q.Id, env)
+			return
+		}
+	}()
+	return env, nil
+}
+
+func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
+	first := true
+	defer t.Close()
+	defer close(c)
+	timeout := dnsTimeout
+	if t.ReadTimeout != 0 {
+		timeout = t.ReadTimeout
+	}
+	for {
+		t.Conn.SetReadDeadline(time.Now().Add(timeout))
+		in, err := t.ReadMsg()
+		if err != nil {
+			c <- &Envelope{nil, err}
+			return
+		}
+		if id != in.Id {
+			c <- &Envelope{in.Answer, ErrId}
+			return
+		}
+		if first {
+			if !isSOAFirst(in) {
+				c <- &Envelope{in.Answer, ErrSoa}
+				return
+			}
+			first = !first
+			// only one answer that is SOA, receive more
+			if len(in.Answer) == 1 {
+				t.tsigTimersOnly = true
+				c <- &Envelope{in.Answer, nil}
+				continue
+			}
+		}
+
+		if !first {
+			t.tsigTimersOnly = true // Subsequent envelopes use this.
+			if isSOALast(in) {
+				c <- &Envelope{in.Answer, nil}
+				return
+			}
+			c <- &Envelope{in.Answer, nil}
+		}
+	}
+}
+
+func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
+	serial := uint32(0) // The first serial seen is the current server serial
+	first := true
+	defer t.Close()
+	defer close(c)
+	timeout := dnsTimeout
+	if t.ReadTimeout != 0 {
+		timeout = t.ReadTimeout
+	}
+	for {
+		t.SetReadDeadline(time.Now().Add(timeout))
+		in, err := t.ReadMsg()
+		if err != nil {
+			c <- &Envelope{nil, err}
+			return
+		}
+		if id != in.Id {
+			c <- &Envelope{in.Answer, ErrId}
+			return
+		}
+		if first {
+			// A single SOA RR signals "no changes"
+			if len(in.Answer) == 1 && isSOAFirst(in) {
+				c <- &Envelope{in.Answer, nil}
+				return
+			}
+
+			// Check if the returned answer is ok
+			if !isSOAFirst(in) {
+				c <- &Envelope{in.Answer, ErrSoa}
+				return
+			}
+			// This serial is important
+			serial = in.Answer[0].(*SOA).Serial
+			first = !first
+		}
+
+		// 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}
+					return
+				}
+			}
+			c <- &Envelope{in.Answer, nil}
+		}
+	}
+}
+
+// Out performs an outgoing transfer with the client connecting in w.
+// Basic use pattern:
+//
+//	ch := make(chan *dns.Envelope)
+//	tr := new(dns.Transfer)
+//	tr.Out(w, r, ch)
+//	c <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
+//	close(ch)
+//	w.Hijack()
+//	// w.Close() // Client closes connection
+//
+// The server is responsible for sending the correct sequence of RRs through the
+// channel ch.
+func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
+	for x := range ch {
+		r := new(Msg)
+		// Compress?
+		r.SetReply(q)
+		r.Authoritative = true
+		// assume it fits TODO(miek): fix
+		r.Answer = append(r.Answer, x.RR...)
+		if err := w.WriteMsg(r); err != nil {
+			return err
+		}
+	}
+	w.TsigTimersOnly(true)
+	return nil
+}
+
+// ReadMsg reads a message from the transfer connection t.
+func (t *Transfer) ReadMsg() (*Msg, error) {
+	m := new(Msg)
+	p := make([]byte, MaxMsgSize)
+	n, err := t.Read(p)
+	if err != nil && n == 0 {
+		return nil, err
+	}
+	p = p[:n]
+	if err := m.Unpack(p); err != nil {
+		return nil, err
+	}
+	if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
+		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
+			return m, ErrSecret
+		}
+		// Need to work on the original message p, as that was used to calculate the tsig.
+		err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+		t.tsigRequestMAC = ts.MAC
+	}
+	return m, err
+}
+
+// WriteMsg writes a message through the transfer connection t.
+func (t *Transfer) WriteMsg(m *Msg) (err error) {
+	var out []byte
+	if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
+		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
+			return ErrSecret
+		}
+		out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+	} else {
+		out, err = m.Pack()
+	}
+	if err != nil {
+		return err
+	}
+	if _, err = t.Write(out); err != nil {
+		return err
+	}
+	return nil
+}
+
+func isSOAFirst(in *Msg) bool {
+	if len(in.Answer) > 0 {
+		return in.Answer[0].Header().Rrtype == TypeSOA
+	}
+	return false
+}
+
+func isSOALast(in *Msg) bool {
+	if len(in.Answer) > 0 {
+		return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
+	}
+	return false
+}
diff --git a/vendor/github.com/miekg/dns/zgenerate.go b/vendor/github.com/miekg/dns/zgenerate.go
new file mode 100644
index 0000000000000000000000000000000000000000..c506e962666b0dfdc3606523cf22fa96b3a82632
--- /dev/null
+++ b/vendor/github.com/miekg/dns/zgenerate.go
@@ -0,0 +1,158 @@
+package dns
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// Parse the $GENERATE statement as used in BIND9 zones.
+// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
+// We are called after '$GENERATE '. After which we expect:
+// * the range (12-24/2)
+// * lhs (ownername)
+// * [[ttl][class]]
+// * type
+// * rhs (rdata)
+// But we are lazy here, only the range is parsed *all* occurences
+// of $ after that are interpreted.
+// Any error are returned as a string value, the empty string signals
+// "no error".
+func generate(l lex, c chan lex, t chan *Token, o string) string {
+	step := 1
+	if i := strings.IndexAny(l.token, "/"); i != -1 {
+		if i+1 == len(l.token) {
+			return "bad step in $GENERATE range"
+		}
+		if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
+			if s < 0 {
+				return "bad step in $GENERATE range"
+			}
+			step = s
+		} else {
+			return "bad step in $GENERATE range"
+		}
+		l.token = l.token[:i]
+	}
+	sx := strings.SplitN(l.token, "-", 2)
+	if len(sx) != 2 {
+		return "bad start-stop in $GENERATE range"
+	}
+	start, err := strconv.Atoi(sx[0])
+	if err != nil {
+		return "bad start in $GENERATE range"
+	}
+	end, err := strconv.Atoi(sx[1])
+	if err != nil {
+		return "bad stop in $GENERATE range"
+	}
+	if end < 0 || start < 0 || end < start {
+		return "bad range in $GENERATE range"
+	}
+
+	<-c // _BLANK
+	// Create a complete new string, which we then parse again.
+	s := ""
+BuildRR:
+	l = <-c
+	if l.value != zNewline && l.value != zEOF {
+		s += l.token
+		goto BuildRR
+	}
+	for i := start; i <= end; i += step {
+		var (
+			escape bool
+			dom    bytes.Buffer
+			mod    string
+			err    string
+			offset int
+		)
+
+		for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
+			switch s[j] {
+			case '\\':
+				if escape {
+					dom.WriteByte('\\')
+					escape = false
+					continue
+				}
+				escape = true
+			case '$':
+				mod = "%d"
+				offset = 0
+				if escape {
+					dom.WriteByte('$')
+					escape = false
+					continue
+				}
+				escape = false
+				if j+1 >= len(s) { // End of the string
+					dom.WriteString(fmt.Sprintf(mod, i+offset))
+					continue
+				} else {
+					if s[j+1] == '$' {
+						dom.WriteByte('$')
+						j++
+						continue
+					}
+				}
+				// Search for { and }
+				if s[j+1] == '{' { // Modifier block
+					sep := strings.Index(s[j+2:], "}")
+					if sep == -1 {
+						return "bad modifier in $GENERATE"
+					}
+					mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
+					if err != "" {
+						return err
+					}
+					j += 2 + sep // Jump to it
+				}
+				dom.WriteString(fmt.Sprintf(mod, i+offset))
+			default:
+				if escape { // Pretty useless here
+					escape = false
+					continue
+				}
+				dom.WriteByte(s[j])
+			}
+		}
+		// Re-parse the RR and send it on the current channel t
+		rx, e := NewRR("$ORIGIN " + o + "\n" + dom.String())
+		if e != nil {
+			return e.(*ParseError).err
+		}
+		t <- &Token{RR: rx}
+		// Its more efficient to first built the rrlist and then parse it in
+		// one go! But is this a problem?
+	}
+	return ""
+}
+
+// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
+func modToPrintf(s string) (string, int, string) {
+	xs := strings.SplitN(s, ",", 3)
+	if len(xs) != 3 {
+		return "", 0, "bad modifier in $GENERATE"
+	}
+	// xs[0] is offset, xs[1] is width, xs[2] is base
+	if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
+		return "", 0, "bad base in $GENERATE"
+	}
+	offset, err := strconv.Atoi(xs[0])
+	if err != nil || offset > 255 {
+		return "", 0, "bad offset in $GENERATE"
+	}
+	width, err := strconv.Atoi(xs[1])
+	if err != nil || width > 255 {
+		return "", offset, "bad width in $GENERATE"
+	}
+	switch {
+	case width < 0:
+		return "", offset, "bad width in $GENERATE"
+	case width == 0:
+		return "%" + xs[1] + xs[2], offset, ""
+	}
+	return "%0" + xs[1] + xs[2], offset, ""
+}
diff --git a/vendor/github.com/miekg/dns/zscan.go b/vendor/github.com/miekg/dns/zscan.go
new file mode 100644
index 0000000000000000000000000000000000000000..40ba35c36dac980d081275f394992213f0bb9145
--- /dev/null
+++ b/vendor/github.com/miekg/dns/zscan.go
@@ -0,0 +1,972 @@
+package dns
+
+import (
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"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 maxUint16 = 1<<16 - 1
+
+// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
+// * Add ownernames if they are left blank;
+// * Suppress sequences of spaces;
+// * Make each RR fit on one line (_NEWLINE is send as last)
+// * Handle comments: ;
+// * Handle braces - anywhere.
+const (
+	// Zonefile
+	zEOF = iota
+	zString
+	zBlank
+	zQuote
+	zNewline
+	zRrtpe
+	zOwner
+	zClass
+	zDirOrigin   // $ORIGIN
+	zDirTtl      // $TTL
+	zDirInclude  // $INCLUDE
+	zDirGenerate // $GENERATE
+
+	// Privatekey file
+	zValue
+	zKey
+
+	zExpectOwnerDir      // Ownername
+	zExpectOwnerBl       // Whitespace after the ownername
+	zExpectAny           // Expect rrtype, ttl or class
+	zExpectAnyNoClass    // Expect rrtype or ttl
+	zExpectAnyNoClassBl  // The whitespace after _EXPECT_ANY_NOCLASS
+	zExpectAnyNoTtl      // Expect rrtype or class
+	zExpectAnyNoTtlBl    // Whitespace after _EXPECT_ANY_NOTTL
+	zExpectRrtype        // Expect rrtype
+	zExpectRrtypeBl      // Whitespace BEFORE rrtype
+	zExpectRdata         // The first element of the rdata
+	zExpectDirTtlBl      // Space after directive $TTL
+	zExpectDirTtl        // Directive $TTL
+	zExpectDirOriginBl   // Space after directive $ORIGIN
+	zExpectDirOrigin     // Directive $ORIGIN
+	zExpectDirIncludeBl  // Space after directive $INCLUDE
+	zExpectDirInclude    // Directive $INCLUDE
+	zExpectDirGenerate   // Directive $GENERATE
+	zExpectDirGenerateBl // Space after directive $GENERATE
+)
+
+// ParseError is a parsing error. It contains the parse error and the location in the io.Reader
+// where the error occured.
+type ParseError struct {
+	file string
+	err  string
+	lex  lex
+}
+
+func (e *ParseError) Error() (s string) {
+	if e.file != "" {
+		s = e.file + ": "
+	}
+	s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " +
+		strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
+	return
+}
+
+type lex struct {
+	token      string // text of the token
+	tokenUpper string // uppercase text of the token
+	length     int    // lenght of the token
+	err        bool   // when true, token text has lexer error
+	value      uint8  // value: zString, _BLANK, etc.
+	line       int    // line in the file
+	column     int    // column in the file
+	torc       uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
+	comment    string // any comment text seen
+}
+
+// Token holds the token that are returned when a zone file is parsed.
+type Token struct {
+	// The scanned resource record when error is not nil.
+	RR
+	// When an error occured, this has the error specifics.
+	Error *ParseError
+	// A potential comment positioned after the RR and on the same line.
+	Comment string
+}
+
+// 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
+// defaults to IN and TTL defaults to 3600. The full zone file syntax
+// like $TTL, $ORIGIN, etc. is supported. All fields of the returned
+// RR are set, except RR.Header().Rdlength which is set to 0.
+func NewRR(s string) (RR, error) {
+	if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
+		return ReadRR(strings.NewReader(s+"\n"), "")
+	}
+	return ReadRR(strings.NewReader(s), "")
+}
+
+// ReadRR reads the RR contained in q.
+// See NewRR for more documentation.
+func ReadRR(q io.Reader, filename string) (RR, error) {
+	r := <-parseZoneHelper(q, ".", filename, 1)
+	if r == nil {
+		return nil, nil
+	}
+
+	if r.Error != nil {
+		return nil, r.Error
+	}
+	return r.RR, nil
+}
+
+// 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.
+// If there is an error the RR is nil. The string file is only used
+// in error reporting. The string origin is used as the initial origin, as
+// if the file would start with: $ORIGIN origin .
+// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
+// The channel t is closed by ParseZone when the end of r is reached.
+//
+// Basic usage pattern when reading from a string (z) containing the
+// zone data:
+//
+//	for x := range dns.ParseZone(strings.NewReader(z), "", "") {
+//		if x.Error != nil {
+//			// Do something with x.RR
+//		}
+//	}
+//
+// Comments specified after an RR (and on the same line!) are returned too:
+//
+//	foo. IN A 10.0.0.1 ; this is a comment
+//
+// The text "; this is comment" is returned in Token.Comment. Comments inside the
+// RR are discarded. Comments on a line by themselves are discarded too.
+func ParseZone(r io.Reader, origin, file string) chan *Token {
+	return parseZoneHelper(r, origin, file, 10000)
+}
+
+func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
+	t := make(chan *Token, chansize)
+	go parseZone(r, origin, file, t, 0)
+	return t
+}
+
+func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
+	defer func() {
+		if include == 0 {
+			close(t)
+		}
+	}()
+	s := scanInit(r)
+	c := make(chan lex)
+	// Start the lexer
+	go zlexer(s, c)
+	// 6 possible beginnings of a line, _ is a space
+	// 0. zRRTYPE                              -> all omitted until the rrtype
+	// 1. zOwner _ zRrtype                     -> class/ttl omitted
+	// 2. zOwner _ zString _ zRrtype           -> class omitted
+	// 3. zOwner _ zString _ zClass  _ zRrtype -> ttl/class
+	// 4. zOwner _ zClass  _ zRrtype           -> ttl omitted
+	// 5. zOwner _ zClass  _ zString _ zRrtype -> class/ttl (reversed)
+	// After detecting these, we know the zRrtype so we can jump to functions
+	// handling the rdata for each of these types.
+
+	if origin == "" {
+		origin = "."
+	}
+	origin = Fqdn(origin)
+	if _, ok := IsDomainName(origin); !ok {
+		t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
+		return
+	}
+
+	st := zExpectOwnerDir // initial state
+	var h RR_Header
+	var defttl uint32 = defaultTtl
+	var prevName string
+	for l := range c {
+		// Lexer spotted an error already
+		if l.err == true {
+			t <- &Token{Error: &ParseError{f, l.token, l}}
+			return
+
+		}
+		switch st {
+		case zExpectOwnerDir:
+			// We can also expect a directive, like $TTL or $ORIGIN
+			h.Ttl = defttl
+			h.Class = ClassINET
+			switch l.value {
+			case zNewline:
+				st = zExpectOwnerDir
+			case zOwner:
+				h.Name = l.token
+				if l.token[0] == '@' {
+					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 {
+					t <- &Token{Error: &ParseError{f, "bad owner name", l}}
+					return
+				}
+				prevName = h.Name
+				st = zExpectOwnerBl
+			case zDirTtl:
+				st = zExpectDirTtlBl
+			case zDirOrigin:
+				st = zExpectDirOriginBl
+			case zDirInclude:
+				st = zExpectDirIncludeBl
+			case zDirGenerate:
+				st = zExpectDirGenerateBl
+			case zRrtpe:
+				h.Name = prevName
+				h.Rrtype = l.torc
+				st = zExpectRdata
+			case zClass:
+				h.Name = prevName
+				h.Class = l.torc
+				st = zExpectAnyNoClassBl
+			case zBlank:
+				// Discard, can happen when there is nothing on the
+				// line except the RR type
+			case zString:
+				ttl, ok := stringToTtl(l.token)
+				if !ok {
+					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+					return
+				}
+				h.Ttl = ttl
+				// Don't about the defttl, we should take the $TTL value
+				// defttl = ttl
+				st = zExpectAnyNoTtlBl
+
+			default:
+				t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
+				return
+			}
+		case zExpectDirIncludeBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
+				return
+			}
+			st = zExpectDirInclude
+		case zExpectDirInclude:
+			if l.value != zString {
+				t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
+				return
+			}
+			neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
+			l := <-c
+			switch l.value {
+			case zBlank:
+				l := <-c
+				if l.value == zString {
+					if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
+						t <- &Token{Error: &ParseError{f, "bad origin name", l}}
+						return
+					}
+					// a new origin is specified.
+					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:
+				// Ok
+			default:
+				t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
+				return
+			}
+			// Start with the new file
+			r1, e1 := os.Open(l.token)
+			if e1 != nil {
+				t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
+				return
+			}
+			if include+1 > 7 {
+				t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
+				return
+			}
+			parseZone(r1, l.token, neworigin, t, include+1)
+			st = zExpectOwnerDir
+		case zExpectDirTtlBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
+				return
+			}
+			st = zExpectDirTtl
+		case zExpectDirTtl:
+			if l.value != zString {
+				t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
+				return
+			}
+			if e, _ := slurpRemainder(c, f); e != nil {
+				t <- &Token{Error: e}
+				return
+			}
+			ttl, ok := stringToTtl(l.token)
+			if !ok {
+				t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
+				return
+			}
+			defttl = ttl
+			st = zExpectOwnerDir
+		case zExpectDirOriginBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
+				return
+			}
+			st = zExpectDirOrigin
+		case zExpectDirOrigin:
+			if l.value != zString {
+				t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
+				return
+			}
+			if e, _ := slurpRemainder(c, f); e != nil {
+				t <- &Token{Error: e}
+			}
+			if _, ok := IsDomainName(l.token); !ok {
+				t <- &Token{Error: &ParseError{f, "bad origin name", l}}
+				return
+			}
+			if l.token[l.length-1] != '.' {
+				if origin != "." { // Prevent .. endings
+					origin = l.token + "." + origin
+				} else {
+					origin = l.token + origin
+				}
+			} else {
+				origin = l.token
+			}
+			st = zExpectOwnerDir
+		case zExpectDirGenerateBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
+				return
+			}
+			st = zExpectDirGenerate
+		case zExpectDirGenerate:
+			if l.value != zString {
+				t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
+				return
+			}
+			if e := generate(l, c, t, origin); e != "" {
+				t <- &Token{Error: &ParseError{f, e, l}}
+				return
+			}
+			st = zExpectOwnerDir
+		case zExpectOwnerBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
+				return
+			}
+			st = zExpectAny
+		case zExpectAny:
+			switch l.value {
+			case zRrtpe:
+				h.Rrtype = l.torc
+				st = zExpectRdata
+			case zClass:
+				h.Class = l.torc
+				st = zExpectAnyNoClassBl
+			case zString:
+				ttl, ok := stringToTtl(l.token)
+				if !ok {
+					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+					return
+				}
+				h.Ttl = ttl
+				// defttl = ttl // don't set the defttl here
+				st = zExpectAnyNoTtlBl
+			default:
+				t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
+				return
+			}
+		case zExpectAnyNoClassBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank before class", l}}
+				return
+			}
+			st = zExpectAnyNoClass
+		case zExpectAnyNoTtlBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
+				return
+			}
+			st = zExpectAnyNoTtl
+		case zExpectAnyNoTtl:
+			switch l.value {
+			case zClass:
+				h.Class = l.torc
+				st = zExpectRrtypeBl
+			case zRrtpe:
+				h.Rrtype = l.torc
+				st = zExpectRdata
+			default:
+				t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
+				return
+			}
+		case zExpectAnyNoClass:
+			switch l.value {
+			case zString:
+				ttl, ok := stringToTtl(l.token)
+				if !ok {
+					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+					return
+				}
+				h.Ttl = ttl
+				// defttl = ttl // don't set the def ttl anymore
+				st = zExpectRrtypeBl
+			case zRrtpe:
+				h.Rrtype = l.torc
+				st = zExpectRdata
+			default:
+				t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
+				return
+			}
+		case zExpectRrtypeBl:
+			if l.value != zBlank {
+				t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
+				return
+			}
+			st = zExpectRrtype
+		case zExpectRrtype:
+			if l.value != zRrtpe {
+				t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
+				return
+			}
+			h.Rrtype = l.torc
+			st = zExpectRdata
+		case zExpectRdata:
+			r, e, c1 := setRR(h, c, origin, f)
+			if e != nil {
+				// If e.lex is nil than we have encounter a unknown RR type
+				// in that case we substitute our current lex token
+				if e.lex.token == "" && e.lex.value == 0 {
+					e.lex = l // Uh, dirty
+				}
+				t <- &Token{Error: e}
+				return
+			}
+			t <- &Token{RR: r, Comment: c1}
+			st = zExpectOwnerDir
+		}
+	}
+	// If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this
+	// is not an error, because an empty zone file is still a zone file.
+}
+
+// zlexer scans the sourcefile and returns tokens on the channel c.
+func zlexer(s *scan, c chan lex) {
+	var l lex
+	str := make([]byte, maxTok) // Should be enough for any token
+	stri := 0                   // Offset in str (0 means empty)
+	com := make([]byte, maxTok) // Hold comment text
+	comi := 0
+	quote := false
+	escape := false
+	space := false
+	commt := false
+	rrtype := false
+	owner := true
+	brace := 0
+	x, err := s.tokenText()
+	defer close(c)
+	for err == nil {
+		l.column = s.position.Column
+		l.line = s.position.Line
+		if stri >= maxTok {
+			l.token = "token length insufficient for parsing"
+			l.err = true
+			debug.Printf("[%+v]", l.token)
+			c <- l
+			return
+		}
+		if comi >= maxTok {
+			l.token = "comment length insufficient for parsing"
+			l.err = true
+			debug.Printf("[%+v]", l.token)
+			c <- l
+			return
+		}
+
+		switch x {
+		case ' ', '\t':
+			if escape {
+				escape = false
+				str[stri] = x
+				stri++
+				break
+			}
+			if quote {
+				// Inside quotes this is legal
+				str[stri] = x
+				stri++
+				break
+			}
+			if commt {
+				com[comi] = x
+				comi++
+				break
+			}
+			if stri == 0 {
+				// Space directly in the beginning, handled in the grammar
+			} else if owner {
+				// If we have a string and its the first, make it an owner
+				l.value = zOwner
+				l.token = string(str[:stri])
+				l.tokenUpper = strings.ToUpper(l.token)
+				l.length = stri
+				// escape $... start with a \ not a $, so this will work
+				switch l.tokenUpper {
+				case "$TTL":
+					l.value = zDirTtl
+				case "$ORIGIN":
+					l.value = zDirOrigin
+				case "$INCLUDE":
+					l.value = zDirInclude
+				case "$GENERATE":
+					l.value = zDirGenerate
+				}
+				debug.Printf("[7 %+v]", l.token)
+				c <- l
+			} else {
+				l.value = zString
+				l.token = string(str[:stri])
+				l.tokenUpper = strings.ToUpper(l.token)
+				l.length = stri
+				if !rrtype {
+					if t, ok := StringToType[l.tokenUpper]; ok {
+						l.value = zRrtpe
+						l.torc = t
+						rrtype = true
+					} else {
+						if strings.HasPrefix(l.tokenUpper, "TYPE") {
+							t, ok := typeToInt(l.token)
+							if !ok {
+								l.token = "unknown RR type"
+								l.err = true
+								c <- l
+								return
+							}
+							l.value = zRrtpe
+							l.torc = t
+						}
+					}
+					if t, ok := StringToClass[l.tokenUpper]; ok {
+						l.value = zClass
+						l.torc = t
+					} else {
+						if strings.HasPrefix(l.tokenUpper, "CLASS") {
+							t, ok := classToInt(l.token)
+							if !ok {
+								l.token = "unknown class"
+								l.err = true
+								c <- l
+								return
+							}
+							l.value = zClass
+							l.torc = t
+						}
+					}
+				}
+				debug.Printf("[6 %+v]", l.token)
+				c <- l
+			}
+			stri = 0
+			// I reverse space stuff here
+			if !space && !commt {
+				l.value = zBlank
+				l.token = " "
+				l.length = 1
+				debug.Printf("[5 %+v]", l.token)
+				c <- l
+			}
+			owner = false
+			space = true
+		case ';':
+			if escape {
+				escape = false
+				str[stri] = x
+				stri++
+				break
+			}
+			if quote {
+				// Inside quotes this is legal
+				str[stri] = x
+				stri++
+				break
+			}
+			if stri > 0 {
+				l.value = zString
+				l.token = string(str[:stri])
+				l.length = stri
+				debug.Printf("[4 %+v]", l.token)
+				c <- l
+				stri = 0
+			}
+			commt = true
+			com[comi] = ';'
+			comi++
+		case '\r':
+			escape = false
+			if quote {
+				str[stri] = x
+				stri++
+				break
+			}
+			// discard if outside of quotes
+		case '\n':
+			escape = false
+			// Escaped newline
+			if quote {
+				str[stri] = x
+				stri++
+				break
+			}
+			// inside quotes this is legal
+			if commt {
+				// Reset a comment
+				commt = false
+				rrtype = false
+				stri = 0
+				// If not in a brace this ends the comment AND the RR
+				if brace == 0 {
+					owner = true
+					owner = true
+					l.value = zNewline
+					l.token = "\n"
+					l.length = 1
+					l.comment = string(com[:comi])
+					debug.Printf("[3 %+v %+v]", l.token, l.comment)
+					c <- l
+					l.comment = ""
+					comi = 0
+					break
+				}
+				com[comi] = ' ' // convert newline to space
+				comi++
+				break
+			}
+
+			if brace == 0 {
+				// If there is previous text, we should output it here
+				if stri != 0 {
+					l.value = zString
+					l.token = string(str[:stri])
+					l.tokenUpper = strings.ToUpper(l.token)
+
+					l.length = stri
+					if !rrtype {
+						if t, ok := StringToType[l.tokenUpper]; ok {
+							l.value = zRrtpe
+							l.torc = t
+							rrtype = true
+						}
+					}
+					debug.Printf("[2 %+v]", l.token)
+					c <- l
+				}
+				l.value = zNewline
+				l.token = "\n"
+				l.length = 1
+				debug.Printf("[1 %+v]", l.token)
+				c <- l
+				stri = 0
+				commt = false
+				rrtype = false
+				owner = true
+				comi = 0
+			}
+		case '\\':
+			// comments do not get escaped chars, everything is copied
+			if commt {
+				com[comi] = x
+				comi++
+				break
+			}
+			// something already escaped must be in string
+			if escape {
+				str[stri] = x
+				stri++
+				escape = false
+				break
+			}
+			// something escaped outside of string gets added to string
+			str[stri] = x
+			stri++
+			escape = true
+		case '"':
+			if commt {
+				com[comi] = x
+				comi++
+				break
+			}
+			if escape {
+				str[stri] = x
+				stri++
+				escape = false
+				break
+			}
+			space = false
+			// send previous gathered text and the quote
+			if stri != 0 {
+				l.value = zString
+				l.token = string(str[:stri])
+				l.length = stri
+
+				debug.Printf("[%+v]", l.token)
+				c <- l
+				stri = 0
+			}
+
+			// send quote itself as separate token
+			l.value = zQuote
+			l.token = "\""
+			l.length = 1
+			c <- l
+			quote = !quote
+		case '(', ')':
+			if commt {
+				com[comi] = x
+				comi++
+				break
+			}
+			if escape {
+				str[stri] = x
+				stri++
+				escape = false
+				break
+			}
+			if quote {
+				str[stri] = x
+				stri++
+				break
+			}
+			switch x {
+			case ')':
+				brace--
+				if brace < 0 {
+					l.token = "extra closing brace"
+					l.err = true
+					debug.Printf("[%+v]", l.token)
+					c <- l
+					return
+				}
+			case '(':
+				brace++
+			}
+		default:
+			escape = false
+			if commt {
+				com[comi] = x
+				comi++
+				break
+			}
+			str[stri] = x
+			stri++
+			space = false
+		}
+		x, err = s.tokenText()
+	}
+	if stri > 0 {
+		// Send remainder
+		l.token = string(str[:stri])
+		l.length = stri
+		l.value = zString
+		debug.Printf("[%+v]", l.token)
+		c <- l
+	}
+}
+
+// Extract the class number from CLASSxx
+func classToInt(token string) (uint16, bool) {
+	offset := 5
+	if len(token) < offset+1 {
+		return 0, false
+	}
+	class, ok := strconv.Atoi(token[offset:])
+	if ok != nil || class > maxUint16 {
+		return 0, false
+	}
+	return uint16(class), true
+}
+
+// Extract the rr number from TYPExxx
+func typeToInt(token string) (uint16, bool) {
+	offset := 4
+	if len(token) < offset+1 {
+		return 0, false
+	}
+	typ, ok := strconv.Atoi(token[offset:])
+	if ok != nil || typ > maxUint16 {
+		return 0, false
+	}
+	return uint16(typ), true
+}
+
+// Parse things like 2w, 2m, etc, Return the time in seconds.
+func stringToTtl(token string) (uint32, bool) {
+	s := uint32(0)
+	i := uint32(0)
+	for _, c := range token {
+		switch c {
+		case 's', 'S':
+			s += i
+			i = 0
+		case 'm', 'M':
+			s += i * 60
+			i = 0
+		case 'h', 'H':
+			s += i * 60 * 60
+			i = 0
+		case 'd', 'D':
+			s += i * 60 * 60 * 24
+			i = 0
+		case 'w', 'W':
+			s += i * 60 * 60 * 24 * 7
+			i = 0
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			i *= 10
+			i += uint32(c) - '0'
+		default:
+			return 0, false
+		}
+	}
+	return s + i, true
+}
+
+// Parse LOC records' <digits>[.<digits>][mM] into a
+// mantissa exponent format. Token should contain the entire
+// string (i.e. no spaces allowed)
+func stringToCm(token string) (e, m uint8, ok bool) {
+	if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
+		token = token[0 : len(token)-1]
+	}
+	s := strings.SplitN(token, ".", 2)
+	var meters, cmeters, val int
+	var err error
+	switch len(s) {
+	case 2:
+		if cmeters, err = strconv.Atoi(s[1]); err != nil {
+			return
+		}
+		fallthrough
+	case 1:
+		if meters, err = strconv.Atoi(s[0]); err != nil {
+			return
+		}
+	case 0:
+		// huh?
+		return 0, 0, false
+	}
+	ok = true
+	if meters > 0 {
+		e = 2
+		val = meters
+	} else {
+		e = 0
+		val = cmeters
+	}
+	for val > 10 {
+		e++
+		val /= 10
+	}
+	if e > 9 {
+		ok = false
+	}
+	m = uint8(val)
+	return
+}
+
+func appendOrigin(name, origin string) string {
+	if origin == "." {
+		return name + origin
+	}
+	return name + "." + origin
+}
+
+// LOC record helper function
+func locCheckNorth(token string, latitude uint32) (uint32, bool) {
+	switch token {
+	case "n", "N":
+		return LOC_EQUATOR + latitude, true
+	case "s", "S":
+		return LOC_EQUATOR - latitude, true
+	}
+	return latitude, false
+}
+
+// LOC record helper function
+func locCheckEast(token string, longitude uint32) (uint32, bool) {
+	switch token {
+	case "e", "E":
+		return LOC_EQUATOR + longitude, true
+	case "w", "W":
+		return LOC_EQUATOR - longitude, true
+	}
+	return longitude, false
+}
+
+// "Eat" the rest of the "line". Return potential comments
+func slurpRemainder(c chan lex, f string) (*ParseError, string) {
+	l := <-c
+	com := ""
+	switch l.value {
+	case zBlank:
+		l = <-c
+		com = l.comment
+		if l.value != zNewline && l.value != zEOF {
+			return &ParseError{f, "garbage after rdata", l}, ""
+		}
+	case zNewline:
+		com = l.comment
+	case zEOF:
+	default:
+		return &ParseError{f, "garbage after rdata", l}, ""
+	}
+	return nil, com
+}
+
+// Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64"
+// Used for NID and L64 record.
+func stringToNodeID(l lex) (uint64, *ParseError) {
+	if len(l.token) < 19 {
+		return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+	}
+	// There must be three colons at fixes postitions, if not its a parse error
+	if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' {
+		return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+	}
+	s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19]
+	u, e := strconv.ParseUint(s, 16, 64)
+	if e != nil {
+		return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+	}
+	return u, nil
+}
diff --git a/vendor/github.com/miekg/dns/zscan_rr.go b/vendor/github.com/miekg/dns/zscan_rr.go
new file mode 100644
index 0000000000000000000000000000000000000000..a2db008fa98b274de13f04c991819dc78b2d74e8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/zscan_rr.go
@@ -0,0 +1,2270 @@
+package dns
+
+import (
+	"encoding/base64"
+	"net"
+	"strconv"
+	"strings"
+)
+
+type parserFunc struct {
+	// Func defines the function that parses the tokens and returns the RR
+	// or an error. The last string contains any comments in the line as
+	// they returned by the lexer as well.
+	Func func(h RR_Header, c chan lex, origin string, file string) (RR, *ParseError, string)
+	// Signals if the RR ending is of variable length, like TXT or records
+	// that have Hexadecimal or Base64 as their last element in the Rdata. Records
+	// that have a fixed ending or for instance A, AAAA, SOA and etc.
+	Variable bool
+}
+
+// Parse the rdata of each rrtype.
+// All data from the channel c is either zString or zBlank.
+// After the rdata there may come a zBlank and then a zNewline
+// or immediately a zNewline. If this is not the case we flag
+// an *ParseError: garbage after rdata.
+func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	parserfunc, ok := typeToparserFunc[h.Rrtype]
+	if ok {
+		r, e, cm := parserfunc.Func(h, c, o, f)
+		if parserfunc.Variable {
+			return r, e, cm
+		}
+		if e != nil {
+			return nil, e, ""
+		}
+		e, cm = slurpRemainder(c, f)
+		if e != nil {
+			return nil, e, ""
+		}
+		return r, nil, cm
+	}
+	// RFC3957 RR (Unknown RR handling)
+	return setRFC3597(h, c, o, f)
+}
+
+// A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
+// or an error
+func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) {
+	s := ""
+	l := <-c // zString
+	for l.value != zNewline && l.value != zEOF {
+		if l.err {
+			return s, &ParseError{f, errstr, l}, ""
+		}
+		switch l.value {
+		case zString:
+			s += l.token
+		case zBlank: // Ok
+		default:
+			return "", &ParseError{f, errstr, l}, ""
+		}
+		l = <-c
+	}
+	return s, nil, l.comment
+}
+
+// A remainder of the rdata with embedded spaces, return the parsed string slice (sans the spaces)
+// or an error
+func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) {
+	// Get the remaining data until we see a zNewline
+	quote := false
+	l := <-c
+	var s []string
+	if l.err {
+		return s, &ParseError{f, errstr, l}, ""
+	}
+	switch l.value == zQuote {
+	case true: // A number of quoted string
+		s = make([]string, 0)
+		empty := true
+		for l.value != zNewline && l.value != zEOF {
+			if l.err {
+				return nil, &ParseError{f, errstr, l}, ""
+			}
+			switch l.value {
+			case zString:
+				empty = false
+				if len(l.token) > 255 {
+					// split up tokens that are larger than 255 into 255-chunks
+					sx := []string{}
+					p, i := 0, 255
+					for {
+						if i <= len(l.token) {
+							sx = append(sx, l.token[p:i])
+						} else {
+							sx = append(sx, l.token[p:])
+							break
+
+						}
+						p, i = p+255, i+255
+					}
+					s = append(s, sx...)
+					break
+				}
+
+				s = append(s, l.token)
+			case zBlank:
+				if quote {
+					// zBlank can only be seen in between txt parts.
+					return nil, &ParseError{f, errstr, l}, ""
+				}
+			case zQuote:
+				if empty && quote {
+					s = append(s, "")
+				}
+				quote = !quote
+				empty = true
+			default:
+				return nil, &ParseError{f, errstr, l}, ""
+			}
+			l = <-c
+		}
+		if quote {
+			return nil, &ParseError{f, errstr, l}, ""
+		}
+	case false: // Unquoted text record
+		s = make([]string, 1)
+		for l.value != zNewline && l.value != zEOF {
+			if l.err {
+				return s, &ParseError{f, errstr, l}, ""
+			}
+			s[0] += l.token
+			l = <-c
+		}
+	}
+	return s, nil, l.comment
+}
+
+func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(A)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 { // Dynamic updates.
+		return rr, nil, ""
+	}
+	rr.A = net.ParseIP(l.token)
+	if rr.A == nil || l.err {
+		return nil, &ParseError{f, "bad A A", l}, ""
+	}
+	return rr, nil, ""
+}
+
+func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(AAAA)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	rr.AAAA = net.ParseIP(l.token)
+	if rr.AAAA == nil || l.err {
+		return nil, &ParseError{f, "bad AAAA AAAA", l}, ""
+	}
+	return rr, nil, ""
+}
+
+func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NS)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Ns = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Ns = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad NS Ns", l}, ""
+	}
+	if rr.Ns[l.length-1] != '.' {
+		rr.Ns = appendOrigin(rr.Ns, o)
+	}
+	return rr, nil, ""
+}
+
+func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(PTR)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Ptr = l.token
+	if l.length == 0 { // dynamic update rr.
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Ptr = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad PTR Ptr", l}, ""
+	}
+	if rr.Ptr[l.length-1] != '.' {
+		rr.Ptr = appendOrigin(rr.Ptr, o)
+	}
+	return rr, nil, ""
+}
+
+func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NSAPPTR)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Ptr = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Ptr = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad NSAP-PTR Ptr", l}, ""
+	}
+	if rr.Ptr[l.length-1] != '.' {
+		rr.Ptr = appendOrigin(rr.Ptr, o)
+	}
+	return rr, nil, ""
+}
+
+func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(RP)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Mbox = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Mbox = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad RP Mbox", l}, ""
+		}
+		if rr.Mbox[l.length-1] != '.' {
+			rr.Mbox = appendOrigin(rr.Mbox, o)
+		}
+	}
+	<-c // zBlank
+	l = <-c
+	rr.Txt = l.token
+	if l.token == "@" {
+		rr.Txt = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad RP Txt", l}, ""
+	}
+	if rr.Txt[l.length-1] != '.' {
+		rr.Txt = appendOrigin(rr.Txt, o)
+	}
+	return rr, nil, ""
+}
+
+func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MR)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Mr = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Mr = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MR Mr", l}, ""
+	}
+	if rr.Mr[l.length-1] != '.' {
+		rr.Mr = appendOrigin(rr.Mr, o)
+	}
+	return rr, nil, ""
+}
+
+func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MB)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Mb = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Mb = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MB Mb", l}, ""
+	}
+	if rr.Mb[l.length-1] != '.' {
+		rr.Mb = appendOrigin(rr.Mb, o)
+	}
+	return rr, nil, ""
+}
+
+func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MG)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Mg = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Mg = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MG Mg", l}, ""
+	}
+	if rr.Mg[l.length-1] != '.' {
+		rr.Mg = appendOrigin(rr.Mg, o)
+	}
+	return rr, nil, ""
+}
+
+func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(HINFO)
+	rr.Hdr = h
+
+	chunks, e, c1 := endingToTxtSlice(c, "bad HINFO Fields", f)
+	if e != nil {
+		return nil, e, c1
+	}
+
+	if ln := len(chunks); ln == 0 {
+		return rr, nil, ""
+	} else if ln == 1 {
+		// Can we split it?
+		if out := strings.Fields(chunks[0]); len(out) > 1 {
+			chunks = out
+		} else {
+			chunks = append(chunks, "")
+		}
+	}
+
+	rr.Cpu = chunks[0]
+	rr.Os = strings.Join(chunks[1:], " ")
+
+	return rr, nil, ""
+}
+
+func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MINFO)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Rmail = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Rmail = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
+		}
+		if rr.Rmail[l.length-1] != '.' {
+			rr.Rmail = appendOrigin(rr.Rmail, o)
+		}
+	}
+	<-c // zBlank
+	l = <-c
+	rr.Email = l.token
+	if l.token == "@" {
+		rr.Email = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MINFO Email", l}, ""
+	}
+	if rr.Email[l.length-1] != '.' {
+		rr.Email = appendOrigin(rr.Email, o)
+	}
+	return rr, nil, ""
+}
+
+func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MF)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Mf = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Mf = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MF Mf", l}, ""
+	}
+	if rr.Mf[l.length-1] != '.' {
+		rr.Mf = appendOrigin(rr.Mf, o)
+	}
+	return rr, nil, ""
+}
+
+func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MD)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Md = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Md = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MD Md", l}, ""
+	}
+	if rr.Md[l.length-1] != '.' {
+		rr.Md = appendOrigin(rr.Md, o)
+	}
+	return rr, nil, ""
+}
+
+func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(MX)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad MX Pref", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Mx = l.token
+	if l.token == "@" {
+		rr.Mx = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad MX Mx", l}, ""
+	}
+	if rr.Mx[l.length-1] != '.' {
+		rr.Mx = appendOrigin(rr.Mx, o)
+	}
+	return rr, nil, ""
+}
+
+func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(RT)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil {
+		return nil, &ParseError{f, "bad RT Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Host = l.token
+	if l.token == "@" {
+		rr.Host = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad RT Host", l}, ""
+	}
+	if rr.Host[l.length-1] != '.' {
+		rr.Host = appendOrigin(rr.Host, o)
+	}
+	return rr, nil, ""
+}
+
+func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(AFSDB)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
+	}
+	rr.Subtype = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Hostname = l.token
+	if l.token == "@" {
+		rr.Hostname = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad AFSDB Hostname", l}, ""
+	}
+	if rr.Hostname[l.length-1] != '.' {
+		rr.Hostname = appendOrigin(rr.Hostname, o)
+	}
+	return rr, nil, ""
+}
+
+func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(X25)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.err {
+		return nil, &ParseError{f, "bad X25 PSDNAddress", l}, ""
+	}
+	rr.PSDNAddress = l.token
+	return rr, nil, ""
+}
+
+func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(KX)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad KX Pref", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Exchanger = l.token
+	if l.token == "@" {
+		rr.Exchanger = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad KX Exchanger", l}, ""
+	}
+	if rr.Exchanger[l.length-1] != '.' {
+		rr.Exchanger = appendOrigin(rr.Exchanger, o)
+	}
+	return rr, nil, ""
+}
+
+func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(CNAME)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Target = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Target = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad CNAME Target", l}, ""
+	}
+	if rr.Target[l.length-1] != '.' {
+		rr.Target = appendOrigin(rr.Target, o)
+	}
+	return rr, nil, ""
+}
+
+func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(DNAME)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Target = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Target = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad CNAME Target", l}, ""
+	}
+	if rr.Target[l.length-1] != '.' {
+		rr.Target = appendOrigin(rr.Target, o)
+	}
+	return rr, nil, ""
+}
+
+func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(SOA)
+	rr.Hdr = h
+
+	l := <-c
+	rr.Ns = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	<-c // zBlank
+	if l.token == "@" {
+		rr.Ns = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad SOA Ns", l}, ""
+		}
+		if rr.Ns[l.length-1] != '.' {
+			rr.Ns = appendOrigin(rr.Ns, o)
+		}
+	}
+
+	l = <-c
+	rr.Mbox = l.token
+	if l.token == "@" {
+		rr.Mbox = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad SOA Mbox", l}, ""
+		}
+		if rr.Mbox[l.length-1] != '.' {
+			rr.Mbox = appendOrigin(rr.Mbox, o)
+		}
+	}
+	<-c // zBlank
+
+	var (
+		v  uint32
+		ok bool
+	)
+	for i := 0; i < 5; i++ {
+		l = <-c
+		if l.err {
+			return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+		}
+		if j, e := strconv.Atoi(l.token); e != nil {
+			if i == 0 {
+				// Serial should be a number
+				return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+			}
+			if v, ok = stringToTtl(l.token); !ok {
+				return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+
+			}
+		} else {
+			v = uint32(j)
+		}
+		switch i {
+		case 0:
+			rr.Serial = v
+			<-c // zBlank
+		case 1:
+			rr.Refresh = v
+			<-c // zBlank
+		case 2:
+			rr.Retry = v
+			<-c // zBlank
+		case 3:
+			rr.Expire = v
+			<-c // zBlank
+		case 4:
+			rr.Minttl = v
+		}
+	}
+	return rr, nil, ""
+}
+
+func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(SRV)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad SRV Priority", l}, ""
+	}
+	rr.Priority = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad SRV Weight", l}, ""
+	}
+	rr.Weight = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad SRV Port", l}, ""
+	}
+	rr.Port = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Target = l.token
+	if l.token == "@" {
+		rr.Target = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad SRV Target", l}, ""
+	}
+	if rr.Target[l.length-1] != '.' {
+		rr.Target = appendOrigin(rr.Target, o)
+	}
+	return rr, nil, ""
+}
+
+func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NAPTR)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NAPTR Order", l}, ""
+	}
+	rr.Order = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NAPTR Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	// Flags
+	<-c     // zBlank
+	l = <-c // _QUOTE
+	if l.value != zQuote {
+		return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+	}
+	l = <-c // Either String or Quote
+	if l.value == zString {
+		rr.Flags = l.token
+		l = <-c // _QUOTE
+		if l.value != zQuote {
+			return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+		}
+	} else if l.value == zQuote {
+		rr.Flags = ""
+	} else {
+		return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+	}
+
+	// Service
+	<-c     // zBlank
+	l = <-c // _QUOTE
+	if l.value != zQuote {
+		return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+	}
+	l = <-c // Either String or Quote
+	if l.value == zString {
+		rr.Service = l.token
+		l = <-c // _QUOTE
+		if l.value != zQuote {
+			return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+		}
+	} else if l.value == zQuote {
+		rr.Service = ""
+	} else {
+		return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+	}
+
+	// Regexp
+	<-c     // zBlank
+	l = <-c // _QUOTE
+	if l.value != zQuote {
+		return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+	}
+	l = <-c // Either String or Quote
+	if l.value == zString {
+		rr.Regexp = l.token
+		l = <-c // _QUOTE
+		if l.value != zQuote {
+			return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+		}
+	} else if l.value == zQuote {
+		rr.Regexp = ""
+	} else {
+		return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+	}
+	// After quote no space??
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Replacement = l.token
+	if l.token == "@" {
+		rr.Replacement = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad NAPTR Replacement", l}, ""
+	}
+	if rr.Replacement[l.length-1] != '.' {
+		rr.Replacement = appendOrigin(rr.Replacement, o)
+	}
+	return rr, nil, ""
+}
+
+func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(TALINK)
+	rr.Hdr = h
+
+	l := <-c
+	rr.PreviousName = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.PreviousName = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
+		}
+		if rr.PreviousName[l.length-1] != '.' {
+			rr.PreviousName = appendOrigin(rr.PreviousName, o)
+		}
+	}
+	<-c // zBlank
+	l = <-c
+	rr.NextName = l.token
+	if l.token == "@" {
+		rr.NextName = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad TALINK NextName", l}, ""
+	}
+	if rr.NextName[l.length-1] != '.' {
+		rr.NextName = appendOrigin(rr.NextName, o)
+	}
+	return rr, nil, ""
+}
+
+func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(LOC)
+	rr.Hdr = h
+	// Non zero defaults for LOC record, see RFC 1876, Section 3.
+	rr.HorizPre = 165 // 10000
+	rr.VertPre = 162  // 10
+	rr.Size = 18      // 1
+	ok := false
+	// North
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Latitude", l}, ""
+	}
+	rr.Latitude = 1000 * 60 * 60 * uint32(i)
+
+	<-c // zBlank
+	// Either number, 'N' or 'S'
+	l = <-c
+	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
+		goto East
+	}
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Latitude minutes", l}, ""
+	}
+	rr.Latitude += 1000 * 60 * uint32(i)
+
+	<-c // zBlank
+	l = <-c
+	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Latitude seconds", l}, ""
+	} else {
+		rr.Latitude += uint32(1000 * i)
+	}
+	<-c // zBlank
+	// Either number, 'N' or 'S'
+	l = <-c
+	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
+		goto East
+	}
+	// If still alive, flag an error
+	return nil, &ParseError{f, "bad LOC Latitude North/South", l}, ""
+
+East:
+	// East
+	<-c // zBlank
+	l = <-c
+	if i, e := strconv.Atoi(l.token); e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Longitude", l}, ""
+	} else {
+		rr.Longitude = 1000 * 60 * 60 * uint32(i)
+	}
+	<-c // zBlank
+	// Either number, 'E' or 'W'
+	l = <-c
+	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
+		goto Altitude
+	}
+	if i, e := strconv.Atoi(l.token); e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Longitude minutes", l}, ""
+	} else {
+		rr.Longitude += 1000 * 60 * uint32(i)
+	}
+	<-c // zBlank
+	l = <-c
+	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
+		return nil, &ParseError{f, "bad LOC Longitude seconds", l}, ""
+	} else {
+		rr.Longitude += uint32(1000 * i)
+	}
+	<-c // zBlank
+	// Either number, 'E' or 'W'
+	l = <-c
+	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
+		goto Altitude
+	}
+	// If still alive, flag an error
+	return nil, &ParseError{f, "bad LOC Longitude East/West", l}, ""
+
+Altitude:
+	<-c // zBlank
+	l = <-c
+	if l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad LOC Altitude", l}, ""
+	}
+	if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
+		l.token = l.token[0 : len(l.token)-1]
+	}
+	if i, e := strconv.ParseFloat(l.token, 32); e != nil {
+		return nil, &ParseError{f, "bad LOC Altitude", l}, ""
+	} else {
+		rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
+	}
+
+	// And now optionally the other values
+	l = <-c
+	count := 0
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zString:
+			switch count {
+			case 0: // Size
+				e, m, ok := stringToCm(l.token)
+				if !ok {
+					return nil, &ParseError{f, "bad LOC Size", l}, ""
+				}
+				rr.Size = (e & 0x0f) | (m << 4 & 0xf0)
+			case 1: // HorizPre
+				e, m, ok := stringToCm(l.token)
+				if !ok {
+					return nil, &ParseError{f, "bad LOC HorizPre", l}, ""
+				}
+				rr.HorizPre = (e & 0x0f) | (m << 4 & 0xf0)
+			case 2: // VertPre
+				e, m, ok := stringToCm(l.token)
+				if !ok {
+					return nil, &ParseError{f, "bad LOC VertPre", l}, ""
+				}
+				rr.VertPre = (e & 0x0f) | (m << 4 & 0xf0)
+			}
+			count++
+		case zBlank:
+			// Ok
+		default:
+			return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, ""
+		}
+		l = <-c
+	}
+	return rr, nil, ""
+}
+
+func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(HIP)
+	rr.Hdr = h
+
+	// HitLength is not represented
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l}, ""
+	}
+	rr.PublicKeyAlgorithm = uint8(i)
+	<-c     // zBlank
+	l = <-c // zString
+	if l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad HIP Hit", l}, ""
+	}
+	rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
+	rr.HitLength = uint8(len(rr.Hit)) / 2
+
+	<-c     // zBlank
+	l = <-c // zString
+	if l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad HIP PublicKey", l}, ""
+	}
+	rr.PublicKey = l.token // This cannot contain spaces
+	rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey)))
+
+	// RendezvousServers (if any)
+	l = <-c
+	var xs []string
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zString:
+			if l.token == "@" {
+				xs = append(xs, o)
+				l = <-c
+				continue
+			}
+			_, ok := IsDomainName(l.token)
+			if !ok || l.length == 0 || l.err {
+				return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+			}
+			if l.token[l.length-1] != '.' {
+				l.token = appendOrigin(l.token, o)
+			}
+			xs = append(xs, l.token)
+		case zBlank:
+			// Ok
+		default:
+			return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+		}
+		l = <-c
+	}
+	rr.RendezvousServers = xs
+	return rr, nil, l.comment
+}
+
+func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(CERT)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	if v, ok := StringToCertType[l.token]; ok {
+		rr.Type = v
+	} else if i, e := strconv.Atoi(l.token); e != nil {
+		return nil, &ParseError{f, "bad CERT Type", l}, ""
+	} else {
+		rr.Type = uint16(i)
+	}
+	<-c     // zBlank
+	l = <-c // zString
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad CERT KeyTag", l}, ""
+	}
+	rr.KeyTag = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	if v, ok := StringToAlgorithm[l.token]; ok {
+		rr.Algorithm = v
+	} else if i, e := strconv.Atoi(l.token); e != nil {
+		return nil, &ParseError{f, "bad CERT Algorithm", l}, ""
+	} else {
+		rr.Algorithm = uint8(i)
+	}
+	s, e1, c1 := endingToString(c, "bad CERT Certificate", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	rr.Certificate = s
+	return rr, nil, c1
+}
+
+func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(OPENPGPKEY)
+	rr.Hdr = h
+
+	s, e, c1 := endingToString(c, "bad OPENPGPKEY PublicKey", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.PublicKey = s
+	return rr, nil, c1
+}
+
+func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setRRSIG(h, c, o, f)
+	if r != nil {
+		return &SIG{*r.(*RRSIG)}, e, s
+	}
+	return nil, e, s
+}
+
+func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(RRSIG)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	if t, ok := StringToType[l.tokenUpper]; !ok {
+		if strings.HasPrefix(l.tokenUpper, "TYPE") {
+			t, ok = typeToInt(l.tokenUpper)
+			if !ok {
+				return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+			}
+			rr.TypeCovered = t
+		} else {
+			return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+		}
+	} else {
+		rr.TypeCovered = t
+	}
+	<-c // zBlank
+	l = <-c
+	i, err := strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad RRSIG Algorithm", l}, ""
+	}
+	rr.Algorithm = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, err = strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad RRSIG Labels", l}, ""
+	}
+	rr.Labels = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, err = strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, ""
+	}
+	rr.OrigTtl = uint32(i)
+	<-c // zBlank
+	l = <-c
+	if i, err := StringToTime(l.token); err != nil {
+		// Try to see if all numeric and use it as epoch
+		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
+			// TODO(miek): error out on > MAX_UINT32, same below
+			rr.Expiration = uint32(i)
+		} else {
+			return nil, &ParseError{f, "bad RRSIG Expiration", l}, ""
+		}
+	} else {
+		rr.Expiration = i
+	}
+	<-c // zBlank
+	l = <-c
+	if i, err := StringToTime(l.token); err != nil {
+		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
+			rr.Inception = uint32(i)
+		} else {
+			return nil, &ParseError{f, "bad RRSIG Inception", l}, ""
+		}
+	} else {
+		rr.Inception = i
+	}
+	<-c // zBlank
+	l = <-c
+	i, err = strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad RRSIG KeyTag", l}, ""
+	}
+	rr.KeyTag = uint16(i)
+	<-c // zBlank
+	l = <-c
+	rr.SignerName = l.token
+	if l.token == "@" {
+		rr.SignerName = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
+		}
+		if rr.SignerName[l.length-1] != '.' {
+			rr.SignerName = appendOrigin(rr.SignerName, o)
+		}
+	}
+	s, e, c1 := endingToString(c, "bad RRSIG Signature", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.Signature = s
+	return rr, nil, c1
+}
+
+func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NSEC)
+	rr.Hdr = h
+
+	l := <-c
+	rr.NextDomain = l.token
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	if l.token == "@" {
+		rr.NextDomain = o
+	} else {
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
+		}
+		if rr.NextDomain[l.length-1] != '.' {
+			rr.NextDomain = appendOrigin(rr.NextDomain, o)
+		}
+	}
+
+	rr.TypeBitMap = make([]uint16, 0)
+	var (
+		k  uint16
+		ok bool
+	)
+	l = <-c
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zBlank:
+			// Ok
+		case zString:
+			if k, ok = StringToType[l.tokenUpper]; !ok {
+				if k, ok = typeToInt(l.tokenUpper); !ok {
+					return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+				}
+			}
+			rr.TypeBitMap = append(rr.TypeBitMap, k)
+		default:
+			return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+		}
+		l = <-c
+	}
+	return rr, nil, l.comment
+}
+
+func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NSEC3)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3 Hash", l}, ""
+	}
+	rr.Hash = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3 Flags", l}, ""
+	}
+	rr.Flags = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3 Iterations", l}, ""
+	}
+	rr.Iterations = uint16(i)
+	<-c
+	l = <-c
+	if len(l.token) == 0 || l.err {
+		return nil, &ParseError{f, "bad NSEC3 Salt", l}, ""
+	}
+	rr.SaltLength = uint8(len(l.token)) / 2
+	rr.Salt = l.token
+
+	<-c
+	l = <-c
+	if len(l.token) == 0 || l.err {
+		return nil, &ParseError{f, "bad NSEC3 NextDomain", l}, ""
+	}
+	rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
+	rr.NextDomain = l.token
+
+	rr.TypeBitMap = make([]uint16, 0)
+	var (
+		k  uint16
+		ok bool
+	)
+	l = <-c
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zBlank:
+			// Ok
+		case zString:
+			if k, ok = StringToType[l.tokenUpper]; !ok {
+				if k, ok = typeToInt(l.tokenUpper); !ok {
+					return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+				}
+			}
+			rr.TypeBitMap = append(rr.TypeBitMap, k)
+		default:
+			return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+		}
+		l = <-c
+	}
+	return rr, nil, l.comment
+}
+
+func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NSEC3PARAM)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, ""
+	}
+	rr.Hash = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, ""
+	}
+	rr.Flags = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, ""
+	}
+	rr.Iterations = uint16(i)
+	<-c
+	l = <-c
+	rr.SaltLength = uint8(len(l.token))
+	rr.Salt = l.token
+	return rr, nil, ""
+}
+
+func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(EUI48)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.length != 17 || l.err {
+		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+	}
+	addr := make([]byte, 12)
+	dash := 0
+	for i := 0; i < 10; i += 2 {
+		addr[i] = l.token[i+dash]
+		addr[i+1] = l.token[i+1+dash]
+		dash++
+		if l.token[i+1+dash] != '-' {
+			return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+		}
+	}
+	addr[10] = l.token[15]
+	addr[11] = l.token[16]
+
+	i, e := strconv.ParseUint(string(addr), 16, 48)
+	if e != nil {
+		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+	}
+	rr.Address = i
+	return rr, nil, ""
+}
+
+func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(EUI64)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.length != 23 || l.err {
+		return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+	}
+	addr := make([]byte, 16)
+	dash := 0
+	for i := 0; i < 14; i += 2 {
+		addr[i] = l.token[i+dash]
+		addr[i+1] = l.token[i+1+dash]
+		dash++
+		if l.token[i+1+dash] != '-' {
+			return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+		}
+	}
+	addr[14] = l.token[21]
+	addr[15] = l.token[22]
+
+	i, e := strconv.ParseUint(string(addr), 16, 64)
+	if e != nil {
+		return nil, &ParseError{f, "bad EUI68 Address", l}, ""
+	}
+	rr.Address = uint64(i)
+	return rr, nil, ""
+}
+
+func setWKS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(WKS)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	rr.Address = net.ParseIP(l.token)
+	if rr.Address == nil || l.err {
+		return nil, &ParseError{f, "bad WKS Address", l}, ""
+	}
+
+	<-c // zBlank
+	l = <-c
+	proto := "tcp"
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad WKS Protocol", l}, ""
+	}
+	rr.Protocol = uint8(i)
+	switch rr.Protocol {
+	case 17:
+		proto = "udp"
+	case 6:
+		proto = "tcp"
+	default:
+		return nil, &ParseError{f, "bad WKS Protocol", l}, ""
+	}
+
+	<-c
+	l = <-c
+	rr.BitMap = make([]uint16, 0)
+	var (
+		k   int
+		err error
+	)
+	for l.value != zNewline && l.value != zEOF {
+		switch l.value {
+		case zBlank:
+			// Ok
+		case zString:
+			if k, err = net.LookupPort(proto, l.token); err != nil {
+				i, e := strconv.Atoi(l.token) // If a number use that
+				if e != nil {
+					return nil, &ParseError{f, "bad WKS BitMap", l}, ""
+				}
+				rr.BitMap = append(rr.BitMap, uint16(i))
+			}
+			rr.BitMap = append(rr.BitMap, uint16(k))
+		default:
+			return nil, &ParseError{f, "bad WKS BitMap", l}, ""
+		}
+		l = <-c
+	}
+	return rr, nil, l.comment
+}
+
+func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(SSHFP)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad SSHFP Algorithm", l}, ""
+	}
+	rr.Algorithm = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad SSHFP Type", l}, ""
+	}
+	rr.Type = uint8(i)
+	<-c // zBlank
+	s, e1, c1 := endingToString(c, "bad SSHFP Fingerprint", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	rr.FingerPrint = s
+	return rr, nil, ""
+}
+
+func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
+	rr := new(DNSKEY)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad " + typ + " Flags", l}, ""
+	}
+	rr.Flags = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad " + typ + " Protocol", l}, ""
+	}
+	rr.Protocol = uint8(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
+	}
+	rr.Algorithm = uint8(i)
+	s, e1, c1 := endingToString(c, "bad "+typ+" PublicKey", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	rr.PublicKey = s
+	return rr, nil, c1
+}
+
+func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDNSKEYs(h, c, o, f, "KEY")
+	if r != nil {
+		return &KEY{*r.(*DNSKEY)}, e, s
+	}
+	return nil, e, s
+}
+
+func setDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY")
+	return r, e, s
+}
+
+func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY")
+	if r != nil {
+		return &CDNSKEY{*r.(*DNSKEY)}, e, s
+	}
+	return nil, e, s
+}
+
+func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(RKEY)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad RKEY Flags", l}, ""
+	}
+	rr.Flags = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad RKEY Protocol", l}, ""
+	}
+	rr.Protocol = uint8(i)
+	<-c     // zBlank
+	l = <-c // zString
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad RKEY Algorithm", l}, ""
+	}
+	rr.Algorithm = uint8(i)
+	s, e1, c1 := endingToString(c, "bad RKEY PublicKey", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	rr.PublicKey = s
+	return rr, nil, c1
+}
+
+func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(EID)
+	rr.Hdr = h
+	s, e, c1 := endingToString(c, "bad EID Endpoint", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.Endpoint = s
+	return rr, nil, c1
+}
+
+func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NIMLOC)
+	rr.Hdr = h
+	s, e, c1 := endingToString(c, "bad NIMLOC Locator", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.Locator = s
+	return rr, nil, c1
+}
+
+func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(GPOS)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	_, e := strconv.ParseFloat(l.token, 64)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad GPOS Longitude", l}, ""
+	}
+	rr.Longitude = l.token
+	<-c // zBlank
+	l = <-c
+	_, e = strconv.ParseFloat(l.token, 64)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad GPOS Latitude", l}, ""
+	}
+	rr.Latitude = l.token
+	<-c // zBlank
+	l = <-c
+	_, e = strconv.ParseFloat(l.token, 64)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad GPOS Altitude", l}, ""
+	}
+	rr.Altitude = l.token
+	return rr, nil, ""
+}
+
+func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
+	rr := new(DS)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, ""
+	}
+	rr.KeyTag = uint16(i)
+	<-c // zBlank
+	l = <-c
+	if i, e := strconv.Atoi(l.token); e != nil {
+		i, ok := StringToAlgorithm[l.tokenUpper]
+		if !ok || l.err {
+			return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
+		}
+		rr.Algorithm = i
+	} else {
+		rr.Algorithm = uint8(i)
+	}
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad " + typ + " DigestType", l}, ""
+	}
+	rr.DigestType = uint8(i)
+	s, e1, c1 := endingToString(c, "bad "+typ+" Digest", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	rr.Digest = s
+	return rr, nil, c1
+}
+
+func setDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDSs(h, c, o, f, "DS")
+	return r, e, s
+}
+
+func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDSs(h, c, o, f, "DLV")
+	if r != nil {
+		return &DLV{*r.(*DS)}, e, s
+	}
+	return nil, e, s
+}
+
+func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	r, e, s := setDSs(h, c, o, f, "CDS")
+	if r != nil {
+		return &CDS{*r.(*DS)}, e, s
+	}
+	return nil, e, s
+}
+
+func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(TA)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad TA KeyTag", l}, ""
+	}
+	rr.KeyTag = uint16(i)
+	<-c // zBlank
+	l = <-c
+	if i, e := strconv.Atoi(l.token); e != nil {
+		i, ok := StringToAlgorithm[l.tokenUpper]
+		if !ok || l.err {
+			return nil, &ParseError{f, "bad TA Algorithm", l}, ""
+		}
+		rr.Algorithm = i
+	} else {
+		rr.Algorithm = uint8(i)
+	}
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad TA DigestType", l}, ""
+	}
+	rr.DigestType = uint8(i)
+	s, e, c1 := endingToString(c, "bad TA Digest", f)
+	if e != nil {
+		return nil, e.(*ParseError), c1
+	}
+	rr.Digest = s
+	return rr, nil, c1
+}
+
+func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(TLSA)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad TLSA Usage", l}, ""
+	}
+	rr.Usage = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad TLSA Selector", l}, ""
+	}
+	rr.Selector = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad TLSA MatchingType", l}, ""
+	}
+	rr.MatchingType = uint8(i)
+	// So this needs be e2 (i.e. different than e), because...??t
+	s, e2, c1 := endingToString(c, "bad TLSA Certificate", f)
+	if e2 != nil {
+		return nil, e2, c1
+	}
+	rr.Certificate = s
+	return rr, nil, c1
+}
+
+func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(RFC3597)
+	rr.Hdr = h
+	l := <-c
+	if l.token != "\\#" {
+		return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
+	}
+	<-c // zBlank
+	l = <-c
+	rdlength, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad RFC3597 Rdata ", l}, ""
+	}
+
+	s, e1, c1 := endingToString(c, "bad RFC3597 Rdata", f)
+	if e1 != nil {
+		return nil, e1, c1
+	}
+	if rdlength*2 != len(s) {
+		return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
+	}
+	rr.Rdata = s
+	return rr, nil, c1
+}
+
+func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(SPF)
+	rr.Hdr = h
+
+	s, e, c1 := endingToTxtSlice(c, "bad SPF Txt", f)
+	if e != nil {
+		return nil, e, ""
+	}
+	rr.Txt = s
+	return rr, nil, c1
+}
+
+func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(TXT)
+	rr.Hdr = h
+
+	// no zBlank reading here, because all this rdata is TXT
+	s, e, c1 := endingToTxtSlice(c, "bad TXT Txt", f)
+	if e != nil {
+		return nil, e, ""
+	}
+	rr.Txt = s
+	return rr, nil, c1
+}
+
+// identical to setTXT
+func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NINFO)
+	rr.Hdr = h
+
+	s, e, c1 := endingToTxtSlice(c, "bad NINFO ZSData", f)
+	if e != nil {
+		return nil, e, ""
+	}
+	rr.ZSData = s
+	return rr, nil, c1
+}
+
+func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(URI)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 { // Dynamic updates.
+		return rr, nil, ""
+	}
+
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad URI Priority", l}, ""
+	}
+	rr.Priority = uint16(i)
+	<-c // zBlank
+	l = <-c
+	i, e = strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad URI Weight", l}, ""
+	}
+	rr.Weight = uint16(i)
+
+	<-c // zBlank
+	s, err, c1 := endingToTxtSlice(c, "bad URI Target", f)
+	if err != nil {
+		return nil, err, ""
+	}
+	if len(s) > 1 {
+		return nil, &ParseError{f, "bad URI Target", l}, ""
+	}
+	rr.Target = s[0]
+	return rr, nil, c1
+}
+
+func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	// awesome record to parse!
+	rr := new(DHCID)
+	rr.Hdr = h
+
+	s, e, c1 := endingToString(c, "bad DHCID Digest", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.Digest = s
+	return rr, nil, c1
+}
+
+func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(NID)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad NID Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	u, err := stringToNodeID(l)
+	if err != nil || l.err {
+		return nil, err, ""
+	}
+	rr.NodeID = u
+	return rr, nil, ""
+}
+
+func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(L32)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad L32 Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Locator32 = net.ParseIP(l.token)
+	if rr.Locator32 == nil || l.err {
+		return nil, &ParseError{f, "bad L32 Locator", l}, ""
+	}
+	return rr, nil, ""
+}
+
+func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(LP)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad LP Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Fqdn = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Fqdn = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad LP Fqdn", l}, ""
+	}
+	if rr.Fqdn[l.length-1] != '.' {
+		rr.Fqdn = appendOrigin(rr.Fqdn, o)
+	}
+	return rr, nil, ""
+}
+
+func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(L64)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad L64 Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	u, err := stringToNodeID(l)
+	if err != nil || l.err {
+		return nil, err, ""
+	}
+	rr.Locator64 = u
+	return rr, nil, ""
+}
+
+func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(UID)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad UID Uid", l}, ""
+	}
+	rr.Uid = uint32(i)
+	return rr, nil, ""
+}
+
+func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(GID)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad GID Gid", l}, ""
+	}
+	rr.Gid = uint32(i)
+	return rr, nil, ""
+}
+
+func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(UINFO)
+	rr.Hdr = h
+	s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
+	if e != nil {
+		return nil, e, ""
+	}
+	rr.Uinfo = s[0] // silently discard anything above
+	return rr, nil, c1
+}
+
+func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(PX)
+	rr.Hdr = h
+
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	i, e := strconv.Atoi(l.token)
+	if e != nil || l.err {
+		return nil, &ParseError{f, "bad PX Preference", l}, ""
+	}
+	rr.Preference = uint16(i)
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Map822 = l.token
+	if l.length == 0 {
+		return rr, nil, ""
+	}
+	if l.token == "@" {
+		rr.Map822 = o
+		return rr, nil, ""
+	}
+	_, ok := IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad PX Map822", l}, ""
+	}
+	if rr.Map822[l.length-1] != '.' {
+		rr.Map822 = appendOrigin(rr.Map822, o)
+	}
+	<-c     // zBlank
+	l = <-c // zString
+	rr.Mapx400 = l.token
+	if l.token == "@" {
+		rr.Mapx400 = o
+		return rr, nil, ""
+	}
+	_, ok = IsDomainName(l.token)
+	if !ok || l.length == 0 || l.err {
+		return nil, &ParseError{f, "bad PX Mapx400", l}, ""
+	}
+	if rr.Mapx400[l.length-1] != '.' {
+		rr.Mapx400 = appendOrigin(rr.Mapx400, o)
+	}
+	return rr, nil, ""
+}
+
+func setIPSECKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(IPSECKEY)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, err := strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad IPSECKEY Precedence", l}, ""
+	}
+	rr.Precedence = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, err = strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
+	}
+	rr.GatewayType = uint8(i)
+	<-c // zBlank
+	l = <-c
+	i, err = strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad IPSECKEY Algorithm", l}, ""
+	}
+	rr.Algorithm = uint8(i)
+
+	// Now according to GatewayType we can have different elements here
+	<-c // zBlank
+	l = <-c
+	switch rr.GatewayType {
+	case 0:
+		fallthrough
+	case 3:
+		rr.GatewayName = l.token
+		if l.token == "@" {
+			rr.GatewayName = o
+		}
+		_, ok := IsDomainName(l.token)
+		if !ok || l.length == 0 || l.err {
+			return nil, &ParseError{f, "bad IPSECKEY GatewayName", l}, ""
+		}
+		if rr.GatewayName[l.length-1] != '.' {
+			rr.GatewayName = appendOrigin(rr.GatewayName, o)
+		}
+	case 1:
+		rr.GatewayA = net.ParseIP(l.token)
+		if rr.GatewayA == nil {
+			return nil, &ParseError{f, "bad IPSECKEY GatewayA", l}, ""
+		}
+	case 2:
+		rr.GatewayAAAA = net.ParseIP(l.token)
+		if rr.GatewayAAAA == nil {
+			return nil, &ParseError{f, "bad IPSECKEY GatewayAAAA", l}, ""
+		}
+	default:
+		return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
+	}
+
+	s, e, c1 := endingToString(c, "bad IPSECKEY PublicKey", f)
+	if e != nil {
+		return nil, e, c1
+	}
+	rr.PublicKey = s
+	return rr, nil, c1
+}
+
+func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+	rr := new(CAA)
+	rr.Hdr = h
+	l := <-c
+	if l.length == 0 {
+		return rr, nil, l.comment
+	}
+	i, err := strconv.Atoi(l.token)
+	if err != nil || l.err {
+		return nil, &ParseError{f, "bad CAA Flag", l}, ""
+	}
+	rr.Flag = uint8(i)
+
+	<-c     // zBlank
+	l = <-c // zString
+	if l.value != zString {
+		return nil, &ParseError{f, "bad CAA Tag", l}, ""
+	}
+	rr.Tag = l.token
+
+	<-c // zBlank
+	s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f)
+	if e != nil {
+		return nil, e, ""
+	}
+	if len(s) > 1 {
+		return nil, &ParseError{f, "bad CAA Value", l}, ""
+	}
+	rr.Value = s[0]
+	return rr, nil, c1
+}
+
+var typeToparserFunc = map[uint16]parserFunc{
+	TypeAAAA:       parserFunc{setAAAA, false},
+	TypeAFSDB:      parserFunc{setAFSDB, false},
+	TypeA:          parserFunc{setA, false},
+	TypeCAA:        parserFunc{setCAA, true},
+	TypeCDS:        parserFunc{setCDS, true},
+	TypeCDNSKEY:    parserFunc{setCDNSKEY, true},
+	TypeCERT:       parserFunc{setCERT, true},
+	TypeCNAME:      parserFunc{setCNAME, false},
+	TypeDHCID:      parserFunc{setDHCID, true},
+	TypeDLV:        parserFunc{setDLV, true},
+	TypeDNAME:      parserFunc{setDNAME, false},
+	TypeKEY:        parserFunc{setKEY, true},
+	TypeDNSKEY:     parserFunc{setDNSKEY, true},
+	TypeDS:         parserFunc{setDS, true},
+	TypeEID:        parserFunc{setEID, true},
+	TypeEUI48:      parserFunc{setEUI48, false},
+	TypeEUI64:      parserFunc{setEUI64, false},
+	TypeGID:        parserFunc{setGID, false},
+	TypeGPOS:       parserFunc{setGPOS, false},
+	TypeHINFO:      parserFunc{setHINFO, true},
+	TypeHIP:        parserFunc{setHIP, true},
+	TypeIPSECKEY:   parserFunc{setIPSECKEY, true},
+	TypeKX:         parserFunc{setKX, false},
+	TypeL32:        parserFunc{setL32, false},
+	TypeL64:        parserFunc{setL64, false},
+	TypeLOC:        parserFunc{setLOC, true},
+	TypeLP:         parserFunc{setLP, false},
+	TypeMB:         parserFunc{setMB, false},
+	TypeMD:         parserFunc{setMD, false},
+	TypeMF:         parserFunc{setMF, false},
+	TypeMG:         parserFunc{setMG, false},
+	TypeMINFO:      parserFunc{setMINFO, false},
+	TypeMR:         parserFunc{setMR, false},
+	TypeMX:         parserFunc{setMX, false},
+	TypeNAPTR:      parserFunc{setNAPTR, false},
+	TypeNID:        parserFunc{setNID, false},
+	TypeNIMLOC:     parserFunc{setNIMLOC, true},
+	TypeNINFO:      parserFunc{setNINFO, true},
+	TypeNSAPPTR:    parserFunc{setNSAPPTR, false},
+	TypeNSEC3PARAM: parserFunc{setNSEC3PARAM, false},
+	TypeNSEC3:      parserFunc{setNSEC3, true},
+	TypeNSEC:       parserFunc{setNSEC, true},
+	TypeNS:         parserFunc{setNS, false},
+	TypeOPENPGPKEY: parserFunc{setOPENPGPKEY, true},
+	TypePTR:        parserFunc{setPTR, false},
+	TypePX:         parserFunc{setPX, false},
+	TypeSIG:        parserFunc{setSIG, true},
+	TypeRKEY:       parserFunc{setRKEY, true},
+	TypeRP:         parserFunc{setRP, false},
+	TypeRRSIG:      parserFunc{setRRSIG, true},
+	TypeRT:         parserFunc{setRT, false},
+	TypeSOA:        parserFunc{setSOA, false},
+	TypeSPF:        parserFunc{setSPF, true},
+	TypeSRV:        parserFunc{setSRV, false},
+	TypeSSHFP:      parserFunc{setSSHFP, true},
+	TypeTALINK:     parserFunc{setTALINK, false},
+	TypeTA:         parserFunc{setTA, true},
+	TypeTLSA:       parserFunc{setTLSA, true},
+	TypeTXT:        parserFunc{setTXT, true},
+	TypeUID:        parserFunc{setUID, false},
+	TypeUINFO:      parserFunc{setUINFO, true},
+	TypeURI:        parserFunc{setURI, true},
+	TypeWKS:        parserFunc{setWKS, true},
+	TypeX25:        parserFunc{setX25, false},
+}
diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go
index 7e87f1ac63439820f9f76d34e54baec286e3583e..74ed5a9f7e9cd466d54eba8f3ebce870a7b30d4d 100644
--- a/vendor/github.com/prometheus/common/model/time.go
+++ b/vendor/github.com/prometheus/common/model/time.go
@@ -214,6 +214,9 @@ func (d Duration) String() string {
 		ms   = int64(time.Duration(d) / time.Millisecond)
 		unit = "ms"
 	)
+	if ms == 0 {
+		return "0s"
+	}
 	factors := map[string]int64{
 		"y":  1000 * 60 * 60 * 24 * 365,
 		"w":  1000 * 60 * 60 * 24 * 7,
diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go
index 1f4fb69edd21dcda39b3995987ea085ec9e94408..8257ffb02115aa46af80a2d52373ded551c31238 100644
--- a/vendor/golang.org/x/crypto/acme/acme.go
+++ b/vendor/golang.org/x/crypto/acme/acme.go
@@ -14,7 +14,6 @@
 package acme
 
 import (
-	"bytes"
 	"context"
 	"crypto"
 	"crypto/ecdsa"
@@ -23,6 +22,8 @@ import (
 	"crypto/sha256"
 	"crypto/tls"
 	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
@@ -33,7 +34,6 @@ import (
 	"io/ioutil"
 	"math/big"
 	"net/http"
-	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -42,6 +42,9 @@ import (
 // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
 const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
 
+// idPeACMEIdentifierV1 is the OID for the ACME extension for the TLS-ALPN challenge.
+var idPeACMEIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}
+
 const (
 	maxChainLen = 5       // max depth and breadth of a certificate chain
 	maxCertSize = 1 << 20 // max size of a certificate, in bytes
@@ -76,6 +79,22 @@ type Client struct {
 	// will have no effect.
 	DirectoryURL string
 
+	// RetryBackoff computes the duration after which the nth retry of a failed request
+	// should occur. The value of n for the first call on failure is 1.
+	// The values of r and resp are the request and response of the last failed attempt.
+	// If the returned value is negative or zero, no more retries are done and an error
+	// is returned to the caller of the original method.
+	//
+	// Requests which result in a 4xx client error are not retried,
+	// except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests.
+	//
+	// If RetryBackoff is nil, a truncated exponential backoff algorithm
+	// with the ceiling of 10 seconds is used, where each subsequent retry n
+	// is done after either ("Retry-After" + jitter) or (2^n seconds + jitter),
+	// preferring the former if "Retry-After" header is found in the resp.
+	// The jitter is a random value up to 1 second.
+	RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration
+
 	dirMu sync.Mutex // guards writes to dir
 	dir   *Directory // cached result of Client's Discover method
 
@@ -99,15 +118,12 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
 	if dirURL == "" {
 		dirURL = LetsEncryptURL
 	}
-	res, err := c.get(ctx, dirURL)
+	res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK))
 	if err != nil {
 		return Directory{}, err
 	}
 	defer res.Body.Close()
 	c.addNonce(res.Header)
-	if res.StatusCode != http.StatusOK {
-		return Directory{}, responseError(res)
-	}
 
 	var v struct {
 		Reg    string `json:"new-reg"`
@@ -166,14 +182,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
 		req.NotAfter = now.Add(exp).Format(time.RFC3339)
 	}
 
-	res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
+	res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated))
 	if err != nil {
 		return nil, "", err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusCreated {
-		return nil, "", responseError(res)
-	}
 
 	curl := res.Header.Get("Location") // cert permanent URL
 	if res.ContentLength == 0 {
@@ -196,26 +209,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
 // Callers are encouraged to parse the returned value to ensure the certificate is valid
 // and has expected features.
 func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
-	for {
-		res, err := c.get(ctx, url)
-		if err != nil {
-			return nil, err
-		}
-		defer res.Body.Close()
-		if res.StatusCode == http.StatusOK {
-			return c.responseCert(ctx, res, bundle)
-		}
-		if res.StatusCode > 299 {
-			return nil, responseError(res)
-		}
-		d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
-		select {
-		case <-time.After(d):
-			// retry
-		case <-ctx.Done():
-			return nil, ctx.Err()
-		}
+	res, err := c.get(ctx, url, wantStatus(http.StatusOK))
+	if err != nil {
+		return nil, err
 	}
+	return c.responseCert(ctx, res, bundle)
 }
 
 // RevokeCert revokes a previously issued certificate cert, provided in DER format.
@@ -241,14 +239,11 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
 	if key == nil {
 		key = c.Key
 	}
-	res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
+	res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK))
 	if err != nil {
 		return err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusOK {
-		return responseError(res)
-	}
 	return nil
 }
 
@@ -329,14 +324,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
 		Resource:   "new-authz",
 		Identifier: authzID{Type: "dns", Value: domain},
 	}
-	res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
+	res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusCreated {
-		return nil, responseError(res)
-	}
 
 	var v wireAuthz
 	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
@@ -353,14 +345,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
 // If a caller needs to poll an authorization until its status is final,
 // see the WaitAuthorization method.
 func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
-	res, err := c.get(ctx, url)
+	res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
-		return nil, responseError(res)
-	}
 	var v wireAuthz
 	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
 		return nil, fmt.Errorf("acme: invalid response: %v", err)
@@ -387,14 +376,11 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
 		Status:   "deactivated",
 		Delete:   true,
 	}
-	res, err := c.retryPostJWS(ctx, c.Key, url, req)
+	res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK))
 	if err != nil {
 		return err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusOK {
-		return responseError(res)
-	}
 	return nil
 }
 
@@ -406,44 +392,42 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
 // In all other cases WaitAuthorization returns an error.
 // If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
 func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
-	sleep := sleeper(ctx)
 	for {
-		res, err := c.get(ctx, url)
+		res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
 		if err != nil {
 			return nil, err
 		}
-		if res.StatusCode >= 400 && res.StatusCode <= 499 {
-			// Non-retriable error. For instance, Let's Encrypt may return 404 Not Found
-			// when requesting an expired authorization.
-			defer res.Body.Close()
-			return nil, responseError(res)
-		}
 
-		retry := res.Header.Get("Retry-After")
-		if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
-			res.Body.Close()
-			if err := sleep(retry, 1); err != nil {
-				return nil, err
-			}
-			continue
-		}
 		var raw wireAuthz
 		err = json.NewDecoder(res.Body).Decode(&raw)
 		res.Body.Close()
-		if err != nil {
-			if err := sleep(retry, 0); err != nil {
-				return nil, err
-			}
-			continue
-		}
-		if raw.Status == StatusValid {
+		switch {
+		case err != nil:
+			// Skip and retry.
+		case raw.Status == StatusValid:
 			return raw.authorization(url), nil
-		}
-		if raw.Status == StatusInvalid {
+		case raw.Status == StatusInvalid:
 			return nil, raw.error(url)
 		}
-		if err := sleep(retry, 0); err != nil {
-			return nil, err
+
+		// Exponential backoff is implemented in c.get above.
+		// This is just to prevent continuously hitting the CA
+		// while waiting for a final authorization status.
+		d := retryAfter(res.Header.Get("Retry-After"))
+		if d == 0 {
+			// Given that the fastest challenges TLS-SNI and HTTP-01
+			// require a CA to make at least 1 network round trip
+			// and most likely persist a challenge state,
+			// this default delay seems reasonable.
+			d = time.Second
+		}
+		t := time.NewTimer(d)
+		select {
+		case <-ctx.Done():
+			t.Stop()
+			return nil, ctx.Err()
+		case <-t.C:
+			// Retry.
 		}
 	}
 }
@@ -452,14 +436,11 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
 //
 // A client typically polls a challenge status using this method.
 func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
-	res, err := c.get(ctx, url)
+	res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
-		return nil, responseError(res)
-	}
 	v := wireChallenge{URI: url}
 	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
 		return nil, fmt.Errorf("acme: invalid response: %v", err)
@@ -486,16 +467,14 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
 		Type:     chal.Type,
 		Auth:     auth,
 	}
-	res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
+	res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus(
+		http.StatusOK,       // according to the spec
+		http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
+	))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	// Note: the protocol specifies 200 as the expected response code, but
-	// letsencrypt seems to be returning 202.
-	if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
-		return nil, responseError(res)
-	}
 
 	var v wireChallenge
 	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
@@ -552,7 +531,7 @@ func (c *Client) HTTP01ChallengePath(token string) string {
 // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
 //
 // The returned certificate is valid for the next 24 hours and must be presented only when
-// the server name of the client hello matches exactly the returned name value.
+// the server name of the TLS ClientHello matches exactly the returned name value.
 func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
 	ka, err := keyAuth(c.Key.Public(), token)
 	if err != nil {
@@ -579,7 +558,7 @@ func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tl
 // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
 //
 // The returned certificate is valid for the next 24 hours and must be presented only when
-// the server name in the client hello matches exactly the returned name value.
+// the server name in the TLS ClientHello matches exactly the returned name value.
 func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
 	b := sha256.Sum256([]byte(token))
 	h := hex.EncodeToString(b[:])
@@ -600,6 +579,52 @@ func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tl
 	return cert, sanA, nil
 }
 
+// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name. For more details on TLS-ALPN-01 see
+// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol
+// has been specified.
+func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) {
+	ka, err := keyAuth(c.Key.Public(), token)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+	shasum := sha256.Sum256([]byte(ka))
+	extValue, err := asn1.Marshal(shasum[:])
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+	acmeExtension := pkix.Extension{
+		Id:       idPeACMEIdentifierV1,
+		Critical: true,
+		Value:    extValue,
+	}
+
+	tmpl := defaultTLSChallengeCertTemplate()
+
+	var newOpt []CertOption
+	for _, o := range opt {
+		switch o := o.(type) {
+		case *certOptTemplate:
+			t := *(*x509.Certificate)(o) // shallow copy is ok
+			tmpl = &t
+		default:
+			newOpt = append(newOpt, o)
+		}
+	}
+	tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension)
+	newOpt = append(newOpt, WithTemplate(tmpl))
+	return tlsChallengeCert([]string{domain}, newOpt)
+}
+
 // doReg sends all types of registration requests.
 // The type of request is identified by typ argument, which is a "resource"
 // in the ACME spec terms.
@@ -619,14 +644,14 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
 		req.Contact = acct.Contact
 		req.Agreement = acct.AgreedTerms
 	}
-	res, err := c.retryPostJWS(ctx, c.Key, url, req)
+	res, err := c.post(ctx, c.Key, url, req, wantStatus(
+		http.StatusOK,      // updates and deletes
+		http.StatusCreated, // new account creation
+	))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	if res.StatusCode < 200 || res.StatusCode > 299 {
-		return nil, responseError(res)
-	}
 
 	var v struct {
 		Contact        []string
@@ -656,59 +681,6 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
 	}, nil
 }
 
-// retryPostJWS will retry calls to postJWS if there is a badNonce error,
-// clearing the stored nonces after each error.
-// If the response was 4XX-5XX, then responseError is called on the body,
-// the body is closed, and the error returned.
-func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
-	sleep := sleeper(ctx)
-	for {
-		res, err := c.postJWS(ctx, key, url, body)
-		if err != nil {
-			return nil, err
-		}
-		// handle errors 4XX-5XX with responseError
-		if res.StatusCode >= 400 && res.StatusCode <= 599 {
-			err := responseError(res)
-			res.Body.Close()
-			// according to spec badNonce is urn:ietf:params:acme:error:badNonce
-			// however, acme servers in the wild return their version of the error
-			// https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
-			if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") {
-				// clear any nonces that we might've stored that might now be
-				// considered bad
-				c.clearNonces()
-				retry := res.Header.Get("Retry-After")
-				if err := sleep(retry, 1); err != nil {
-					return nil, err
-				}
-				continue
-			}
-			return nil, err
-		}
-		return res, nil
-	}
-}
-
-// postJWS signs the body with the given key and POSTs it to the provided url.
-// The body argument must be JSON-serializable.
-func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
-	nonce, err := c.popNonce(ctx, url)
-	if err != nil {
-		return nil, err
-	}
-	b, err := jwsEncodeJSON(body, key, nonce)
-	if err != nil {
-		return nil, err
-	}
-	res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b))
-	if err != nil {
-		return nil, err
-	}
-	c.addNonce(res.Header)
-	return res, nil
-}
-
 // popNonce returns a nonce value previously stored with c.addNonce
 // or fetches a fresh one from the given URL.
 func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
@@ -749,58 +721,12 @@ func (c *Client) addNonce(h http.Header) {
 	c.nonces[v] = struct{}{}
 }
 
-func (c *Client) httpClient() *http.Client {
-	if c.HTTPClient != nil {
-		return c.HTTPClient
-	}
-	return http.DefaultClient
-}
-
-func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
-	req, err := http.NewRequest("GET", urlStr, nil)
-	if err != nil {
-		return nil, err
-	}
-	return c.do(ctx, req)
-}
-
-func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
-	req, err := http.NewRequest("HEAD", urlStr, nil)
-	if err != nil {
-		return nil, err
-	}
-	return c.do(ctx, req)
-}
-
-func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
-	req, err := http.NewRequest("POST", urlStr, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header.Set("Content-Type", contentType)
-	return c.do(ctx, req)
-}
-
-func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
-	res, err := c.httpClient().Do(req.WithContext(ctx))
+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
+	r, err := http.NewRequest("HEAD", url, nil)
 	if err != nil {
-		select {
-		case <-ctx.Done():
-			// Prefer the unadorned context error.
-			// (The acme package had tests assuming this, previously from ctxhttp's
-			// behavior, predating net/http supporting contexts natively)
-			// TODO(bradfitz): reconsider this in the future. But for now this
-			// requires no test updates.
-			return nil, ctx.Err()
-		default:
-			return nil, err
-		}
+		return "", err
 	}
-	return res, nil
-}
-
-func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
-	resp, err := c.head(ctx, url)
+	resp, err := c.doNoRetry(ctx, r)
 	if err != nil {
 		return "", err
 	}
@@ -852,24 +778,6 @@ func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bo
 	return cert, nil
 }
 
-// responseError creates an error of Error type from resp.
-func responseError(resp *http.Response) error {
-	// don't care if ReadAll returns an error:
-	// json.Unmarshal will fail in that case anyway
-	b, _ := ioutil.ReadAll(resp.Body)
-	e := &wireError{Status: resp.StatusCode}
-	if err := json.Unmarshal(b, e); err != nil {
-		// this is not a regular error response:
-		// populate detail with anything we received,
-		// e.Status will already contain HTTP response code value
-		e.Detail = string(b)
-		if e.Detail == "" {
-			e.Detail = resp.Status
-		}
-	}
-	return e.error(resp.Header)
-}
-
 // chainCert fetches CA certificate chain recursively by following "up" links.
 // Each recursive call increments the depth by 1, resulting in an error
 // if the recursion level reaches maxChainLen.
@@ -880,14 +788,11 @@ func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte
 		return nil, errors.New("acme: certificate chain is too deep")
 	}
 
-	res, err := c.get(ctx, url)
+	res, err := c.get(ctx, url, wantStatus(http.StatusOK))
 	if err != nil {
 		return nil, err
 	}
 	defer res.Body.Close()
-	if res.StatusCode != http.StatusOK {
-		return nil, responseError(res)
-	}
 	b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
 	if err != nil {
 		return nil, err
@@ -932,65 +837,6 @@ func linkHeader(h http.Header, rel string) []string {
 	return links
 }
 
-// sleeper returns a function that accepts the Retry-After HTTP header value
-// and an increment that's used with backoff to increasingly sleep on
-// consecutive calls until the context is done. If the Retry-After header
-// cannot be parsed, then backoff is used with a maximum sleep time of 10
-// seconds.
-func sleeper(ctx context.Context) func(ra string, inc int) error {
-	var count int
-	return func(ra string, inc int) error {
-		count += inc
-		d := backoff(count, 10*time.Second)
-		d = retryAfter(ra, d)
-		wakeup := time.NewTimer(d)
-		defer wakeup.Stop()
-		select {
-		case <-ctx.Done():
-			return ctx.Err()
-		case <-wakeup.C:
-			return nil
-		}
-	}
-}
-
-// retryAfter parses a Retry-After HTTP header value,
-// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
-// It returns d if v cannot be parsed.
-func retryAfter(v string, d time.Duration) time.Duration {
-	if i, err := strconv.Atoi(v); err == nil {
-		return time.Duration(i) * time.Second
-	}
-	t, err := http.ParseTime(v)
-	if err != nil {
-		return d
-	}
-	return t.Sub(timeNow())
-}
-
-// backoff computes a duration after which an n+1 retry iteration should occur
-// using truncated exponential backoff algorithm.
-//
-// The n argument is always bounded between 0 and 30.
-// The max argument defines upper bound for the returned value.
-func backoff(n int, max time.Duration) time.Duration {
-	if n < 0 {
-		n = 0
-	}
-	if n > 30 {
-		n = 30
-	}
-	var d time.Duration
-	if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
-		d = time.Duration(x.Int64()) * time.Millisecond
-	}
-	d += time.Duration(1<<uint(n)) * time.Second
-	if d > max {
-		return max
-	}
-	return d
-}
-
 // keyAuth generates a key authorization string for a given token.
 func keyAuth(pub crypto.PublicKey, token string) (string, error) {
 	th, err := JWKThumbprint(pub)
@@ -1000,15 +846,25 @@ func keyAuth(pub crypto.PublicKey, token string) (string, error) {
 	return fmt.Sprintf("%s.%s", token, th), nil
 }
 
+// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges.
+func defaultTLSChallengeCertTemplate() *x509.Certificate {
+	return &x509.Certificate{
+		SerialNumber:          big.NewInt(1),
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().Add(24 * time.Hour),
+		BasicConstraintsValid: true,
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+	}
+}
+
 // tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
 // with the given SANs and auto-generated public/private key pair.
 // The Subject Common Name is set to the first SAN to aid debugging.
 // To create a cert with a custom key pair, specify WithKey option.
 func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
-	var (
-		key  crypto.Signer
-		tmpl *x509.Certificate
-	)
+	var key crypto.Signer
+	tmpl := defaultTLSChallengeCertTemplate()
 	for _, o := range opt {
 		switch o := o.(type) {
 		case *certOptKey:
@@ -1017,7 +873,7 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
 			}
 			key = o.key
 		case *certOptTemplate:
-			var t = *(*x509.Certificate)(o) // shallow copy is ok
+			t := *(*x509.Certificate)(o) // shallow copy is ok
 			tmpl = &t
 		default:
 			// package's fault, if we let this happen:
@@ -1030,16 +886,6 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
 			return tls.Certificate{}, err
 		}
 	}
-	if tmpl == nil {
-		tmpl = &x509.Certificate{
-			SerialNumber:          big.NewInt(1),
-			NotBefore:             time.Now(),
-			NotAfter:              time.Now().Add(24 * time.Hour),
-			BasicConstraintsValid: true,
-			KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
-			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
-		}
-	}
 	tmpl.DNSNames = san
 	if len(san) > 0 {
 		tmpl.Subject.CommonName = san[0]
diff --git a/vendor/golang.org/x/crypto/acme/http.go b/vendor/golang.org/x/crypto/acme/http.go
new file mode 100644
index 0000000000000000000000000000000000000000..a43ce6a5fe7086eb45cea813ad7e3b11b2408ee8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/http.go
@@ -0,0 +1,281 @@
+// Copyright 2018 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 acme
+
+import (
+	"bytes"
+	"context"
+	"crypto"
+	"crypto/rand"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"math/big"
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// retryTimer encapsulates common logic for retrying unsuccessful requests.
+// It is not safe for concurrent use.
+type retryTimer struct {
+	// backoffFn provides backoff delay sequence for retries.
+	// See Client.RetryBackoff doc comment.
+	backoffFn func(n int, r *http.Request, res *http.Response) time.Duration
+	// n is the current retry attempt.
+	n int
+}
+
+func (t *retryTimer) inc() {
+	t.n++
+}
+
+// backoff pauses the current goroutine as described in Client.RetryBackoff.
+func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error {
+	d := t.backoffFn(t.n, r, res)
+	if d <= 0 {
+		return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n)
+	}
+	wakeup := time.NewTimer(d)
+	defer wakeup.Stop()
+	select {
+	case <-ctx.Done():
+		return ctx.Err()
+	case <-wakeup.C:
+		return nil
+	}
+}
+
+func (c *Client) retryTimer() *retryTimer {
+	f := c.RetryBackoff
+	if f == nil {
+		f = defaultBackoff
+	}
+	return &retryTimer{backoffFn: f}
+}
+
+// defaultBackoff provides default Client.RetryBackoff implementation
+// using a truncated exponential backoff algorithm,
+// as described in Client.RetryBackoff.
+//
+// The n argument is always bounded between 1 and 30.
+// The returned value is always greater than 0.
+func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration {
+	const max = 10 * time.Second
+	var jitter time.Duration
+	if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
+		// Set the minimum to 1ms to avoid a case where
+		// an invalid Retry-After value is parsed into 0 below,
+		// resulting in the 0 returned value which would unintentionally
+		// stop the retries.
+		jitter = (1 + time.Duration(x.Int64())) * time.Millisecond
+	}
+	if v, ok := res.Header["Retry-After"]; ok {
+		return retryAfter(v[0]) + jitter
+	}
+
+	if n < 1 {
+		n = 1
+	}
+	if n > 30 {
+		n = 30
+	}
+	d := time.Duration(1<<uint(n-1))*time.Second + jitter
+	if d > max {
+		return max
+	}
+	return d
+}
+
+// retryAfter parses a Retry-After HTTP header value,
+// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
+// It returns zero value if v cannot be parsed.
+func retryAfter(v string) time.Duration {
+	if i, err := strconv.Atoi(v); err == nil {
+		return time.Duration(i) * time.Second
+	}
+	t, err := http.ParseTime(v)
+	if err != nil {
+		return 0
+	}
+	return t.Sub(timeNow())
+}
+
+// resOkay is a function that reports whether the provided response is okay.
+// It is expected to keep the response body unread.
+type resOkay func(*http.Response) bool
+
+// wantStatus returns a function which reports whether the code
+// matches the status code of a response.
+func wantStatus(codes ...int) resOkay {
+	return func(res *http.Response) bool {
+		for _, code := range codes {
+			if code == res.StatusCode {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+// get issues an unsigned GET request to the specified URL.
+// It returns a non-error value only when ok reports true.
+//
+// get retries unsuccessful attempts according to c.RetryBackoff
+// until the context is done or a non-retriable error is received.
+func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) {
+	retry := c.retryTimer()
+	for {
+		req, err := http.NewRequest("GET", url, nil)
+		if err != nil {
+			return nil, err
+		}
+		res, err := c.doNoRetry(ctx, req)
+		switch {
+		case err != nil:
+			return nil, err
+		case ok(res):
+			return res, nil
+		case isRetriable(res.StatusCode):
+			retry.inc()
+			resErr := responseError(res)
+			res.Body.Close()
+			// Ignore the error value from retry.backoff
+			// and return the one from last retry, as received from the CA.
+			if retry.backoff(ctx, req, res) != nil {
+				return nil, resErr
+			}
+		default:
+			defer res.Body.Close()
+			return nil, responseError(res)
+		}
+	}
+}
+
+// post issues a signed POST request in JWS format using the provided key
+// to the specified URL.
+// It returns a non-error value only when ok reports true.
+//
+// post retries unsuccessful attempts according to c.RetryBackoff
+// until the context is done or a non-retriable error is received.
+// It uses postNoRetry to make individual requests.
+func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) {
+	retry := c.retryTimer()
+	for {
+		res, req, err := c.postNoRetry(ctx, key, url, body)
+		if err != nil {
+			return nil, err
+		}
+		if ok(res) {
+			return res, nil
+		}
+		resErr := responseError(res)
+		res.Body.Close()
+		switch {
+		// Check for bad nonce before isRetriable because it may have been returned
+		// with an unretriable response code such as 400 Bad Request.
+		case isBadNonce(resErr):
+			// Consider any previously stored nonce values to be invalid.
+			c.clearNonces()
+		case !isRetriable(res.StatusCode):
+			return nil, resErr
+		}
+		retry.inc()
+		// Ignore the error value from retry.backoff
+		// and return the one from last retry, as received from the CA.
+		if err := retry.backoff(ctx, req, res); err != nil {
+			return nil, resErr
+		}
+	}
+}
+
+// postNoRetry signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+// It is used by c.post to retry unsuccessful attempts.
+func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) {
+	nonce, err := c.popNonce(ctx, url)
+	if err != nil {
+		return nil, nil, err
+	}
+	b, err := jwsEncodeJSON(body, key, nonce)
+	if err != nil {
+		return nil, nil, err
+	}
+	req, err := http.NewRequest("POST", url, bytes.NewReader(b))
+	if err != nil {
+		return nil, nil, err
+	}
+	req.Header.Set("Content-Type", "application/jose+json")
+	res, err := c.doNoRetry(ctx, req)
+	if err != nil {
+		return nil, nil, err
+	}
+	c.addNonce(res.Header)
+	return res, req, nil
+}
+
+// doNoRetry issues a request req, replacing its context (if any) with ctx.
+func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) {
+	res, err := c.httpClient().Do(req.WithContext(ctx))
+	if err != nil {
+		select {
+		case <-ctx.Done():
+			// Prefer the unadorned context error.
+			// (The acme package had tests assuming this, previously from ctxhttp's
+			// behavior, predating net/http supporting contexts natively)
+			// TODO(bradfitz): reconsider this in the future. But for now this
+			// requires no test updates.
+			return nil, ctx.Err()
+		default:
+			return nil, err
+		}
+	}
+	return res, nil
+}
+
+func (c *Client) httpClient() *http.Client {
+	if c.HTTPClient != nil {
+		return c.HTTPClient
+	}
+	return http.DefaultClient
+}
+
+// isBadNonce reports whether err is an ACME "badnonce" error.
+func isBadNonce(err error) bool {
+	// According to the spec badNonce is urn:ietf:params:acme:error:badNonce.
+	// However, ACME servers in the wild return their versions of the error.
+	// See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
+	// and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66.
+	ae, ok := err.(*Error)
+	return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce")
+}
+
+// isRetriable reports whether a request can be retried
+// based on the response status code.
+//
+// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code.
+// Callers should parse the response and check with isBadNonce.
+func isRetriable(code int) bool {
+	return code <= 399 || code >= 500 || code == http.StatusTooManyRequests
+}
+
+// responseError creates an error of Error type from resp.
+func responseError(resp *http.Response) error {
+	// don't care if ReadAll returns an error:
+	// json.Unmarshal will fail in that case anyway
+	b, _ := ioutil.ReadAll(resp.Body)
+	e := &wireError{Status: resp.StatusCode}
+	if err := json.Unmarshal(b, e); err != nil {
+		// this is not a regular error response:
+		// populate detail with anything we received,
+		// e.Status will already contain HTTP response code value
+		e.Detail = string(b)
+		if e.Detail == "" {
+			e.Detail = resp.Status
+		}
+	}
+	return e.error(resp.Header)
+}
diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go
index 3e199749ecb7eb9a8366506a5d4a82dd305ec5a4..54792c0650fa9be0269d88bb0261b9875e581081 100644
--- a/vendor/golang.org/x/crypto/acme/types.go
+++ b/vendor/golang.org/x/crypto/acme/types.go
@@ -104,7 +104,7 @@ func RateLimit(err error) (time.Duration, bool) {
 	if e.Header == nil {
 		return 0, true
 	}
-	return retryAfter(e.Header.Get("Retry-After"), 0), true
+	return retryAfter(e.Header.Get("Retry-After")), true
 }
 
 // Account is a user account. It is associated with a private key.
@@ -296,8 +296,8 @@ func (e *wireError) error(h http.Header) *Error {
 	}
 }
 
-// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
-// customizing a temporary certificate for TLS-SNI challenges.
+// CertOption is an optional argument type for the TLS ChallengeCert methods for
+// customizing a temporary certificate for TLS-based challenges.
 type CertOption interface {
 	privateCertOpt()
 }
@@ -317,7 +317,7 @@ func (*certOptKey) privateCertOpt() {}
 // WithTemplate creates an option for specifying a certificate template.
 // See x509.CreateCertificate for template usage details.
 //
-// In TLSSNIxChallengeCert methods, the template is also used as parent,
+// In TLS ChallengeCert methods, the template is also used as parent,
 // resulting in a self-signed certificate.
 // The DNSNames field of t is always overwritten for tls-sni challenge certs.
 func WithTemplate(t *x509.Certificate) CertOption {
diff --git a/vendor/gopkg.in/yaml.v2/LICENSE b/vendor/gopkg.in/yaml.v2/LICENSE
index 8dada3edaf50dbc082c9a125058f25def75e625a..866d74a7ad79165312a2ce3904b4bdb53e6aedf7 100644
--- a/vendor/gopkg.in/yaml.v2/LICENSE
+++ b/vendor/gopkg.in/yaml.v2/LICENSE
@@ -1,201 +1,13 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
+Copyright 2011-2016 Canonical Ltd.
 
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
 
-   1. Definitions.
+    http://www.apache.org/licenses/LICENSE-2.0
 
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright {yyyy} {name of copyright owner}
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/vendor.json b/vendor/vendor.json
index ab8aecfdb9b9fcb2829ddcda2ab06dd2e76569c6..52086fd70358bb094f57b1150aae009d8532dbdb 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -3,28 +3,28 @@
 	"ignore": "test",
 	"package": [
 		{
-			"checksumSHA1": "gHJY2xf5fdCTGbBUf+QQba30lPA=",
+			"checksumSHA1": "raJx5BjBbVQG0ylGSjPpi+JvqjU=",
 			"path": "git.autistici.org/ai3/go-common",
-			"revision": "1c931821c1fcd47c904e85850c1b4c811148c28f",
-			"revisionTime": "2018-05-24T08:55:40Z"
+			"revision": "39b1908a9e399db1a0ceebb0fe4f3d3c35298357",
+			"revisionTime": "2018-08-17T06:38:25Z"
 		},
 		{
-			"checksumSHA1": "o+rWKVQIDy79ZwrItwa5/whAL6g=",
+			"checksumSHA1": "49MChcx9D+/+pCyl/F469TcQcK4=",
 			"path": "git.autistici.org/ai3/go-common/clientutil",
-			"revision": "1c931821c1fcd47c904e85850c1b4c811148c28f",
-			"revisionTime": "2018-05-24T08:55:40Z"
+			"revision": "39b1908a9e399db1a0ceebb0fe4f3d3c35298357",
+			"revisionTime": "2018-08-17T06:38:25Z"
 		},
 		{
 			"checksumSHA1": "7VBLbwaK1m/jwsk8sLsh4iD9T/s=",
 			"path": "git.autistici.org/ai3/go-common/serverutil",
-			"revision": "1c931821c1fcd47c904e85850c1b4c811148c28f",
-			"revisionTime": "2018-05-24T08:55:40Z"
+			"revision": "39b1908a9e399db1a0ceebb0fe4f3d3c35298357",
+			"revisionTime": "2018-08-17T06:38:25Z"
 		},
 		{
-			"checksumSHA1": "QZLvJV+CttBnZ0wK5D3XlKjKq0I=",
+			"checksumSHA1": "zCVstnZ23vTfA6oKC389y6Opglw=",
 			"path": "git.autistici.org/ai3/replds",
-			"revision": "47130d7caf4b0cfc8c445cdeee0d993a779ece60",
-			"revisionTime": "2018-05-24T08:58:05Z"
+			"revision": "a60c057e6e543d8842e83cbdd770350a4228fa2a",
+			"revisionTime": "2018-08-17T07:17:02Z"
 		},
 		{
 			"checksumSHA1": "spyv5/YFBjYyZLZa1U2LBfDR8PM=",
@@ -33,22 +33,22 @@
 			"revisionTime": "2016-08-04T10:47:26Z"
 		},
 		{
-			"checksumSHA1": "hTThB1Cw2ue02RD5Oig4eu1Dkzk=",
+			"checksumSHA1": "EAUmmJ4ccZbyuyf8Fnf+KU+DH3w=",
 			"path": "github.com/cenkalti/backoff",
-			"revision": "309aa717adbf351e92864cbedf9cca0b769a4b5a",
-			"revisionTime": "2017-10-07T11:45:50Z"
+			"revision": "b7325b0f3f1097c6546ea5e83c4a23267e58ad71",
+			"revisionTime": "2018-08-01T15:21:24Z"
 		},
 		{
 			"checksumSHA1": "+Zz+leZHHC9C0rx8DoRuffSRPso=",
 			"path": "github.com/coreos/go-systemd/daemon",
-			"revision": "d2196463941895ee908e13531a23a39feb9e1243",
-			"revisionTime": "2017-07-31T11:19:25Z"
+			"revision": "1f9909e51b2dab2487c26d64c8f2e7e580e4c9f5",
+			"revisionTime": "2017-03-24T09:58:19Z"
 		},
 		{
-			"checksumSHA1": "Pyou8mceOASSFxc7GeXZuVdSMi0=",
+			"checksumSHA1": "yqF125xVSkmfLpIVGrLlfE05IUk=",
 			"path": "github.com/golang/protobuf/proto",
-			"revision": "b4deda0973fb4c70b50d226b1af49f3da59f5265",
-			"revisionTime": "2018-04-30T18:52:41Z"
+			"revision": "1e59b77b52bf8e4b449a57e6f79f21226d571845",
+			"revisionTime": "2017-11-13T18:07:20Z"
 		},
 		{
 			"checksumSHA1": "t1nayUUugNoJWht7p4cbKyWuk8Q=",
@@ -62,41 +62,47 @@
 			"revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c",
 			"revisionTime": "2016-04-24T11:30:07Z"
 		},
+		{
+			"checksumSHA1": "Ovc3HTFXmFFlk8i1tf+4hEu3bx4=",
+			"path": "github.com/miekg/dns",
+			"revision": "874ec871288a738d8d87fd5cec1dd71e88fdacb2",
+			"revisionTime": "2015-09-23T21:02:39Z"
+		},
 		{
 			"checksumSHA1": "hu0MsbTdFzZxNRyAxe2HmTFFFak=",
 			"path": "github.com/prometheus/client_golang/prometheus",
-			"revision": "5cec1d0429b02e4323e042eb04dafdb079ddf568",
-			"revisionTime": "2017-10-05T11:29:15Z"
+			"revision": "661e31bf844dfca9aeba15f27ea8aa0d485ad212",
+			"revisionTime": "2017-12-01T12:22:22Z"
 		},
 		{
 			"checksumSHA1": "wsAkYlRRUNx+OAuUOIqdjO7dICM=",
 			"path": "github.com/prometheus/client_golang/prometheus/promhttp",
-			"revision": "5cec1d0429b02e4323e042eb04dafdb079ddf568",
-			"revisionTime": "2017-10-05T11:29:15Z"
+			"revision": "661e31bf844dfca9aeba15f27ea8aa0d485ad212",
+			"revisionTime": "2017-12-01T12:22:22Z"
 		},
 		{
 			"checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",
 			"path": "github.com/prometheus/client_model/go",
-			"revision": "6f3806018612930941127f2a7c6c453ba2c527d2",
-			"revisionTime": "2017-02-16T18:52:47Z"
+			"revision": "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c",
+			"revisionTime": "2017-11-17T10:05:41Z"
 		},
 		{
 			"checksumSHA1": "xfnn0THnqNwjwimeTClsxahYrIo=",
 			"path": "github.com/prometheus/common/expfmt",
-			"revision": "e3fb1a1acd7605367a2b378bc2e2f893c05174b7",
-			"revisionTime": "2017-11-04T09:59:07Z"
+			"revision": "2e54d0b93cba2fd133edc32211dcc32c06ef72ca",
+			"revisionTime": "2017-11-17T16:30:51Z"
 		},
 		{
 			"checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
 			"path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
-			"revision": "e3fb1a1acd7605367a2b378bc2e2f893c05174b7",
-			"revisionTime": "2017-11-04T09:59:07Z"
+			"revision": "2e54d0b93cba2fd133edc32211dcc32c06ef72ca",
+			"revisionTime": "2017-11-17T16:30:51Z"
 		},
 		{
-			"checksumSHA1": "3VoqH7TFfzA6Ds0zFzIbKCUvBmw=",
+			"checksumSHA1": "YU+/K48IMawQnToO4ETE6a+hhj4=",
 			"path": "github.com/prometheus/common/model",
-			"revision": "e3fb1a1acd7605367a2b378bc2e2f893c05174b7",
-			"revisionTime": "2017-11-04T09:59:07Z"
+			"revision": "2e54d0b93cba2fd133edc32211dcc32c06ef72ca",
+			"revisionTime": "2017-11-17T16:30:51Z"
 		},
 		{
 			"checksumSHA1": "pW1yt1G1J9jnQMCxr1TDI7LQr3s=",
@@ -111,22 +117,22 @@
 			"revisionTime": "2017-10-17T21:40:25Z"
 		},
 		{
-			"checksumSHA1": "zHLlCNnnX/KNVue2tHr+FWxbszA=",
+			"checksumSHA1": "FBc8PNxDwtV1tPS4LzJAX2oGNqM=",
 			"path": "golang.org/x/crypto/acme",
-			"revision": "4ec37c66abab2c7e02ae775328b2ff001c3f025a",
-			"revisionTime": "2018-05-05T00:22:42Z"
+			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
+			"revisionTime": "2018-06-20T09:14:27Z"
 		},
 		{
 			"checksumSHA1": "GtamqiJoL7PGHsN454AoffBFMa8=",
 			"path": "golang.org/x/net/context",
-			"revision": "f73e4c9ed3b7ebdd5f699a16a880c2b1994e50dd",
-			"revisionTime": "2018-05-08T00:58:03Z"
+			"revision": "c39426892332e1bb5ec0a434a079bf82f5d30c54",
+			"revisionTime": "2018-07-15T06:54:04Z"
 		},
 		{
-			"checksumSHA1": "RDJpJQwkF012L6m/2BJizyOksNw=",
+			"checksumSHA1": "o20lmjzBQyKD5LfLZ3OhUoMkLds=",
 			"path": "gopkg.in/yaml.v2",
-			"revision": "eb3733d160e74a9c7e442f435eb3bea458e1d19f",
-			"revisionTime": "2017-08-12T16:00:11Z"
+			"revision": "25c4ec802a7d637f88d584ab26798e94ad14c13b",
+			"revisionTime": "2017-07-21T12:20:51Z"
 		}
 	],
 	"rootPath": "git.autistici.org/ai3/acmeserver"