Browse Source

Update miekg/dns

~1 month of changes.
Ask Bjørn Hansen 10 years ago
parent
commit
3e3e6c5b55
33 changed files with 952 additions and 523 deletions
  1. 1 1
      Godeps/Godeps.json
  2. 3 2
      Godeps/_workspace/src/github.com/miekg/dns/.travis.yml
  3. 7 3
      Godeps/_workspace/src/github.com/miekg/dns/README.md
  4. 11 9
      Godeps/_workspace/src/github.com/miekg/dns/client_test.go
  5. 1 3
      Godeps/_workspace/src/github.com/miekg/dns/dns.go
  6. 129 108
      Godeps/_workspace/src/github.com/miekg/dns/dnssec.go
  7. 5 4
      Godeps/_workspace/src/github.com/miekg/dns/dnssec_keygen.go
  8. 6 5
      Godeps/_workspace/src/github.com/miekg/dns/dnssec_keyscan.go
  9. 61 120
      Godeps/_workspace/src/github.com/miekg/dns/dnssec_privkey.go
  10. 13 10
      Godeps/_workspace/src/github.com/miekg/dns/dnssec_test.go
  11. 6 5
      Godeps/_workspace/src/github.com/miekg/dns/doc.go
  12. 5 4
      Godeps/_workspace/src/github.com/miekg/dns/edns.go
  13. 25 0
      Godeps/_workspace/src/github.com/miekg/dns/fuzz_test.go
  14. 67 4
      Godeps/_workspace/src/github.com/miekg/dns/idn/punycode.go
  15. 4 3
      Godeps/_workspace/src/github.com/miekg/dns/idn/punycode_test.go
  16. 3 3
      Godeps/_workspace/src/github.com/miekg/dns/labels.go
  17. 6 7
      Godeps/_workspace/src/github.com/miekg/dns/msg.go
  18. 9 12
      Godeps/_workspace/src/github.com/miekg/dns/parse_test.go
  19. 3 1
      Godeps/_workspace/src/github.com/miekg/dns/privaterr.go
  20. 19 0
      Godeps/_workspace/src/github.com/miekg/dns/remote_test.go
  21. 84 0
      Godeps/_workspace/src/github.com/miekg/dns/sanitize.go
  22. 85 0
      Godeps/_workspace/src/github.com/miekg/dns/sanitize_test.go
  23. 93 23
      Godeps/_workspace/src/github.com/miekg/dns/server.go
  24. 52 1
      Godeps/_workspace/src/github.com/miekg/dns/server_test.go
  25. 10 15
      Godeps/_workspace/src/github.com/miekg/dns/sig0.go
  26. 4 3
      Godeps/_workspace/src/github.com/miekg/dns/sig0_test.go
  27. 13 25
      Godeps/_workspace/src/github.com/miekg/dns/types.go
  28. 3 0
      Godeps/_workspace/src/github.com/miekg/dns/udp.go
  29. 0 1
      Godeps/_workspace/src/github.com/miekg/dns/xfr.go
  30. 72 3
      Godeps/_workspace/src/github.com/miekg/dns/xfr_test.go
  31. 2 2
      Godeps/_workspace/src/github.com/miekg/dns/zgenerate.go
  32. 14 6
      Godeps/_workspace/src/github.com/miekg/dns/zscan.go
  33. 136 140
      Godeps/_workspace/src/github.com/miekg/dns/zscan_rr.go

+ 1 - 1
Godeps/Godeps.json

@@ -16,7 +16,7 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/miekg/dns",
 			"ImportPath": "github.com/miekg/dns",
-			"Rev": "8fdd5c33f834fe1c16ede39b38a6bc822d32d07f"
+			"Rev": "8395762c3490507cf5a27405fcd0e3d3dc547109"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/pborman/uuid",
 			"ImportPath": "github.com/pborman/uuid",

+ 3 - 2
Godeps/_workspace/src/github.com/miekg/dns/.travis.yml

@@ -1,6 +1,7 @@
 language: go
 language: go
+sudo: false
 go:
 go:
-  - 1.3
   - 1.4
   - 1.4
+  - 1.5
 script:
 script:
-  - go test -short -bench=.
+  - go test -race -bench=.

+ 7 - 3
Godeps/_workspace/src/github.com/miekg/dns/README.md

@@ -24,6 +24,7 @@ If you like this, you may also be interested in:
 
 
 A not-so-up-to-date-list-that-may-be-actually-current:
 A not-so-up-to-date-list-that-may-be-actually-current:
 
 
+* https://cloudflare.com
 * https://github.com/abh/geodns
 * https://github.com/abh/geodns
 * http://www.statdns.com/
 * http://www.statdns.com/
 * http://www.dnsinspect.com/
 * http://www.dnsinspect.com/
@@ -38,6 +39,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
 * https://github.com/tianon/rawdns
 * https://github.com/tianon/rawdns
 * https://mesosphere.github.io/mesos-dns/
 * https://mesosphere.github.io/mesos-dns/
 * https://pulse.turbobytes.com/
 * https://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
 
 
 Send pull request if you want to be listed here.
 Send pull request if you want to be listed here.
 
 
@@ -81,7 +85,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 *all of them*
 *all of them*
 
 
 * 103{4,5} - DNS standard
 * 103{4,5} - DNS standard
-* 1348 - NSAP record
+* 1348 - NSAP record (removed the record)
 * 1982 - Serial Arithmetic
 * 1982 - Serial Arithmetic
 * 1876 - LOC record
 * 1876 - LOC record
 * 1995 - IXFR
 * 1995 - IXFR
@@ -138,7 +142,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 ## TODO
 ## TODO
 
 
 * privatekey.Precompute() when signing?
 * privatekey.Precompute() when signing?
-* Last remaining RRs: APL, ATMA, A6 and NXT.
-* Missing in parsing: ISDN, UNSPEC, ATMA.
+* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
+* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
 * NSEC(3) cover/match/closest enclose.
 * NSEC(3) cover/match/closest enclose.
 * Replies with TC bit are not parsed to the end.
 * Replies with TC bit are not parsed to the end.

+ 11 - 9
Godeps/_workspace/src/github.com/miekg/dns/client_test.go

@@ -88,7 +88,6 @@ func TestClientEDNS0(t *testing.T) {
 
 
 // Validates the transmission and parsing of local EDNS0 options.
 // Validates the transmission and parsing of local EDNS0 options.
 func TestClientEDNS0Local(t *testing.T) {
 func TestClientEDNS0Local(t *testing.T) {
-
 	optStr1 := "1979:0x0707"
 	optStr1 := "1979:0x0707"
 	optStr2 := strconv.Itoa(EDNS0LOCALSTART) + ":0x0601"
 	optStr2 := strconv.Itoa(EDNS0LOCALSTART) + ":0x0601"
 
 
@@ -149,20 +148,24 @@ func TestClientEDNS0Local(t *testing.T) {
 	// Validate the local options in the reply.
 	// Validate the local options in the reply.
 	got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String()
 	got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String()
 	if got != optStr1 {
 	if got != optStr1 {
-		t.Log("failed to get local edns0 answer; got %s, expected %s", got, optStr1)
+		t.Logf("failed to get local edns0 answer; got %s, expected %s", got, optStr1)
 		t.Fail()
 		t.Fail()
 		t.Logf("%v\n", r)
 		t.Logf("%v\n", r)
 	}
 	}
 
 
 	got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String()
 	got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String()
 	if got != optStr2 {
 	if got != optStr2 {
-		t.Log("failed to get local edns0 answer; got %s, expected %s", got, optStr2)
+		t.Logf("failed to get local edns0 answer; got %s, expected %s", got, optStr2)
 		t.Fail()
 		t.Fail()
 		t.Logf("%v\n", r)
 		t.Logf("%v\n", r)
 	}
 	}
 }
 }
 
 
-func TestSingleSingleInflight(t *testing.T) {
+func TestSingleInflight(t *testing.T) {
+	// Test is inherently racy, because queries might actually be returned before the test
+	// is over, leading to multiple queries even with SingleInflight. This ofcourse then
+	// leads to diff. rrts and the test fails. Number of tests is now 3, to lower the chance
+	// for the race to hit.
 	HandleFunc("miek.nl.", HelloServer)
 	HandleFunc("miek.nl.", HelloServer)
 	defer HandleRemove("miek.nl.")
 	defer HandleRemove("miek.nl.")
 
 
@@ -177,7 +180,7 @@ func TestSingleSingleInflight(t *testing.T) {
 
 
 	c := new(Client)
 	c := new(Client)
 	c.SingleInflight = true
 	c.SingleInflight = true
-	nr := 10
+	nr := 3
 	ch := make(chan time.Duration)
 	ch := make(chan time.Duration)
 	for i := 0; i < nr; i++ {
 	for i := 0; i < nr; i++ {
 		go func() {
 		go func() {
@@ -188,7 +191,7 @@ func TestSingleSingleInflight(t *testing.T) {
 	i := 0
 	i := 0
 	var first time.Duration
 	var first time.Duration
 	// With inflight *all* rtt are identical, and by doing actual lookups
 	// With inflight *all* rtt are identical, and by doing actual lookups
-	// the changes that this is a coincidence is small.
+	// the chances that this is a coincidence is small.
 Loop:
 Loop:
 	for {
 	for {
 		select {
 		select {
@@ -197,11 +200,11 @@ Loop:
 				first = rtt
 				first = rtt
 			} else {
 			} else {
 				if first != rtt {
 				if first != rtt {
-					t.Errorf("all rtts should be equal.  got %d want %d", rtt, first)
+					t.Errorf("all rtts should be equal, got %d want %d", rtt, first)
 				}
 				}
 			}
 			}
 			i++
 			i++
-			if i == 10 {
+			if i == nr {
 				break Loop
 				break Loop
 			}
 			}
 		}
 		}
@@ -282,5 +285,4 @@ func TestClientConn(t *testing.T) {
 	if err = r.Unpack(buf); err != nil {
 	if err = r.Unpack(buf); err != nil {
 		t.Errorf("unable to unpack message fully: %v", err)
 		t.Errorf("unable to unpack message fully: %v", err)
 	}
 	}
-
 }
 }

+ 1 - 3
Godeps/_workspace/src/github.com/miekg/dns/dns.go

@@ -36,9 +36,7 @@ type RR interface {
 	len() int
 	len() int
 }
 }
 
 
-// DNS resource records.
-// There are many types of RRs,
-// but they all share the same header.
+// RR_Header is the header all DNS resource records share.
 type RR_Header struct {
 type RR_Header struct {
 	Name     string `dns:"cdomain-name"`
 	Name     string `dns:"cdomain-name"`
 	Rrtype   uint16
 	Rrtype   uint16

+ 129 - 108
Godeps/_workspace/src/github.com/miekg/dns/dnssec.go

@@ -6,14 +6,14 @@ import (
 	"crypto/dsa"
 	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/elliptic"
-	"crypto/md5"
+	_ "crypto/md5"
+	"crypto/rand"
 	"crypto/rsa"
 	"crypto/rsa"
-	"crypto/sha1"
-	"crypto/sha256"
-	"crypto/sha512"
+	_ "crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/asn1"
 	"encoding/hex"
 	"encoding/hex"
-	"hash"
-	"io"
 	"math/big"
 	"math/big"
 	"sort"
 	"sort"
 	"strings"
 	"strings"
@@ -42,6 +42,38 @@ const (
 	PRIVATEOID uint8 = 254
 	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.
 // DNSSEC hashing algorithm codes.
 const (
 const (
 	_      uint8 = iota
 	_      uint8 = iota
@@ -52,6 +84,18 @@ const (
 	SHA512       // 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.
 // DNSKEY flag values.
 const (
 const (
 	SEP    = 1
 	SEP    = 1
@@ -168,24 +212,23 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
 	// digest buffer
 	// digest buffer
 	digest := append(owner, wire...) // another copy
 	digest := append(owner, wire...) // another copy
 
 
+	var hash crypto.Hash
 	switch h {
 	switch h {
 	case SHA1:
 	case SHA1:
-		s := sha1.New()
-		io.WriteString(s, string(digest))
-		ds.Digest = hex.EncodeToString(s.Sum(nil))
+		hash = crypto.SHA1
 	case SHA256:
 	case SHA256:
-		s := sha256.New()
-		io.WriteString(s, string(digest))
-		ds.Digest = hex.EncodeToString(s.Sum(nil))
+		hash = crypto.SHA256
 	case SHA384:
 	case SHA384:
-		s := sha512.New384()
-		io.WriteString(s, string(digest))
-		ds.Digest = hex.EncodeToString(s.Sum(nil))
-	case GOST94:
-		/* I have no clue */
+		hash = crypto.SHA384
+	case SHA512:
+		hash = crypto.SHA512
 	default:
 	default:
 		return nil
 		return nil
 	}
 	}
+
+	s := hash.New()
+	s.Write(digest)
+	ds.Digest = hex.EncodeToString(s.Sum(nil))
 	return ds
 	return ds
 }
 }
 
 
@@ -212,7 +255,7 @@ func (d *DS) ToCDS() *CDS {
 // There is no check if RRSet is a proper (RFC 2181) RRSet.
 // 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
 // If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
 // is used as the OrigTTL.
 // is used as the OrigTTL.
-func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
+func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 	if k == nil {
 	if k == nil {
 		return ErrPrivKey
 		return ErrPrivKey
 	}
 	}
@@ -258,39 +301,66 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
 	}
 	}
 	signdata = append(signdata, wire...)
 	signdata = append(signdata, wire...)
 
 
-	var h hash.Hash
-	switch rr.Algorithm {
-	case DSA, DSANSEC3SHA1:
-		// TODO: this seems bugged, will panic
-	case RSASHA1, RSASHA1NSEC3SHA1:
-		h = sha1.New()
-	case RSASHA256, ECDSAP256SHA256:
-		h = sha256.New()
-	case ECDSAP384SHA384:
-		h = sha512.New384()
-	case RSASHA512:
-		h = sha512.New()
-	case RSAMD5:
-		fallthrough // Deprecated in RFC 6725
-	default:
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
 		return ErrAlg
 		return ErrAlg
 	}
 	}
 
 
-	_, err = h.Write(signdata)
-	if err != nil {
-		return err
-	}
-	sighash := h.Sum(nil)
+	h := hash.New()
+	h.Write(signdata)
 
 
-	signature, err := k.Sign(sighash, rr.Algorithm)
+	signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+
 	rr.Signature = toBase64(signature)
 	rr.Signature = toBase64(signature)
 
 
 	return nil
 	return nil
 }
 }
 
 
+func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
+	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
 // Verify validates an RRSet with the signature and key. This is only the
 // cryptographic test, the signature validity period must be checked separately.
 // cryptographic test, the signature validity period must be checked separately.
 // This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
 // This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
@@ -355,6 +425,11 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 		// remove the domain name and assume its our
 		// remove the domain name and assume its our
 	}
 	}
 
 
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
+		return ErrAlg
+	}
+
 	switch rr.Algorithm {
 	switch rr.Algorithm {
 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
 		// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
 		// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
@@ -362,52 +437,31 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 		if pubkey == nil {
 		if pubkey == nil {
 			return ErrKey
 			return ErrKey
 		}
 		}
-		// Setup the hash as defined for this alg.
-		var h hash.Hash
-		var ch crypto.Hash
-		switch rr.Algorithm {
-		case RSAMD5:
-			h = md5.New()
-			ch = crypto.MD5
-		case RSASHA1, RSASHA1NSEC3SHA1:
-			h = sha1.New()
-			ch = crypto.SHA1
-		case RSASHA256:
-			h = sha256.New()
-			ch = crypto.SHA256
-		case RSASHA512:
-			h = sha512.New()
-			ch = crypto.SHA512
-		}
-		io.WriteString(h, string(signeddata))
-		sighash := h.Sum(nil)
-		return rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf)
+
+		h := hash.New()
+		h.Write(signeddata)
+		return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
+
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		pubkey := k.publicKeyECDSA()
 		pubkey := k.publicKeyECDSA()
 		if pubkey == nil {
 		if pubkey == nil {
 			return ErrKey
 			return ErrKey
 		}
 		}
-		var h hash.Hash
-		switch rr.Algorithm {
-		case ECDSAP256SHA256:
-			h = sha256.New()
-		case ECDSAP384SHA384:
-			h = sha512.New384()
-		}
-		io.WriteString(h, string(signeddata))
-		sighash := h.Sum(nil)
+
 		// Split sigbuf into the r and s coordinates
 		// Split sigbuf into the r and s coordinates
-		r := big.NewInt(0)
-		r.SetBytes(sigbuf[:len(sigbuf)/2])
-		s := big.NewInt(0)
-		s.SetBytes(sigbuf[len(sigbuf)/2:])
-		if ecdsa.Verify(pubkey, sighash, r, s) {
+		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 nil
 		}
 		}
 		return ErrSig
 		return ErrSig
+
+	default:
+		return ErrAlg
 	}
 	}
-	// Unknown alg
-	return ErrAlg
 }
 }
 
 
 // ValidityPeriod uses RFC1982 serial arithmetic to calculate
 // ValidityPeriod uses RFC1982 serial arithmetic to calculate
@@ -603,36 +657,3 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 	}
 	}
 	return buf, nil
 	return buf, nil
 }
 }
-
-// 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 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)

+ 5 - 4
Godeps/_workspace/src/github.com/miekg/dns/dnssec_keygen.go

@@ -1,6 +1,7 @@
 package dns
 package dns
 
 
 import (
 import (
+	"crypto"
 	"crypto/dsa"
 	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/elliptic"
@@ -15,7 +16,7 @@ import (
 // what kind of DNSKEY will be generated.
 // what kind of DNSKEY will be generated.
 // The ECDSA algorithms imply a fixed keysize, in that case
 // The ECDSA algorithms imply a fixed keysize, in that case
 // bits should be set to the size of the algorithm.
 // bits should be set to the size of the algorithm.
-func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
+func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
 	switch k.Algorithm {
 	switch k.Algorithm {
 	case DSA, DSANSEC3SHA1:
 	case DSA, DSANSEC3SHA1:
 		if bits != 1024 {
 		if bits != 1024 {
@@ -52,14 +53,14 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
 			return nil, err
 			return nil, err
 		}
 		}
 		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
 		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
-		return (*DSAPrivateKey)(priv), nil
+		return priv, nil
 	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
 	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
 		priv, err := rsa.GenerateKey(rand.Reader, bits)
 		priv, err := rsa.GenerateKey(rand.Reader, bits)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 		k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
 		k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
-		return (*RSAPrivateKey)(priv), nil
+		return priv, nil
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		var c elliptic.Curve
 		var c elliptic.Curve
 		switch k.Algorithm {
 		switch k.Algorithm {
@@ -73,7 +74,7 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
 			return nil, err
 			return nil, err
 		}
 		}
 		k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
 		k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
-		return (*ECDSAPrivateKey)(priv), nil
+		return priv, nil
 	default:
 	default:
 		return nil, ErrAlg
 		return nil, ErrAlg
 	}
 	}

+ 6 - 5
Godeps/_workspace/src/github.com/miekg/dns/dnssec_keyscan.go

@@ -1,6 +1,7 @@
 package dns
 package dns
 
 
 import (
 import (
+	"crypto"
 	"crypto/dsa"
 	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/rsa"
@@ -12,7 +13,7 @@ import (
 
 
 // NewPrivateKey returns a PrivateKey by parsing the string s.
 // NewPrivateKey returns a PrivateKey by parsing the string s.
 // s should be in the same form of the BIND private key files.
 // s should be in the same form of the BIND private key files.
-func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
+func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
 	if s[len(s)-1] != '\n' { // We need a closing newline
 	if s[len(s)-1] != '\n' { // We need a closing newline
 		return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
 		return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
 	}
 	}
@@ -23,7 +24,7 @@ func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
 // only used in error reporting.
 // only used in error reporting.
 // The public key must be known, because some cryptographic algorithms embed
 // The public key must be known, because some cryptographic algorithms embed
 // the public inside the privatekey.
 // the public inside the privatekey.
-func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
+func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
 	m, e := parseKey(q, file)
 	m, e := parseKey(q, file)
 	if m == nil {
 	if m == nil {
 		return nil, e
 		return nil, e
@@ -50,7 +51,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
 			return nil, ErrKey
 			return nil, ErrKey
 		}
 		}
 		priv.PublicKey = *pub
 		priv.PublicKey = *pub
-		return (*DSAPrivateKey)(priv), e
+		return priv, e
 	case RSAMD5:
 	case RSAMD5:
 		fallthrough
 		fallthrough
 	case RSASHA1:
 	case RSASHA1:
@@ -69,7 +70,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
 			return nil, ErrKey
 			return nil, ErrKey
 		}
 		}
 		priv.PublicKey = *pub
 		priv.PublicKey = *pub
-		return (*RSAPrivateKey)(priv), e
+		return priv, e
 	case ECCGOST:
 	case ECCGOST:
 		return nil, ErrPrivKey
 		return nil, ErrPrivKey
 	case ECDSAP256SHA256:
 	case ECDSAP256SHA256:
@@ -84,7 +85,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
 			return nil, ErrKey
 			return nil, ErrKey
 		}
 		}
 		priv.PublicKey = *pub
 		priv.PublicKey = *pub
-		return (*ECDSAPrivateKey)(priv), e
+		return priv, e
 	default:
 	default:
 		return nil, ErrPrivKey
 		return nil, ErrPrivKey
 	}
 	}

+ 61 - 120
Godeps/_workspace/src/github.com/miekg/dns/dnssec_privkey.go

@@ -4,7 +4,6 @@ import (
 	"crypto"
 	"crypto"
 	"crypto/dsa"
 	"crypto/dsa"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
-	"crypto/rand"
 	"crypto/rsa"
 	"crypto/rsa"
 	"math/big"
 	"math/big"
 	"strconv"
 	"strconv"
@@ -12,133 +11,75 @@ import (
 
 
 const format = "Private-key-format: v1.3\n"
 const format = "Private-key-format: v1.3\n"
 
 
-// PrivateKey ... TODO(miek)
-type PrivateKey interface {
-	Sign([]byte, uint8) ([]byte, error)
-	String(uint8) string
-}
-
 // PrivateKeyString converts a PrivateKey to a string. This string has the same
 // PrivateKeyString converts a PrivateKey to a string. This string has the same
 // format as the private-key-file of BIND9 (Private-key-format: v1.3).
 // format as the private-key-file of BIND9 (Private-key-format: v1.3).
-// It needs some info from the key (the algorithm), so its a method of the
-// DNSKEY and calls PrivateKey.String(alg).
-func (r *DNSKEY) PrivateKeyString(p PrivateKey) string {
-	return p.String(r.Algorithm)
-}
+// 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] + ")"
 
 
-type RSAPrivateKey rsa.PrivateKey
+	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])
 
 
-func (p *RSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
-	var hash crypto.Hash
-	switch alg {
-	case RSASHA1, RSASHA1NSEC3SHA1:
-		hash = crypto.SHA1
-	case RSASHA256:
-		hash = crypto.SHA256
-	case RSASHA512:
-		hash = crypto.SHA512
-	default:
-		return nil, ErrAlg
-	}
-	return rsa.SignPKCS1v15(nil, (*rsa.PrivateKey)(p), hash, hashed)
-}
-
-func (p *RSAPrivateKey) String(alg uint8) string {
-	algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
-	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())
 
 
-	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"
 
 
-	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"
 
 
-type ECDSAPrivateKey ecdsa.PrivateKey
+	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"
 
 
-func (p *ECDSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
-	var intlen int
-	switch alg {
-	case ECDSAP256SHA256:
-		intlen = 32
-	case ECDSAP384SHA384:
-		intlen = 48
 	default:
 	default:
-		return nil, ErrAlg
-	}
-	r1, s1, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(p), hashed)
-	if err != nil {
-		return nil, err
+		return ""
 	}
 	}
-	signature := intToBytes(r1, intlen)
-	signature = append(signature, intToBytes(s1, intlen)...)
-	return signature, nil
-}
-
-func (p *ECDSAPrivateKey) String(alg uint8) string {
-	algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
-	var intlen int
-	switch alg {
-	case ECDSAP256SHA256:
-		intlen = 32
-	case ECDSAP384SHA384:
-		intlen = 48
-	}
-	private := toBase64(intToBytes(p.D, intlen))
-	return format +
-		"Algorithm: " + algorithm + "\n" +
-		"PrivateKey: " + private + "\n"
-}
-
-type DSAPrivateKey dsa.PrivateKey
-
-func (p *DSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
-	r1, s1, err := dsa.Sign(rand.Reader, (*dsa.PrivateKey)(p), hashed)
-	if err != nil {
-		return nil, err
-	}
-	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)...)
-	return signature, nil
-}
-
-func (p *DSAPrivateKey) String(alg uint8) string {
-	algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
-	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"
 }
 }

+ 13 - 10
Godeps/_workspace/src/github.com/miekg/dns/dnssec_test.go

@@ -1,6 +1,9 @@
 package dns
 package dns
 
 
 import (
 import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/rsa"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
@@ -192,7 +195,7 @@ func TestSignVerify(t *testing.T) {
 	sig.Algorithm = RSASHA256
 	sig.Algorithm = RSASHA256
 
 
 	for _, r := range []RR{soa, soa1, srv} {
 	for _, r := range []RR{soa, soa1, srv} {
-		if sig.Sign(privkey, []RR{r}) != nil {
+		if sig.Sign(privkey.(*rsa.PrivateKey), []RR{r}) != nil {
 			t.Error("failure to sign the record")
 			t.Error("failure to sign the record")
 			continue
 			continue
 		}
 		}
@@ -228,7 +231,7 @@ func Test65534(t *testing.T) {
 	sig.KeyTag = key.KeyTag()
 	sig.KeyTag = key.KeyTag()
 	sig.SignerName = key.Hdr.Name
 	sig.SignerName = key.Hdr.Name
 	sig.Algorithm = RSASHA256
 	sig.Algorithm = RSASHA256
-	if err := sig.Sign(privkey, []RR{t6}); err != nil {
+	if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{t6}); err != nil {
 		t.Error(err)
 		t.Error(err)
 		t.Error("failure to sign the TYPE65534 record")
 		t.Error("failure to sign the TYPE65534 record")
 	}
 	}
@@ -324,7 +327,7 @@ func TestKeyRSA(t *testing.T) {
 	sig.KeyTag = key.KeyTag()
 	sig.KeyTag = key.KeyTag()
 	sig.SignerName = key.Hdr.Name
 	sig.SignerName = key.Hdr.Name
 
 
-	if err := sig.Sign(priv, []RR{soa}); err != nil {
+	if err := sig.Sign(priv.(*rsa.PrivateKey), []RR{soa}); err != nil {
 		t.Error("failed to sign")
 		t.Error("failed to sign")
 		return
 		return
 	}
 	}
@@ -374,7 +377,7 @@ Activate: 20110302104537`
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 	switch priv := p.(type) {
 	switch priv := p.(type) {
-	case *RSAPrivateKey:
+	case *rsa.PrivateKey:
 		if 65537 != priv.PublicKey.E {
 		if 65537 != priv.PublicKey.E {
 			t.Error("exponenent should be 65537")
 			t.Error("exponenent should be 65537")
 		}
 		}
@@ -403,7 +406,7 @@ Activate: 20110302104537`
 	sig.SignerName = k.Hdr.Name
 	sig.SignerName = k.Hdr.Name
 	sig.Algorithm = k.Algorithm
 	sig.Algorithm = k.Algorithm
 
 
-	sig.Sign(p, []RR{soa})
+	sig.Sign(p.(*rsa.PrivateKey), []RR{soa})
 	if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
 	if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
 		t.Errorf("signature is not correct: %v", sig)
 		t.Errorf("signature is not correct: %v", sig)
 	}
 	}
@@ -443,7 +446,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
 	sig.SignerName = eckey.(*DNSKEY).Hdr.Name
 	sig.SignerName = eckey.(*DNSKEY).Hdr.Name
 	sig.Algorithm = eckey.(*DNSKEY).Algorithm
 	sig.Algorithm = eckey.(*DNSKEY).Algorithm
 
 
-	if sig.Sign(privkey, []RR{a}) != nil {
+	if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{a}) != nil {
 		t.Fatal("failure to sign the record")
 		t.Fatal("failure to sign the record")
 	}
 	}
 
 
@@ -491,7 +494,7 @@ func TestSignVerifyECDSA2(t *testing.T) {
 	sig.SignerName = key.Hdr.Name
 	sig.SignerName = key.Hdr.Name
 	sig.Algorithm = ECDSAP256SHA256
 	sig.Algorithm = ECDSAP256SHA256
 
 
-	if sig.Sign(privkey, []RR{srv}) != nil {
+	if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{srv}) != nil {
 		t.Fatal("failure to sign the record")
 		t.Fatal("failure to sign the record")
 	}
 	}
 
 
@@ -564,7 +567,7 @@ PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
 	}
 	}
 	ourRRSIG.Expiration, _ = StringToTime("20100909100439")
 	ourRRSIG.Expiration, _ = StringToTime("20100909100439")
 	ourRRSIG.Inception, _ = StringToTime("20100812100439")
 	ourRRSIG.Inception, _ = StringToTime("20100812100439")
-	err = ourRRSIG.Sign(priv, []RR{rrA})
+	err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -640,7 +643,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
 	}
 	}
 	ourRRSIG.Expiration, _ = StringToTime("20100909102025")
 	ourRRSIG.Expiration, _ = StringToTime("20100909102025")
 	ourRRSIG.Inception, _ = StringToTime("20100812102025")
 	ourRRSIG.Inception, _ = StringToTime("20100812102025")
-	err = ourRRSIG.Sign(priv, []RR{rrA})
+	err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -709,7 +712,7 @@ func TestInvalidRRSet(t *testing.T) {
 	}
 	}
 
 
 	// Sign the good record set and then make sure verification fails on the bad record set
 	// Sign the good record set and then make sure verification fails on the bad record set
-	if err := signature.Sign(privatekey, goodRecords); err != nil {
+	if err := signature.Sign(privatekey.(crypto.Signer), goodRecords); err != nil {
 		t.Fatal("Signing good records failed")
 		t.Fatal("Signing good records failed")
 	}
 	}
 
 

+ 6 - 5
Godeps/_workspace/src/github.com/miekg/dns/doc.go

@@ -13,7 +13,8 @@ Resource records are native types. They are not stored in wire format.
 Basic usage pattern for creating a new resource record:
 Basic usage pattern for creating a new resource record:
 
 
      r := new(dns.MX)
      r := new(dns.MX)
-     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
+     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
+	Class: dns.ClassINET, Ttl: 3600}
      r.Preference = 10
      r.Preference = 10
      r.Mx = "mx.miek.nl."
      r.Mx = "mx.miek.nl."
 
 
@@ -57,8 +58,8 @@ server configured on 127.0.0.1 and port 53:
      c := new(dns.Client)
      c := new(dns.Client)
      in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
      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:
+Suppressing multiple outstanding queries (with the same question, type and
+class) is as easy as setting:
 
 
 	c.SingleInflight = true
 	c.SingleInflight = true
 
 
@@ -118,7 +119,7 @@ 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
 should be added or removed. The table from RFC 2136 supplemented with the Go
 DNS function shows which functions exist to specify the prerequisites.
 DNS function shows which functions exist to specify the prerequisites.
 
 
-3.2.4 - Table Of Metavalues Used In Prerequisite Section
+ 3.2.4 - Table Of Metavalues Used In Prerequisite Section
 
 
   CLASS    TYPE     RDATA    Meaning                    Function
   CLASS    TYPE     RDATA    Meaning                    Function
   --------------------------------------------------------------
   --------------------------------------------------------------
@@ -133,7 +134,7 @@ 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
 be added or deleted. The next table shows the options you have and
 what functions to call.
 what functions to call.
 
 
-3.4.2.6 - Table Of Metavalues Used In Update Section
+ 3.4.2.6 - Table Of Metavalues Used In Update Section
 
 
   CLASS    TYPE     RDATA    Meaning                     Function
   CLASS    TYPE     RDATA    Meaning                     Function
   ---------------------------------------------------------------
   ---------------------------------------------------------------

+ 5 - 4
Godeps/_workspace/src/github.com/miekg/dns/edns.go

@@ -30,6 +30,7 @@ type OPT struct {
 	Option []EDNS0 `dns:"opt"`
 	Option []EDNS0 `dns:"opt"`
 }
 }
 
 
+// Header implements the RR interface.
 func (rr *OPT) Header() *RR_Header {
 func (rr *OPT) Header() *RR_Header {
 	return &rr.Hdr
 	return &rr.Hdr
 }
 }
@@ -176,7 +177,7 @@ 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) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
 func (e *EDNS0_NSID) String() string        { return string(e.Nsid) }
 func (e *EDNS0_NSID) String() string        { return string(e.Nsid) }
 
 
-// The subnet EDNS0 option is used to give the remote nameserver
+// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
 // an idea of where the client lives. It can then give back a different
 // an idea of where the client lives. It can then give back a different
 // answer depending on the location or network topology.
 // answer depending on the location or network topology.
 // Basic use pattern for creating an subnet option:
 // Basic use pattern for creating an subnet option:
@@ -291,7 +292,7 @@ func (e *EDNS0_SUBNET) String() (s string) {
 	return
 	return
 }
 }
 
 
-// The UL (Update Lease) EDNS0 (draft RFC) option is used to tell the server to set
+// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
 // an expiration on an update RR. This is helpful for clients that cannot clean
 // an expiration on an update RR. This is helpful for clients that cannot clean
 // up after themselves. This is a draft RFC and more information can be found at
 // up after themselves. This is a draft RFC and more information can be found at
 // http://files.dns-sd.org/draft-sekar-dns-ul.txt
 // http://files.dns-sd.org/draft-sekar-dns-ul.txt
@@ -329,7 +330,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
 	return nil
 	return nil
 }
 }
 
 
-// Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
+// 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.
 // Implemented for completeness, as the EDNS0 type code is assigned.
 type EDNS0_LLQ struct {
 type EDNS0_LLQ struct {
 	Code      uint16 // Always EDNS0LLQ
 	Code      uint16 // Always EDNS0LLQ
@@ -471,7 +472,7 @@ func (e *EDNS0_EXPIRE) unpack(b []byte) error {
 	return nil
 	return nil
 }
 }
 
 
-// The local EDNS0 option is used for local/experimental purposes.  The option
+// The EDNS0_LOCAL option is used for local/experimental purposes. The option
 // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
 // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
 // (RFC6891), although any unassigned code can actually be used.  The content of
 // (RFC6891), although any unassigned code can actually be used.  The content of
 // the option is made available in Data, unaltered.
 // the option is made available in Data, unaltered.

+ 25 - 0
Godeps/_workspace/src/github.com/miekg/dns/fuzz_test.go

@@ -0,0 +1,25 @@
+package dns
+
+import "testing"
+
+func TestFuzzString(t *testing.T) {
+	testcases := []string{"", " MINFO ", "	RP ", "	NSEC 0 0", "	\" NSEC 0 0\"", "  \" MINFO \"",
+		";a ", ";a����������",
+		"	NSAP O ", "  NSAP N ",
+		" TYPE4 TYPE6a789a3bc0045c8a5fb42c7d1bd998f5444 IN 9579b47d46817afbd17273e6",
+		" TYPE45 3 3 4147994 TYPE\\(\\)\\)\\(\\)\\(\\(\\)\\(\\)\\)\\)\\(\\)\\(\\)\\(\\(\\R 948\"\")\\(\\)\\)\\)\\(\\ ",
+		"$GENERATE 0-3 ${441189,5039418474430,o}",
+		"$INCLUDE 00 TYPE00000000000n ",
+		"$INCLUDE PE4 TYPE061463623/727071511 \\(\\)\\$GENERATE 6-462/0",
+	}
+	for i, tc := range testcases {
+		rr, err := NewRR(tc)
+		if err == nil {
+			// rr can be nil because we can (for instance) just parse a comment
+			if rr == nil {
+				continue
+			}
+			t.Fatalf("parsed mailformed RR %d: %s", i, rr.String())
+		}
+	}
+}

+ 67 - 4
Godeps/_workspace/src/github.com/miekg/dns/idn/punycode.go

@@ -5,6 +5,7 @@ import (
 	"bytes"
 	"bytes"
 	"strings"
 	"strings"
 	"unicode"
 	"unicode"
+	"unicode/utf8"
 
 
 	"github.com/abh/geodns/Godeps/_workspace/src/github.com/miekg/dns"
 	"github.com/abh/geodns/Godeps/_workspace/src/github.com/miekg/dns"
 )
 )
@@ -27,9 +28,15 @@ const (
 )
 )
 
 
 // ToPunycode converts unicode domain names to DNS-appropriate punycode names.
 // ToPunycode converts unicode domain names to DNS-appropriate punycode names.
-// This function would return an empty string result for domain names with
+// This function will return an empty string result for domain names with
 // invalid unicode strings. This function expects domain names in lowercase.
 // invalid unicode strings. This function expects domain names in lowercase.
 func ToPunycode(s string) string {
 func ToPunycode(s string) string {
+	// Early check to see if encoding is needed.
+	// This will prevent making heap allocations when not needed.
+	if !needToPunycode(s) {
+		return s
+	}
+
 	tokens := dns.SplitDomainName(s)
 	tokens := dns.SplitDomainName(s)
 	switch {
 	switch {
 	case s == "":
 	case s == "":
@@ -51,7 +58,14 @@ func ToPunycode(s string) string {
 }
 }
 
 
 // FromPunycode returns unicode domain name from provided punycode string.
 // FromPunycode returns unicode domain name from provided punycode string.
+// This function expects punycode strings in lowercase.
 func FromPunycode(s string) string {
 func FromPunycode(s string) string {
+	// Early check to see if decoding is needed.
+	// This will prevent making heap allocations when not needed.
+	if !needFromPunycode(s) {
+		return s
+	}
+
 	tokens := dns.SplitDomainName(s)
 	tokens := dns.SplitDomainName(s)
 	switch {
 	switch {
 	case s == "":
 	case s == "":
@@ -124,7 +138,7 @@ func next(b []rune, boundary rune) rune {
 }
 }
 
 
 // preprune converts unicode rune to lower case. At this time it's not
 // preprune converts unicode rune to lower case. At this time it's not
-// supporting all things described in RFCs
+// supporting all things described in RFCs.
 func preprune(r rune) rune {
 func preprune(r rune) rune {
 	if unicode.IsUpper(r) {
 	if unicode.IsUpper(r) {
 		r = unicode.ToLower(r)
 		r = unicode.ToLower(r)
@@ -132,7 +146,7 @@ func preprune(r rune) rune {
 	return r
 	return r
 }
 }
 
 
-// tfunc is a function that helps calculate each character weight
+// tfunc is a function that helps calculate each character weight.
 func tfunc(k, bias rune) rune {
 func tfunc(k, bias rune) rune {
 	switch {
 	switch {
 	case k <= bias:
 	case k <= bias:
@@ -143,6 +157,51 @@ func tfunc(k, bias rune) rune {
 	return k - bias
 	return k - bias
 }
 }
 
 
+// needToPunycode returns true for strings that require punycode encoding
+// (contain unicode characters).
+func needToPunycode(s string) bool {
+	// This function is very similar to bytes.Runes. We don't use bytes.Runes
+	// because it makes a heap allocation that's not needed here.
+	for i := 0; len(s) > 0; i++ {
+		r, l := utf8.DecodeRuneInString(s)
+		if r > 0x7f {
+			return true
+		}
+		s = s[l:]
+	}
+	return false
+}
+
+// needFromPunycode returns true for strings that require punycode decoding.
+func needFromPunycode(s string) bool {
+	if s == "." {
+		return false
+	}
+
+	off := 0
+	end := false
+	pl := len(_PREFIX)
+	sl := len(s)
+
+	// If s starts with _PREFIX.
+	if sl > pl && s[off:off+pl] == _PREFIX {
+		return true
+	}
+
+	for {
+		// Find the part after the next ".".
+		off, end = dns.NextLabel(s, off)
+		if end {
+			return false
+		}
+		// If this parts starts with _PREFIX.
+		if sl-off > pl && s[off:off+pl] == _PREFIX {
+			return true
+		}
+	}
+	panic("dns: not reached")
+}
+
 // encode transforms Unicode input bytes (that represent DNS label) into
 // encode transforms Unicode input bytes (that represent DNS label) into
 // punycode bytestream. This function would return nil if there's an invalid
 // punycode bytestream. This function would return nil if there's an invalid
 // character in the label.
 // character in the label.
@@ -217,7 +276,7 @@ func encode(input []byte) []byte {
 	return out.Bytes()
 	return out.Bytes()
 }
 }
 
 
-// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream
+// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream.
 func decode(b []byte) []byte {
 func decode(b []byte) []byte {
 	src := b // b would move and we need to keep it
 	src := b // b would move and we need to keep it
 
 
@@ -254,6 +313,10 @@ func decode(b []byte) []byte {
 				return src
 				return src
 			}
 			}
 			i += digit * w
 			i += digit * w
+			if i < 0 {
+				// safety check for rune overflow
+				return src
+			}
 
 
 			t = tfunc(k, bias)
 			t = tfunc(k, bias)
 			if digit < t {
 			if digit < t {

+ 4 - 3
Godeps/_workspace/src/github.com/miekg/dns/idn/punycode_test.go

@@ -8,9 +8,9 @@ import (
 var testcases = [][2]string{
 var testcases = [][2]string{
 	{"", ""},
 	{"", ""},
 	{"a", "a"},
 	{"a", "a"},
-	{"A-B", "a-b"},
-	{"A-B-C", "a-b-c"},
-	{"AbC", "abc"},
+	{"a-b", "a-b"},
+	{"a-b-c", "a-b-c"},
+	{"abc", "abc"},
 	{"я", "xn--41a"},
 	{"я", "xn--41a"},
 	{"zя", "xn--z-0ub"},
 	{"zя", "xn--z-0ub"},
 	{"яZ", "xn--z-zub"},
 	{"яZ", "xn--z-zub"},
@@ -86,6 +86,7 @@ var invalidACEs = []string{
 	"xn--*",
 	"xn--*",
 	"xn--",
 	"xn--",
 	"xn---",
 	"xn---",
+	"xn--a000000000",
 }
 }
 
 
 func TestInvalidPunycode(t *testing.T) {
 func TestInvalidPunycode(t *testing.T) {

+ 3 - 3
Godeps/_workspace/src/github.com/miekg/dns/labels.go

@@ -98,12 +98,11 @@ func CountLabel(s string) (labels int) {
 			return
 			return
 		}
 		}
 	}
 	}
-	panic("dns: not reached")
 }
 }
 
 
 // Split splits a name s into its label indexes.
 // 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}.
 // www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
-// The root name (.) returns nil. Also see dns.SplitDomainName.
+// The root name (.) returns nil. Also see SplitDomainName.
 func Split(s string) []int {
 func Split(s string) []int {
 	if s == "." {
 	if s == "." {
 		return nil
 		return nil
@@ -119,12 +118,12 @@ func Split(s string) []int {
 		}
 		}
 		idx = append(idx, off)
 		idx = append(idx, off)
 	}
 	}
-	panic("dns: not reached")
 }
 }
 
 
 // NextLabel returns the index of the start of the next label in the
 // NextLabel returns the index of the start of the next label in the
 // string s starting at offset.
 // string s starting at offset.
 // The bool end is true when the end of the string has been reached.
 // The bool end is true when the end of the string has been reached.
+// Also see PrevLabel.
 func NextLabel(s string, offset int) (i int, end bool) {
 func NextLabel(s string, offset int) (i int, end bool) {
 	quote := false
 	quote := false
 	for i = offset; i < len(s)-1; i++ {
 	for i = offset; i < len(s)-1; i++ {
@@ -147,6 +146,7 @@ func NextLabel(s string, offset int) (i int, end bool) {
 // PrevLabel returns the index of the label when starting from the right and
 // PrevLabel returns the index of the label when starting from the right and
 // jumping n labels to the left.
 // jumping n labels to the left.
 // The bool start is true when the start of the string has been overshot.
 // The bool start is true when the start of the string has been overshot.
+// Also see NextLabel.
 func PrevLabel(s string, n int) (i int, start bool) {
 func PrevLabel(s string, n int) (i int, start bool) {
 	if n == 0 {
 	if n == 0 {
 		return len(s), false
 		return len(s), false

+ 6 - 7
Godeps/_workspace/src/github.com/miekg/dns/msg.go

@@ -29,8 +29,6 @@ var (
 	ErrAuth error = &Error{err: "bad authentication"}
 	ErrAuth error = &Error{err: "bad authentication"}
 	// ErrBuf indicates that the buffer used it too small for the message.
 	// ErrBuf indicates that the buffer used it too small for the message.
 	ErrBuf error = &Error{err: "buffer size too small"}
 	ErrBuf error = &Error{err: "buffer size too small"}
-	// ErrConn indicates that a connection has both a TCP and UDP socket.
-	ErrConn error = &Error{err: "conn holds both UDP and TCP connection"}
 	// ErrConnEmpty indicates a connection is being uses before it is initialized.
 	// ErrConnEmpty indicates a connection is being uses before it is initialized.
 	ErrConnEmpty error = &Error{err: "conn has no connection"}
 	ErrConnEmpty error = &Error{err: "conn has no connection"}
 	// ErrExtendedRcode ...
 	// ErrExtendedRcode ...
@@ -38,7 +36,8 @@ var (
 	// ErrFqdn indicates that a domain name does not have a closing dot.
 	// ErrFqdn indicates that a domain name does not have a closing dot.
 	ErrFqdn error = &Error{err: "domain must be fully qualified"}
 	ErrFqdn error = &Error{err: "domain must be fully qualified"}
 	// ErrId indicates there is a mismatch with the message's ID.
 	// ErrId indicates there is a mismatch with the message's ID.
-	ErrId        error = &Error{err: "id mismatch"}
+	ErrId error = &Error{err: "id mismatch"}
+	// ErrKeyAlg indicates that the algorithm in the key is not valid.
 	ErrKeyAlg    error = &Error{err: "bad key algorithm"}
 	ErrKeyAlg    error = &Error{err: "bad key algorithm"}
 	ErrKey       error = &Error{err: "bad key"}
 	ErrKey       error = &Error{err: "bad key"}
 	ErrKeySize   error = &Error{err: "bad key size"}
 	ErrKeySize   error = &Error{err: "bad key size"}
@@ -51,8 +50,6 @@ var (
 	ErrShortRead error = &Error{err: "short read"}
 	ErrShortRead error = &Error{err: "short read"}
 	// ErrSig indicates that a signature can not be cryptographically validated.
 	// ErrSig indicates that a signature can not be cryptographically validated.
 	ErrSig error = &Error{err: "bad signature"}
 	ErrSig error = &Error{err: "bad signature"}
-	// ErrSigGen indicates a faulure to generate a signature.
-	ErrSigGen error = &Error{err: "bad signature generation"}
 	// ErrSOA indicates that no SOA RR was seen when doing zone transfers.
 	// ErrSOA indicates that no SOA RR was seen when doing zone transfers.
 	ErrSoa error = &Error{err: "no SOA"}
 	ErrSoa error = &Error{err: "no SOA"}
 	// ErrTime indicates a timing error in TSIG authentication.
 	// ErrTime indicates a timing error in TSIG authentication.
@@ -138,7 +135,6 @@ var TypeToString = map[uint16]string{
 	TypeNINFO:      "NINFO",
 	TypeNINFO:      "NINFO",
 	TypeNIMLOC:     "NIMLOC",
 	TypeNIMLOC:     "NIMLOC",
 	TypeNS:         "NS",
 	TypeNS:         "NS",
-	TypeNSAP:       "NSAP",
 	TypeNSAPPTR:    "NSAP-PTR",
 	TypeNSAPPTR:    "NSAP-PTR",
 	TypeNSEC3:      "NSEC3",
 	TypeNSEC3:      "NSEC3",
 	TypeNSEC3PARAM: "NSEC3PARAM",
 	TypeNSEC3PARAM: "NSEC3PARAM",
@@ -237,7 +233,7 @@ var RcodeToString = map[int]string{
 // PackDomainName packs a domain name s into msg[off:].
 // PackDomainName packs a domain name s into msg[off:].
 // If compression is wanted compress must be true and the compression
 // If compression is wanted compress must be true and the compression
 // map needs to hold a mapping between domain names and offsets
 // map needs to hold a mapping between domain names and offsets
-// pointing into msg[].
+// pointing into msg.
 func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
 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)
 	off1, _, err = packDomainName(s, msg, off, compression, compress)
 	return
 	return
@@ -1701,6 +1697,9 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
 	// an error, because technically it isn't an error. So return
 	// an error, because technically it isn't an error. So return
 	// without parsing the potentially corrupt packet and hitting an error.
 	// without parsing the potentially corrupt packet and hitting an error.
 	// TODO(miek): this isn't the best strategy!
 	// 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 {
 	if dns.Truncated {
 		dns.Answer = nil
 		dns.Answer = nil
 		dns.Ns = nil
 		dns.Ns = nil

+ 9 - 12
Godeps/_workspace/src/github.com/miekg/dns/parse_test.go

@@ -905,16 +905,13 @@ func TestILNP(t *testing.T) {
 	}
 	}
 }
 }
 
 
-func TestNsapGposEidNimloc(t *testing.T) {
+func TestGposEidNimloc(t *testing.T) {
 	dt := map[string]string{
 	dt := map[string]string{
-		"foo.bar.com.    IN  NSAP   21 47000580ffff000000321099991111222233334444": "foo.bar.com.\t3600\tIN\tNSAP\t0x47000580ffff000000321099991111222233334444",
-		"foo.bar.com.    IN  NSAP   0x47000580ffff000000321099991111222233334444":  "foo.bar.com.\t3600\tIN\tNSAP\t0x47000580ffff000000321099991111222233334444",
-		"host.school.de  IN  NSAP   17 39276f3100111100002222333344449876":         "host.school.de.\t3600\tIN\tNSAP\t0x39276f3100111100002222333344449876",
-		"444433332222111199990123000000ff. NSAP-PTR foo.bar.com.":                  "444433332222111199990123000000ff.\t3600\tIN\tNSAP-PTR\tfoo.bar.com.",
-		"lillee. IN  GPOS -32.6882 116.8652 10.0":                                  "lillee.\t3600\tIN\tGPOS\t-32.6882 116.8652 10.0",
-		"hinault. IN GPOS -22.6882 116.8652 250.0":                                 "hinault.\t3600\tIN\tGPOS\t-22.6882 116.8652 250.0",
-		"VENERA.   IN NIMLOC  75234159EAC457800920":                                "VENERA.\t3600\tIN\tNIMLOC\t75234159EAC457800920",
-		"VAXA.     IN EID     3141592653589793":                                    "VAXA.\t3600\tIN\tEID\t3141592653589793",
+		"444433332222111199990123000000ff. NSAP-PTR foo.bar.com.": "444433332222111199990123000000ff.\t3600\tIN\tNSAP-PTR\tfoo.bar.com.",
+		"lillee. IN  GPOS -32.6882 116.8652 10.0":                 "lillee.\t3600\tIN\tGPOS\t-32.6882 116.8652 10.0",
+		"hinault. IN GPOS -22.6882 116.8652 250.0":                "hinault.\t3600\tIN\tGPOS\t-22.6882 116.8652 250.0",
+		"VENERA.   IN NIMLOC  75234159EAC457800920":               "VENERA.\t3600\tIN\tNIMLOC\t75234159EAC457800920",
+		"VAXA.     IN EID     3141592653589793":                   "VAXA.\t3600\tIN\tEID\t3141592653589793",
 	}
 	}
 	for i, o := range dt {
 	for i, o := range dt {
 		rr, err := NewRR(i)
 		rr, err := NewRR(i)
@@ -1240,8 +1237,8 @@ func TestNewPrivateKey(t *testing.T) {
 		}
 		}
 
 
 		switch newPrivKey := newPrivKey.(type) {
 		switch newPrivKey := newPrivKey.(type) {
-		case *RSAPrivateKey:
-			(*rsa.PrivateKey)(newPrivKey).Precompute()
+		case *rsa.PrivateKey:
+			newPrivKey.Precompute()
 		}
 		}
 
 
 		if !reflect.DeepEqual(privkey, newPrivKey) {
 		if !reflect.DeepEqual(privkey, newPrivKey) {
@@ -1510,7 +1507,7 @@ func TestPackCAA(t *testing.T) {
 func TestParseURI(t *testing.T) {
 func TestParseURI(t *testing.T) {
 	lt := map[string]string{
 	lt := map[string]string{
 		"_http._tcp. IN URI   10 1 \"http://www.example.com/path\"": "_http._tcp.\t3600\tIN\tURI\t10 1 \"http://www.example.com/path\"",
 		"_http._tcp. IN URI   10 1 \"http://www.example.com/path\"": "_http._tcp.\t3600\tIN\tURI\t10 1 \"http://www.example.com/path\"",
-		"_http._tcp. IN URI   10 1 \"\"": "_http._tcp.\t3600\tIN\tURI\t10 1 \"\"",
+		"_http._tcp. IN URI   10 1 \"\"":                            "_http._tcp.\t3600\tIN\tURI\t10 1 \"\"",
 	}
 	}
 	for i, o := range lt {
 	for i, o := range lt {
 		rr, err := NewRR(i)
 		rr, err := NewRR(i)

+ 3 - 1
Godeps/_workspace/src/github.com/miekg/dns/privaterr.go

@@ -46,8 +46,10 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
 	panic(fmt.Sprintf("dns: RR is not a PrivateRR, typeToRR[%d] generator returned %T", rrtype, anyrr))
 	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) Header() *RR_Header { return &r.Hdr }
-func (r *PrivateRR) String() string     { return r.Hdr.String() + r.Data.String() }
+
+func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
 
 
 // Private len and copy parts to satisfy RR interface.
 // Private len and copy parts to satisfy RR interface.
 func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
 func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }

+ 19 - 0
Godeps/_workspace/src/github.com/miekg/dns/remote_test.go

@@ -0,0 +1,19 @@
+package dns
+
+import "testing"
+
+const LinodeAddr = "176.58.119.54:53"
+
+func TestClientRemote(t *testing.T) {
+	m := new(Msg)
+	m.SetQuestion("go.dns.miek.nl.", TypeTXT)
+
+	c := new(Client)
+	r, _, err := c.Exchange(m, LinodeAddr)
+	if err != nil {
+		t.Errorf("failed to exchange: %v", err)
+	}
+	if r != nil && r.Rcode != RcodeSuccess {
+		t.Errorf("failed to get an valid answer\n%v", r)
+	}
+}

+ 84 - 0
Godeps/_workspace/src/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])
+}

+ 85 - 0
Godeps/_workspace/src/github.com/miekg/dns/sanitize_test.go

@@ -0,0 +1,85 @@
+package dns
+
+import "testing"
+
+func TestDedup(t *testing.T) {
+	// make it []string
+	testcases := map[[3]RR][]string{
+		[...]RR{
+			newRR(t, "mIek.nl. IN A 127.0.0.1"),
+			newRR(t, "mieK.nl. IN A 127.0.0.1"),
+			newRR(t, "miek.Nl. IN A 127.0.0.1"),
+		}: []string{"mIek.nl.\t3600\tIN\tA\t127.0.0.1"},
+		[...]RR{
+			newRR(t, "miEk.nl. 2000 IN A 127.0.0.1"),
+			newRR(t, "mieK.Nl. 1000 IN A 127.0.0.1"),
+			newRR(t, "Miek.nL. 500 IN A 127.0.0.1"),
+		}: []string{"miEk.nl.\t500\tIN\tA\t127.0.0.1"},
+		[...]RR{
+			newRR(t, "miek.nl. IN A 127.0.0.1"),
+			newRR(t, "miek.nl. CH A 127.0.0.1"),
+			newRR(t, "miek.nl. IN A 127.0.0.1"),
+		}: []string{"miek.nl.\t3600\tIN\tA\t127.0.0.1",
+			"miek.nl.\t3600\tCH\tA\t127.0.0.1",
+		},
+		[...]RR{
+			newRR(t, "miek.nl. CH A 127.0.0.1"),
+			newRR(t, "miek.nl. IN A 127.0.0.1"),
+			newRR(t, "miek.de. IN A 127.0.0.1"),
+		}: []string{"miek.nl.\t3600\tCH\tA\t127.0.0.1",
+			"miek.nl.\t3600\tIN\tA\t127.0.0.1",
+			"miek.de.\t3600\tIN\tA\t127.0.0.1",
+		},
+		[...]RR{
+			newRR(t, "miek.de. IN A 127.0.0.1"),
+			newRR(t, "miek.nl. 200 IN A 127.0.0.1"),
+			newRR(t, "miek.nl. 300 IN A 127.0.0.1"),
+		}: []string{"miek.de.\t3600\tIN\tA\t127.0.0.1",
+			"miek.nl.\t200\tIN\tA\t127.0.0.1",
+		},
+	}
+
+	for rr, expected := range testcases {
+		out := Dedup([]RR{rr[0], rr[1], rr[2]}, nil)
+		for i, o := range out {
+			if o.String() != expected[i] {
+				t.Fatalf("expected %v, got %v", expected[i], o.String())
+			}
+		}
+	}
+}
+
+func BenchmarkDedup(b *testing.B) {
+	rrs := []RR{
+		newRR(nil, "miEk.nl. 2000 IN A 127.0.0.1"),
+		newRR(nil, "mieK.Nl. 1000 IN A 127.0.0.1"),
+		newRR(nil, "Miek.nL. 500 IN A 127.0.0.1"),
+	}
+	m := make(map[string]RR)
+	for i := 0; i < b.N; i++ {
+		Dedup(rrs,m )
+	}
+}
+
+func TestNormalizedString(t *testing.T) {
+	tests := map[RR]string{
+		newRR(t, "mIEk.Nl. 3600 IN A 127.0.0.1"):     "miek.nl.\tIN\tA\t127.0.0.1",
+		newRR(t, "m\\ iek.nL. 3600 IN A 127.0.0.1"):  "m\\ iek.nl.\tIN\tA\t127.0.0.1",
+		newRR(t, "m\\\tIeK.nl. 3600 in A 127.0.0.1"): "m\\tiek.nl.\tIN\tA\t127.0.0.1",
+	}
+	for tc, expected := range tests {
+		n := normalizedString(tc)
+		if n != expected {
+			t.Logf("expected %s, got %s", expected, n)
+			t.Fail()
+		}
+	}
+}
+
+func newRR(t *testing.T, s string) RR {
+	r, e := NewRR(s)
+	if e != nil {
+		t.Logf("newRR: %s", e)
+	}
+	return r
+}

+ 93 - 23
Godeps/_workspace/src/github.com/miekg/dns/server.go

@@ -10,6 +10,9 @@ import (
 	"time"
 	"time"
 )
 )
 
 
+// Maximum number of TCP queries before we close the socket.
+const maxTCPQueries = 128
+
 // Handler is implemented by any value that implements ServeDNS.
 // Handler is implemented by any value that implements ServeDNS.
 type Handler interface {
 type Handler interface {
 	ServeDNS(w ResponseWriter, r *Msg)
 	ServeDNS(w ResponseWriter, r *Msg)
@@ -47,6 +50,7 @@ type response struct {
 	tcp            *net.TCPConn      // i/o connection if TCP was used
 	tcp            *net.TCPConn      // i/o connection if TCP was used
 	udpSession     *SessionUDP       // oob data to get egress interface right
 	udpSession     *SessionUDP       // oob data to get egress interface right
 	remoteAddr     net.Addr          // address of the client
 	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
 // ServeMux is an DNS request multiplexer. It matches the
@@ -158,9 +162,9 @@ func (mux *ServeMux) HandleRemove(pattern string) {
 	if pattern == "" {
 	if pattern == "" {
 		panic("dns: invalid pattern " + pattern)
 		panic("dns: invalid pattern " + pattern)
 	}
 	}
-	// don't need a mutex here, because deleting is OK, even if the
-	// entry is note there.
+	mux.m.Lock()
 	delete(mux.z, Fqdn(pattern))
 	delete(mux.z, Fqdn(pattern))
+	mux.m.Unlock()
 }
 }
 
 
 // ServeDNS dispatches the request to the handler whose
 // ServeDNS dispatches the request to the handler whose
@@ -197,6 +201,43 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
 	DefaultServeMux.HandleFunc(pattern, handler)
 	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.
 // A Server defines parameters for running an DNS server.
 type Server struct {
 type Server struct {
 	// Address to listen on, ":dns" if empty.
 	// Address to listen on, ":dns" if empty.
@@ -223,8 +264,12 @@ type Server struct {
 	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
 	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
 	// the handler. It will specfically not check if the query has the QR bit not set.
 	// the handler. It will specfically not check if the query has the QR bit not set.
 	Unsafe bool
 	Unsafe bool
-	// If NotifyStartedFunc is set is is called, once the server has started listening.
+	// If NotifyStartedFunc is set it is called once the server has started listening.
 	NotifyStartedFunc func()
 	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.
 	// For graceful shutdown.
 	stopUDP chan bool
 	stopUDP chan bool
@@ -246,7 +291,6 @@ func (srv *Server) ListenAndServe() error {
 	}
 	}
 	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
 	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
 	srv.started = true
 	srv.started = true
-	srv.lock.Unlock()
 	addr := srv.Addr
 	addr := srv.Addr
 	if addr == "" {
 	if addr == "" {
 		addr = ":domain"
 		addr = ":domain"
@@ -265,6 +309,7 @@ func (srv *Server) ListenAndServe() error {
 			return e
 			return e
 		}
 		}
 		srv.Listener = l
 		srv.Listener = l
+		srv.lock.Unlock()
 		return srv.serveTCP(l)
 		return srv.serveTCP(l)
 	case "udp", "udp4", "udp6":
 	case "udp", "udp4", "udp6":
 		a, e := net.ResolveUDPAddr(srv.Net, addr)
 		a, e := net.ResolveUDPAddr(srv.Net, addr)
@@ -279,8 +324,10 @@ func (srv *Server) ListenAndServe() error {
 			return e
 			return e
 		}
 		}
 		srv.PacketConn = l
 		srv.PacketConn = l
+		srv.lock.Unlock()
 		return srv.serveUDP(l)
 		return srv.serveUDP(l)
 	}
 	}
+	srv.lock.Unlock()
 	return &Error{err: "bad network"}
 	return &Error{err: "bad network"}
 }
 }
 
 
@@ -294,20 +341,22 @@ func (srv *Server) ActivateAndServe() error {
 	}
 	}
 	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
 	srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
 	srv.started = true
 	srv.started = true
+	pConn := srv.PacketConn
+	l := srv.Listener
 	srv.lock.Unlock()
 	srv.lock.Unlock()
-	if srv.PacketConn != nil {
+	if pConn != nil {
 		if srv.UDPSize == 0 {
 		if srv.UDPSize == 0 {
 			srv.UDPSize = MinMsgSize
 			srv.UDPSize = MinMsgSize
 		}
 		}
-		if t, ok := srv.PacketConn.(*net.UDPConn); ok {
+		if t, ok := pConn.(*net.UDPConn); ok {
 			if e := setUDPSocketOptions(t); e != nil {
 			if e := setUDPSocketOptions(t); e != nil {
 				return e
 				return e
 			}
 			}
 			return srv.serveUDP(t)
 			return srv.serveUDP(t)
 		}
 		}
 	}
 	}
-	if srv.Listener != nil {
-		if t, ok := srv.Listener.(*net.TCPListener); ok {
+	if l != nil {
+		if t, ok := l.(*net.TCPListener); ok {
 			return srv.serveTCP(t)
 			return srv.serveTCP(t)
 		}
 		}
 	}
 	}
@@ -316,7 +365,7 @@ func (srv *Server) ActivateAndServe() error {
 
 
 // Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
 // 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
 // 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 and error
+// is taken down. If the Shutdown is taking longer than the reading timeout an error
 // is returned.
 // is returned.
 func (srv *Server) Shutdown() error {
 func (srv *Server) Shutdown() error {
 	srv.lock.Lock()
 	srv.lock.Lock()
@@ -325,7 +374,6 @@ func (srv *Server) Shutdown() error {
 		return &Error{err: "server not started"}
 		return &Error{err: "server not started"}
 	}
 	}
 	srv.started = false
 	srv.started = false
-	srv.lock.Unlock()
 	net, addr := srv.Net, srv.Addr
 	net, addr := srv.Net, srv.Addr
 	switch {
 	switch {
 	case srv.Listener != nil:
 	case srv.Listener != nil:
@@ -335,6 +383,7 @@ func (srv *Server) Shutdown() error {
 		a := srv.PacketConn.LocalAddr()
 		a := srv.PacketConn.LocalAddr()
 		net, addr = a.Network(), a.String()
 		net, addr = a.Network(), a.String()
 	}
 	}
+	srv.lock.Unlock()
 
 
 	fin := make(chan bool)
 	fin := make(chan bool)
 	switch net {
 	switch net {
@@ -382,6 +431,11 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
 		srv.NotifyStartedFunc()
 		srv.NotifyStartedFunc()
 	}
 	}
 
 
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
+
 	handler := srv.Handler
 	handler := srv.Handler
 	if handler == nil {
 	if handler == nil {
 		handler = DefaultServeMux
 		handler = DefaultServeMux
@@ -393,7 +447,7 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
 		if e != nil {
 		if e != nil {
 			continue
 			continue
 		}
 		}
-		m, e := srv.readTCP(rw, rtimeout)
+		m, e := reader.ReadTCP(rw, rtimeout)
 		select {
 		select {
 		case <-srv.stopTCP:
 		case <-srv.stopTCP:
 			return nil
 			return nil
@@ -405,7 +459,6 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
 		srv.wgTCP.Add(1)
 		srv.wgTCP.Add(1)
 		go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
 		go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
 	}
 	}
-	panic("dns: not reached")
 }
 }
 
 
 // serveUDP starts a UDP listener for the server.
 // serveUDP starts a UDP listener for the server.
@@ -417,6 +470,11 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 		srv.NotifyStartedFunc()
 		srv.NotifyStartedFunc()
 	}
 	}
 
 
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
+
 	handler := srv.Handler
 	handler := srv.Handler
 	if handler == nil {
 	if handler == nil {
 		handler = DefaultServeMux
 		handler = DefaultServeMux
@@ -424,7 +482,7 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 	rtimeout := srv.getReadTimeout()
 	rtimeout := srv.getReadTimeout()
 	// deadline is not used here
 	// deadline is not used here
 	for {
 	for {
-		m, s, e := srv.readUDP(l, rtimeout)
+		m, s, e := reader.ReadUDP(l, rtimeout)
 		select {
 		select {
 		case <-srv.stopUDP:
 		case <-srv.stopUDP:
 			return nil
 			return nil
@@ -436,13 +494,19 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 		srv.wgUDP.Add(1)
 		srv.wgUDP.Add(1)
 		go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
 		go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
 	}
 	}
-	panic("dns: not reached")
 }
 }
 
 
 // Serve a new connection.
 // Serve a new connection.
 func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t *net.TCPConn) {
 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}
 	w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
-	q := 0
+	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() {
 	defer func() {
 		if u != nil {
 		if u != nil {
 			srv.wgUDP.Done()
 			srv.wgUDP.Done()
@@ -451,6 +515,11 @@ func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *Ses
 			srv.wgTCP.Done()
 			srv.wgTCP.Done()
 		}
 		}
 	}()
 	}()
+
+	reader := Reader(&defaultReader{srv})
+	if srv.DecorateReader != nil {
+		reader = srv.DecorateReader(reader)
+	}
 Redo:
 Redo:
 	req := new(Msg)
 	req := new(Msg)
 	err := req.Unpack(m)
 	err := req.Unpack(m)
@@ -479,6 +548,12 @@ Redo:
 	h.ServeDNS(w, req) // Writes back to the client
 	h.ServeDNS(w, req) // Writes back to the client
 
 
 Exit:
 Exit:
+	// TODO(miek): make this number configurable?
+	if q > maxTCPQueries { // close socket after this many queries
+		w.Close()
+		return
+	}
+
 	if w.hijacked {
 	if w.hijacked {
 		return // client calls Close()
 		return // client calls Close()
 	}
 	}
@@ -490,14 +565,9 @@ Exit:
 	if srv.IdleTimeout != nil {
 	if srv.IdleTimeout != nil {
 		idleTimeout = srv.IdleTimeout()
 		idleTimeout = srv.IdleTimeout()
 	}
 	}
-	m, e := srv.readTCP(w.tcp, idleTimeout)
+	m, e := reader.ReadTCP(w.tcp, idleTimeout)
 	if e == nil {
 	if e == nil {
 		q++
 		q++
-		// TODO(miek): make this number configurable?
-		if q > 128 { // close socket after this many queries
-			w.Close()
-			return
-		}
 		goto Redo
 		goto Redo
 	}
 	}
 	w.Close()
 	w.Close()
@@ -562,7 +632,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
-			_, err = w.Write(data)
+			_, err = w.writer.Write(data)
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -570,7 +640,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	_, err = w.Write(data)
+	_, err = w.writer.Write(data)
 	return err
 	return err
 }
 }
 
 

+ 52 - 1
Godeps/_workspace/src/github.com/miekg/dns/server_test.go

@@ -20,7 +20,7 @@ func HelloServer(w ResponseWriter, req *Msg) {
 func HelloServerBadId(w ResponseWriter, req *Msg) {
 func HelloServerBadId(w ResponseWriter, req *Msg) {
 	m := new(Msg)
 	m := new(Msg)
 	m.SetReply(req)
 	m.SetReply(req)
-	m.Id += 1
+	m.Id++
 
 
 	m.Extra = make([]RR, 1)
 	m.Extra = make([]RR, 1)
 	m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
 	m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
@@ -397,3 +397,54 @@ func TestShutdownUDP(t *testing.T) {
 		t.Errorf("Could not shutdown test UDP server, %v", err)
 		t.Errorf("Could not shutdown test UDP server, %v", err)
 	}
 	}
 }
 }
+
+type ExampleFrameLengthWriter struct {
+	Writer
+}
+
+func (e *ExampleFrameLengthWriter) Write(m []byte) (int, error) {
+	fmt.Println("writing raw DNS message of length", len(m))
+	return e.Writer.Write(m)
+}
+
+func ExampleDecorateWriter() {
+	// instrument raw DNS message writing
+	wf := DecorateWriter(func(w Writer) Writer {
+		return &ExampleFrameLengthWriter{w}
+	})
+
+	// simple UDP server
+	pc, err := net.ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		fmt.Println(err.Error())
+		return
+	}
+	server := &Server{
+		PacketConn:     pc,
+		DecorateWriter: wf,
+	}
+
+	waitLock := sync.Mutex{}
+	waitLock.Lock()
+	server.NotifyStartedFunc = waitLock.Unlock
+	defer server.Shutdown()
+
+	go func() {
+		server.ActivateAndServe()
+		pc.Close()
+	}()
+
+	waitLock.Lock()
+
+	HandleFunc("miek.nl.", HelloServer)
+
+	c := new(Client)
+	m := new(Msg)
+	m.SetQuestion("miek.nl.", TypeTXT)
+	_, _, err = c.Exchange(m, pc.LocalAddr().String())
+	if err != nil {
+		fmt.Println("failed to exchange", err.Error())
+		return
+	}
+	// Output: writing raw DNS message of length 56
+}

+ 10 - 15
Godeps/_workspace/src/github.com/miekg/dns/sig0.go

@@ -13,7 +13,7 @@ import (
 // Sign signs a dns.Msg. It fills the signature with the appropriate data.
 // Sign signs a dns.Msg. It fills the signature with the appropriate data.
 // The SIG record should have the SignerName, KeyTag, Algorithm, Inception
 // The SIG record should have the SignerName, KeyTag, Algorithm, Inception
 // and Expiration set.
 // and Expiration set.
-func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
+func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
 	if k == nil {
 	if k == nil {
 		return nil, ErrPrivKey
 		return nil, ErrPrivKey
 	}
 	}
@@ -41,31 +41,26 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 	buf = buf[:off:cap(buf)]
 	buf = buf[:off:cap(buf)]
-	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:
+
+	hash, ok := AlgorithmToHash[rr.Algorithm]
+	if !ok {
 		return nil, ErrAlg
 		return nil, ErrAlg
 	}
 	}
+
 	hasher := hash.New()
 	hasher := hash.New()
 	// Write SIG rdata
 	// Write SIG rdata
 	hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
 	hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
 	// Write message
 	// Write message
 	hasher.Write(buf[:len(mbuf)])
 	hasher.Write(buf[:len(mbuf)])
-	hashed := hasher.Sum(nil)
 
 
-	sig, err := k.Sign(hashed, rr.Algorithm)
+	signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	rr.Signature = toBase64(sig)
+
+	rr.Signature = toBase64(signature)
+	sig := string(signature)
+
 	buf = append(buf, sig...)
 	buf = append(buf, sig...)
 	if len(buf) > int(^uint16(0)) {
 	if len(buf) > int(^uint16(0)) {
 		return nil, ErrBuf
 		return nil, ErrBuf

+ 4 - 3
Godeps/_workspace/src/github.com/miekg/dns/sig0_test.go

@@ -1,6 +1,7 @@
 package dns
 package dns
 
 
 import (
 import (
+	"crypto"
 	"testing"
 	"testing"
 	"time"
 	"time"
 )
 )
@@ -11,7 +12,7 @@ func TestSIG0(t *testing.T) {
 	}
 	}
 	m := new(Msg)
 	m := new(Msg)
 	m.SetQuestion("example.org.", TypeSOA)
 	m.SetQuestion("example.org.", TypeSOA)
-	for _, alg := range []uint8{DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
+	for _, alg := range []uint8{ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
 		algstr := AlgorithmToString[alg]
 		algstr := AlgorithmToString[alg]
 		keyrr := new(KEY)
 		keyrr := new(KEY)
 		keyrr.Hdr.Name = algstr + "."
 		keyrr.Hdr.Name = algstr + "."
@@ -40,7 +41,7 @@ func TestSIG0(t *testing.T) {
 		sigrr.Inception = now - 300
 		sigrr.Inception = now - 300
 		sigrr.KeyTag = keyrr.KeyTag()
 		sigrr.KeyTag = keyrr.KeyTag()
 		sigrr.SignerName = keyrr.Hdr.Name
 		sigrr.SignerName = keyrr.Hdr.Name
-		mb, err := sigrr.Sign(pk, m)
+		mb, err := sigrr.Sign(pk.(crypto.Signer), m)
 		if err != nil {
 		if err != nil {
 			t.Errorf("Failed to sign message using “%s”: %v", algstr, err)
 			t.Errorf("Failed to sign message using “%s”: %v", algstr, err)
 			continue
 			continue
@@ -79,7 +80,7 @@ func TestSIG0(t *testing.T) {
 		}
 		}
 		sigrr.Expiration = 2
 		sigrr.Expiration = 2
 		sigrr.Inception = 1
 		sigrr.Inception = 1
-		mb, _ = sigrr.Sign(pk, m)
+		mb, _ = sigrr.Sign(pk.(crypto.Signer), m)
 		if err := sigrr.Verify(keyrr, mb); err == nil {
 		if err := sigrr.Verify(keyrr, mb); err == nil {
 			t.Errorf("Verify succeeded on an expired message using “%s”", algstr)
 			t.Errorf("Verify succeeded on an expired message using “%s”", algstr)
 			continue
 			continue

+ 13 - 25
Godeps/_workspace/src/github.com/miekg/dns/types.go

@@ -46,7 +46,6 @@ const (
 	TypeX25        uint16 = 19
 	TypeX25        uint16 = 19
 	TypeISDN       uint16 = 20
 	TypeISDN       uint16 = 20
 	TypeRT         uint16 = 21
 	TypeRT         uint16 = 21
-	TypeNSAP       uint16 = 22
 	TypeNSAPPTR    uint16 = 23
 	TypeNSAPPTR    uint16 = 23
 	TypeSIG        uint16 = 24
 	TypeSIG        uint16 = 24
 	TypeKEY        uint16 = 25
 	TypeKEY        uint16 = 25
@@ -92,26 +91,24 @@ const (
 	TypeLP         uint16 = 107
 	TypeLP         uint16 = 107
 	TypeEUI48      uint16 = 108
 	TypeEUI48      uint16 = 108
 	TypeEUI64      uint16 = 109
 	TypeEUI64      uint16 = 109
+	TypeURI        uint16 = 256
+	TypeCAA        uint16 = 257
 
 
 	TypeTKEY uint16 = 249
 	TypeTKEY uint16 = 249
 	TypeTSIG uint16 = 250
 	TypeTSIG uint16 = 250
 
 
 	// valid Question.Qtype only
 	// valid Question.Qtype only
-
 	TypeIXFR  uint16 = 251
 	TypeIXFR  uint16 = 251
 	TypeAXFR  uint16 = 252
 	TypeAXFR  uint16 = 252
 	TypeMAILB uint16 = 253
 	TypeMAILB uint16 = 253
 	TypeMAILA uint16 = 254
 	TypeMAILA uint16 = 254
 	TypeANY   uint16 = 255
 	TypeANY   uint16 = 255
 
 
-	TypeURI      uint16 = 256
-	TypeCAA      uint16 = 257
 	TypeTA       uint16 = 32768
 	TypeTA       uint16 = 32768
 	TypeDLV      uint16 = 32769
 	TypeDLV      uint16 = 32769
 	TypeReserved uint16 = 65535
 	TypeReserved uint16 = 65535
 
 
 	// valid Question.Qclass
 	// valid Question.Qclass
-
 	ClassINET   = 1
 	ClassINET   = 1
 	ClassCSNET  = 2
 	ClassCSNET  = 2
 	ClassCHAOS  = 3
 	ClassCHAOS  = 3
@@ -119,8 +116,7 @@ const (
 	ClassNONE   = 254
 	ClassNONE   = 254
 	ClassANY    = 255
 	ClassANY    = 255
 
 
-	// Msg.rcode
-
+	// Message Response Codes.
 	RcodeSuccess        = 0
 	RcodeSuccess        = 0
 	RcodeFormatError    = 1
 	RcodeFormatError    = 1
 	RcodeServerFailure  = 2
 	RcodeServerFailure  = 2
@@ -141,8 +137,7 @@ const (
 	RcodeBadAlg         = 21
 	RcodeBadAlg         = 21
 	RcodeBadTrunc       = 22 // TSIG
 	RcodeBadTrunc       = 22 // TSIG
 
 
-	// Opcode, there is no 3
-
+	// Message Opcodes. There is no 3.
 	OpcodeQuery  = 0
 	OpcodeQuery  = 0
 	OpcodeIQuery = 1
 	OpcodeIQuery = 1
 	OpcodeStatus = 2
 	OpcodeStatus = 2
@@ -150,7 +145,7 @@ const (
 	OpcodeUpdate = 5
 	OpcodeUpdate = 5
 )
 )
 
 
-// The wire format for the DNS packet header.
+// Headers is the wire format for the DNS packet header.
 type Header struct {
 type Header struct {
 	Id                                 uint16
 	Id                                 uint16
 	Bits                               uint16
 	Bits                               uint16
@@ -179,7 +174,7 @@ const (
 	LOC_ALTITUDEBASE = 100000
 	LOC_ALTITUDEBASE = 100000
 )
 )
 
 
-// RFC 4398, Section 2.1
+// Different Certificate Types, see RFC 4398, Section 2.1
 const (
 const (
 	CertPKIX = 1 + iota
 	CertPKIX = 1 + iota
 	CertSPKI
 	CertSPKI
@@ -193,6 +188,8 @@ const (
 	CertOID = 254
 	CertOID = 254
 )
 )
 
 
+// CertTypeToString converts the Cert Type to its string representation.
+// See RFC 4398 and RFC 6944.
 var CertTypeToString = map[uint16]string{
 var CertTypeToString = map[uint16]string{
 	CertPKIX:    "PKIX",
 	CertPKIX:    "PKIX",
 	CertSPKI:    "SPKI",
 	CertSPKI:    "SPKI",
@@ -206,6 +203,7 @@ var CertTypeToString = map[uint16]string{
 	CertOID:     "OID",
 	CertOID:     "OID",
 }
 }
 
 
+// StringToCertType is the reverseof CertTypeToString.
 var StringToCertType = reverseInt16(CertTypeToString)
 var StringToCertType = reverseInt16(CertTypeToString)
 
 
 // Question holds a DNS question. There can be multiple questions in the
 // Question holds a DNS question. There can be multiple questions in the
@@ -229,6 +227,8 @@ func (q *Question) len() int {
 	return l + 4
 	return l + 4
 }
 }
 
 
+// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY
+// is named "*" there.
 type ANY struct {
 type ANY struct {
 	Hdr RR_Header
 	Hdr RR_Header
 	// Does not have any rdata
 	// Does not have any rdata
@@ -702,7 +702,7 @@ func (rr *NAPTR) len() int {
 		len(rr.Regexp) + 1 + len(rr.Replacement) + 1
 		len(rr.Regexp) + 1 + len(rr.Replacement) + 1
 }
 }
 
 
-// See RFC 4398.
+// The CERT resource record, see RFC 4398.
 type CERT struct {
 type CERT struct {
 	Hdr         RR_Header
 	Hdr         RR_Header
 	Type        uint16
 	Type        uint16
@@ -738,7 +738,7 @@ func (rr *CERT) len() int {
 		base64.StdEncoding.DecodedLen(len(rr.Certificate))
 		base64.StdEncoding.DecodedLen(len(rr.Certificate))
 }
 }
 
 
-// See RFC 2672.
+// The DNAME resource record, see RFC 2672.
 type DNAME struct {
 type DNAME struct {
 	Hdr    RR_Header
 	Hdr    RR_Header
 	Target string `dns:"domain-name"`
 	Target string `dns:"domain-name"`
@@ -850,7 +850,6 @@ func cmToM(m, e uint8) string {
 	return s
 	return s
 }
 }
 
 
-// String returns a string version of a LOC
 func (rr *LOC) String() string {
 func (rr *LOC) String() string {
 	s := rr.Hdr.String()
 	s := rr.Hdr.String()
 
 
@@ -1180,16 +1179,6 @@ func (rr *RKEY) String() string {
 		" " + rr.PublicKey
 		" " + rr.PublicKey
 }
 }
 
 
-type NSAP struct {
-	Hdr  RR_Header
-	Nsap string
-}
-
-func (rr *NSAP) Header() *RR_Header { return &rr.Hdr }
-func (rr *NSAP) copy() RR           { return &NSAP{*rr.Hdr.copyHeader(), rr.Nsap} }
-func (rr *NSAP) String() string     { return rr.Hdr.String() + "0x" + rr.Nsap }
-func (rr *NSAP) len() int           { return rr.Hdr.len() + 1 + len(rr.Nsap) + 1 }
-
 type NSAPPTR struct {
 type NSAPPTR struct {
 	Hdr RR_Header
 	Hdr RR_Header
 	Ptr string `dns:"domain-name"`
 	Ptr string `dns:"domain-name"`
@@ -1721,7 +1710,6 @@ var typeToRR = map[uint16]func() RR{
 	TypeNINFO:      func() RR { return new(NINFO) },
 	TypeNINFO:      func() RR { return new(NINFO) },
 	TypeNIMLOC:     func() RR { return new(NIMLOC) },
 	TypeNIMLOC:     func() RR { return new(NIMLOC) },
 	TypeNS:         func() RR { return new(NS) },
 	TypeNS:         func() RR { return new(NS) },
-	TypeNSAP:       func() RR { return new(NSAP) },
 	TypeNSAPPTR:    func() RR { return new(NSAPPTR) },
 	TypeNSAPPTR:    func() RR { return new(NSAPPTR) },
 	TypeNSEC3:      func() RR { return new(NSEC3) },
 	TypeNSEC3:      func() RR { return new(NSEC3) },
 	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
 	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },

+ 3 - 0
Godeps/_workspace/src/github.com/miekg/dns/udp.go

@@ -7,11 +7,14 @@ import (
 	"syscall"
 	"syscall"
 )
 )
 
 
+// SessionUDP holds the remote address and the associated
+// out-of-band data.
 type SessionUDP struct {
 type SessionUDP struct {
 	raddr   *net.UDPAddr
 	raddr   *net.UDPAddr
 	context []byte
 	context []byte
 }
 }
 
 
+// RemoteAddr returns the remote network address.
 func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
 func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
 
 
 // setUDPSocketOptions sets the UDP socket options.
 // setUDPSocketOptions sets the UDP socket options.

+ 0 - 1
Godeps/_workspace/src/github.com/miekg/dns/xfr.go

@@ -91,7 +91,6 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
 			c <- &Envelope{in.Answer, nil}
 			c <- &Envelope{in.Answer, nil}
 		}
 		}
 	}
 	}
-	panic("dns: not reached")
 }
 }
 
 
 func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
 func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {

+ 72 - 3
Godeps/_workspace/src/github.com/miekg/dns/xfr_test.go

@@ -1,3 +1,5 @@
+// +build net
+
 package dns
 package dns
 
 
 import (
 import (
@@ -16,7 +18,8 @@ func getIP(s string) string {
 
 
 // flaky, need to setup local server and test from
 // flaky, need to setup local server and test from
 // that.
 // that.
-func testClientAXFR(t *testing.T) {
+func TestAXFR_Miek(t *testing.T) {
+	// This test runs against a server maintained by Miek
 	if testing.Short() {
 	if testing.Short() {
 		return
 		return
 	}
 	}
@@ -43,7 +46,8 @@ func testClientAXFR(t *testing.T) {
 }
 }
 
 
 // fails.
 // fails.
-func testClientAXFRMultipleEnvelopes(t *testing.T) {
+func TestAXFR_NLNL_MultipleEnvelopes(t *testing.T) {
+	// This test runs against a server maintained by NLnet Labs
 	if testing.Short() {
 	if testing.Short() {
 		return
 		return
 	}
 	}
@@ -65,7 +69,8 @@ func testClientAXFRMultipleEnvelopes(t *testing.T) {
 	}
 	}
 }
 }
 
 
-func testClientTsigAXFR(t *testing.T) {
+func TestAXFR_Miek_Tsig(t *testing.T) {
+	// This test runs against a server maintained by Miek
 	if testing.Short() {
 	if testing.Short() {
 		return
 		return
 	}
 	}
@@ -90,3 +95,67 @@ func testClientTsigAXFR(t *testing.T) {
 		}
 		}
 	}
 	}
 }
 }
+
+func TestAXFR_SIDN_NSD3_NONE(t *testing.T)   { testAXFRSIDN(t, "nsd", "") }
+func TestAXFR_SIDN_NSD3_MD5(t *testing.T)    { testAXFRSIDN(t, "nsd", HmacMD5) }
+func TestAXFR_SIDN_NSD3_SHA1(t *testing.T)   { testAXFRSIDN(t, "nsd", HmacSHA1) }
+func TestAXFR_SIDN_NSD3_SHA256(t *testing.T) { testAXFRSIDN(t, "nsd", HmacSHA256) }
+
+func TestAXFR_SIDN_NSD4_NONE(t *testing.T)   { testAXFRSIDN(t, "nsd4", "") }
+func TestAXFR_SIDN_NSD4_MD5(t *testing.T)    { testAXFRSIDN(t, "nsd4", HmacMD5) }
+func TestAXFR_SIDN_NSD4_SHA1(t *testing.T)   { testAXFRSIDN(t, "nsd4", HmacSHA1) }
+func TestAXFR_SIDN_NSD4_SHA256(t *testing.T) { testAXFRSIDN(t, "nsd4", HmacSHA256) }
+
+func TestAXFR_SIDN_BIND9_NONE(t *testing.T)   { testAXFRSIDN(t, "bind9", "") }
+func TestAXFR_SIDN_BIND9_MD5(t *testing.T)    { testAXFRSIDN(t, "bind9", HmacMD5) }
+func TestAXFR_SIDN_BIND9_SHA1(t *testing.T)   { testAXFRSIDN(t, "bind9", HmacSHA1) }
+func TestAXFR_SIDN_BIND9_SHA256(t *testing.T) { testAXFRSIDN(t, "bind9", HmacSHA256) }
+
+func TestAXFR_SIDN_KNOT_NONE(t *testing.T)   { testAXFRSIDN(t, "knot", "") }
+func TestAXFR_SIDN_KNOT_MD5(t *testing.T)    { testAXFRSIDN(t, "knot", HmacMD5) }
+func TestAXFR_SIDN_KNOT_SHA1(t *testing.T)   { testAXFRSIDN(t, "knot", HmacSHA1) }
+func TestAXFR_SIDN_KNOT_SHA256(t *testing.T) { testAXFRSIDN(t, "knot", HmacSHA256) }
+
+func TestAXFR_SIDN_POWERDNS_NONE(t *testing.T)   { testAXFRSIDN(t, "powerdns", "") }
+func TestAXFR_SIDN_POWERDNS_MD5(t *testing.T)    { testAXFRSIDN(t, "powerdns", HmacMD5) }
+func TestAXFR_SIDN_POWERDNS_SHA1(t *testing.T)   { testAXFRSIDN(t, "powerdns", HmacSHA1) }
+func TestAXFR_SIDN_POWERDNS_SHA256(t *testing.T) { testAXFRSIDN(t, "powerdns", HmacSHA256) }
+
+func TestAXFR_SIDN_YADIFA_NONE(t *testing.T)   { testAXFRSIDN(t, "yadifa", "") }
+func TestAXFR_SIDN_YADIFA_MD5(t *testing.T)    { testAXFRSIDN(t, "yadifa", HmacMD5) }
+func TestAXFR_SIDN_YADIFA_SHA1(t *testing.T)   { testAXFRSIDN(t, "yadifa", HmacSHA1) }
+func TestAXFR_SIDN_YADIFA_SHA256(t *testing.T) { testAXFRSIDN(t, "yadifa", HmacSHA256) }
+
+func testAXFRSIDN(t *testing.T, host, alg string) {
+	// This tests run against a server maintained by SIDN labs, see:
+	// https://workbench.sidnlabs.nl/
+	if testing.Short() {
+		return
+	}
+	x := new(Transfer)
+	x.TsigSecret = map[string]string{
+		"wb_md5.":          "Wu/utSasZUkoeCNku152Zw==",
+		"wb_sha1_longkey.": "uhMpEhPq/RAD9Bt4mqhfmi+7ZdKmjLQb/lcrqYPXR4s/nnbsqw==",
+		"wb_sha256.":       "npfrIJjt/MJOjGJoBNZtsjftKMhkSpIYMv2RzRZt1f8=",
+	}
+	keyname := map[string]string{
+		HmacMD5:    "wb_md5.",
+		HmacSHA1:   "wb_sha1_longkey.",
+		HmacSHA256: "wb_sha256.",
+	}[alg]
+
+	m := new(Msg)
+	m.SetAxfr("types.wb.sidnlabs.nl.")
+	if keyname != "" {
+		m.SetTsig(keyname, alg, 300, time.Now().Unix())
+	}
+	c, err := x.In(m, host+".sidnlabs.nl:53")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for e := range c {
+		if e.Error != nil {
+			t.Fatal(e.Error)
+		}
+	}
+}

+ 2 - 2
Godeps/_workspace/src/github.com/miekg/dns/zgenerate.go

@@ -141,11 +141,11 @@ func modToPrintf(s string) (string, int, string) {
 		return "", 0, "bad base in $GENERATE"
 		return "", 0, "bad base in $GENERATE"
 	}
 	}
 	offset, err := strconv.Atoi(xs[0])
 	offset, err := strconv.Atoi(xs[0])
-	if err != nil {
+	if err != nil || offset > 255 {
 		return "", 0, "bad offset in $GENERATE"
 		return "", 0, "bad offset in $GENERATE"
 	}
 	}
 	width, err := strconv.Atoi(xs[1])
 	width, err := strconv.Atoi(xs[1])
-	if err != nil {
+	if err != nil || width > 255 {
 		return "", offset, "bad width in $GENERATE"
 		return "", offset, "bad width in $GENERATE"
 	}
 	}
 	switch {
 	switch {

+ 14 - 6
Godeps/_workspace/src/github.com/miekg/dns/zscan.go

@@ -131,11 +131,11 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
 	return r.RR, nil
 	return r.RR, nil
 }
 }
 
 
-// ParseZone reads a RFC 1035 style one from r. It returns *Tokens on the
+// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
 // returned channel, which consist out the parsed RR, a potential comment or an error.
 // returned channel, 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
 // 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
 // in error reporting. The string origin is used as the initial origin, as
-// if the file would start with: $ORIGIN origin  .
+// if the file would start with: $ORIGIN origin .
 // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
 // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
 // The channel t is closed by ParseZone when the end of r is reached.
 // The channel t is closed by ParseZone when the end of r is reached.
 //
 //
@@ -152,7 +152,7 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
 //
 //
 //	foo. IN A 10.0.0.1 ; this is a comment
 //	foo. IN A 10.0.0.1 ; this is a comment
 //
 //
-// The text "; this is comment" is returned in Token.Comment . Comments inside the
+// The text "; this is comment" is returned in Token.Comment. Comments inside the
 // RR are discarded. Comments on a line by themselves are discarded too.
 // RR are discarded. Comments on a line by themselves are discarded too.
 func ParseZone(r io.Reader, origin, file string) chan *Token {
 func ParseZone(r io.Reader, origin, file string) chan *Token {
 	return parseZoneHelper(r, origin, file, 10000)
 	return parseZoneHelper(r, origin, file, 10000)
@@ -281,7 +281,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
 			case zBlank:
 			case zBlank:
 				l := <-c
 				l := <-c
 				if l.value == zString {
 				if l.value == zString {
-					if _, ok := IsDomainName(l.token); !ok {
+					if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
 						t <- &Token{Error: &ParseError{f, "bad origin name", l}}
 						t <- &Token{Error: &ParseError{f, "bad origin name", l}}
 						return
 						return
 					}
 					}
@@ -806,7 +806,11 @@ func zlexer(s *scan, c chan lex) {
 
 
 // Extract the class number from CLASSxx
 // Extract the class number from CLASSxx
 func classToInt(token string) (uint16, bool) {
 func classToInt(token string) (uint16, bool) {
-	class, ok := strconv.Atoi(token[5:])
+	offset := 5
+	if len(token) < offset+1 {
+		return 0, false
+	}
+	class, ok := strconv.Atoi(token[offset:])
 	if ok != nil || class > maxUint16 {
 	if ok != nil || class > maxUint16 {
 		return 0, false
 		return 0, false
 	}
 	}
@@ -815,7 +819,11 @@ func classToInt(token string) (uint16, bool) {
 
 
 // Extract the rr number from TYPExxx
 // Extract the rr number from TYPExxx
 func typeToInt(token string) (uint16, bool) {
 func typeToInt(token string) (uint16, bool) {
-	typ, ok := strconv.Atoi(token[4:])
+	offset := 4
+	if len(token) < offset+1 {
+		return 0, false
+	}
+	typ, ok := strconv.Atoi(token[offset:])
 	if ok != nil || typ > maxUint16 {
 	if ok != nil || typ > maxUint16 {
 		return 0, false
 		return 0, false
 	}
 	}

File diff suppressed because it is too large
+ 136 - 140
Godeps/_workspace/src/github.com/miekg/dns/zscan_rr.go


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