gofmt -w
This commit is contained in:
parent
b56e9b4e04
commit
da0603089a
|
@ -108,7 +108,7 @@ func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter,
|
|||
func (mux *QueryMux) QueryDNS(w RequestWriter, r *Msg) {
|
||||
h := mux.match(r.Question[0].Name)
|
||||
if h == nil {
|
||||
panic("dns: no handler found for " + r.Question[0].Name)
|
||||
panic("dns: no handler found for " + r.Question[0].Name)
|
||||
}
|
||||
h.QueryDNS(w, r)
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ type Client struct {
|
|||
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
|
||||
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>
|
||||
// LocalAddr string // Local address to use
|
||||
// LocalAddr string // Local address to use
|
||||
}
|
||||
|
||||
// Create a new client, with some defaults.
|
||||
|
@ -144,7 +144,7 @@ func (q *Query) Query() os.Error {
|
|||
if handler == nil {
|
||||
handler = DefaultQueryMux
|
||||
}
|
||||
//forever:
|
||||
//forever:
|
||||
for {
|
||||
select {
|
||||
case in := <-q.ChannelQuery:
|
||||
|
@ -210,7 +210,7 @@ func (c *Client) Exchange(m *Msg, a string) *Msg {
|
|||
return nil
|
||||
}
|
||||
p = p[:n]
|
||||
r := new(Msg)
|
||||
r := new(Msg)
|
||||
if ok := r.Unpack(p); !ok {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package dns
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestClientSync(t *testing.T) {
|
||||
|
@ -80,19 +80,19 @@ func TestClientTsigAXFR(t *testing.T) {
|
|||
m := new(Msg)
|
||||
m.SetAxfr("miek.nl")
|
||||
|
||||
m.SetTsig("axfr", HmacMD5, 300, uint64(time.Seconds()))
|
||||
secrets := make(map[string]string)
|
||||
secrets["axfr"] = "so6ZGir4GPAqINNh9U5c3A=="
|
||||
m.SetTsig("axfr", HmacMD5, 300, uint64(time.Seconds()))
|
||||
secrets := make(map[string]string)
|
||||
secrets["axfr"] = "so6ZGir4GPAqINNh9U5c3A=="
|
||||
|
||||
c := NewClient()
|
||||
c.Net = "tcp"
|
||||
c.TsigSecret = secrets
|
||||
c := NewClient()
|
||||
c.Net = "tcp"
|
||||
c.TsigSecret = secrets
|
||||
|
||||
c.XfrReceive(m, "85.223.71.124:53")
|
||||
/*
|
||||
if err != nil {
|
||||
t.Log("%s\n", err.String())
|
||||
t.Fail()
|
||||
}
|
||||
*/
|
||||
c.XfrReceive(m, "85.223.71.124:53")
|
||||
/*
|
||||
if err != nil {
|
||||
t.Log("%s\n", err.String())
|
||||
t.Fail()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func ClientConfigFromFile(conf string) (*ClientConfig, os.Error) {
|
|||
b := bufio.NewReader(file)
|
||||
c.Servers = make([]string, 3)[0:0] // small, but the standard limit
|
||||
c.Search = make([]string, 0)
|
||||
c.Port = "53"
|
||||
c.Port = "53"
|
||||
c.Ndots = 1
|
||||
c.Timeout = 5
|
||||
c.Attempts = 2
|
||||
|
|
192
dnssec.go
192
dnssec.go
|
@ -6,8 +6,8 @@ import (
|
|||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
|
@ -22,25 +22,25 @@ import (
|
|||
|
||||
// DNSSEC encryption algorithm codes.
|
||||
const (
|
||||
RSAMD5 = 1
|
||||
DH = 2
|
||||
DSA = 3
|
||||
ECC = 4
|
||||
RSASHA1 = 5
|
||||
RSASHA256 = 8
|
||||
RSASHA512 = 10
|
||||
ECCGOST = 12
|
||||
ECDSAP256SHA256 = 13
|
||||
ECDSAP384SHA384 = 14
|
||||
RSAMD5 = 1
|
||||
DH = 2
|
||||
DSA = 3
|
||||
ECC = 4
|
||||
RSASHA1 = 5
|
||||
RSASHA256 = 8
|
||||
RSASHA512 = 10
|
||||
ECCGOST = 12
|
||||
ECDSAP256SHA256 = 13
|
||||
ECDSAP384SHA384 = 14
|
||||
)
|
||||
|
||||
// DNSSEC hashing algorithm codes.
|
||||
const (
|
||||
_ = iota
|
||||
SHA1 // RFC 4034
|
||||
SHA256 // RFC 4509
|
||||
GOST94 // RFC 5933
|
||||
SHA384 // Experimental
|
||||
_ = iota
|
||||
SHA1 // RFC 4034
|
||||
SHA256 // RFC 4509
|
||||
GOST94 // RFC 5933
|
||||
SHA384 // Experimental
|
||||
)
|
||||
|
||||
// DNSKEY flag values.
|
||||
|
@ -151,8 +151,8 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
|
|||
s := sha256.New()
|
||||
io.WriteString(s, string(digest))
|
||||
ds.Digest = hex.EncodeToString(s.Sum())
|
||||
case SHA384:
|
||||
s := sha512.New384()
|
||||
case SHA384:
|
||||
s := sha512.New384()
|
||||
io.WriteString(s, string(digest))
|
||||
ds.Digest = hex.EncodeToString(s.Sum())
|
||||
case GOST94:
|
||||
|
@ -213,49 +213,49 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
|||
}
|
||||
signdata = append(signdata, wire...)
|
||||
|
||||
var sighash []byte
|
||||
var h hash.Hash
|
||||
var ch crypto.Hash // Only need for RSA
|
||||
switch s.Algorithm {
|
||||
case RSAMD5:
|
||||
h = md5.New()
|
||||
ch = crypto.MD5
|
||||
case RSASHA1:
|
||||
h = sha1.New()
|
||||
ch = crypto.SHA1
|
||||
case RSASHA256, ECDSAP256SHA256:
|
||||
h = sha256.New()
|
||||
ch = crypto.SHA256
|
||||
case ECDSAP384SHA384:
|
||||
h = sha512.New384()
|
||||
case RSASHA512:
|
||||
h = sha512.New()
|
||||
ch = crypto.SHA512
|
||||
default:
|
||||
return false // Illegal alg
|
||||
}
|
||||
io.WriteString(h, string(signdata))
|
||||
sighash = h.Sum()
|
||||
var sighash []byte
|
||||
var h hash.Hash
|
||||
var ch crypto.Hash // Only need for RSA
|
||||
switch s.Algorithm {
|
||||
case RSAMD5:
|
||||
h = md5.New()
|
||||
ch = crypto.MD5
|
||||
case RSASHA1:
|
||||
h = sha1.New()
|
||||
ch = crypto.SHA1
|
||||
case RSASHA256, ECDSAP256SHA256:
|
||||
h = sha256.New()
|
||||
ch = crypto.SHA256
|
||||
case ECDSAP384SHA384:
|
||||
h = sha512.New384()
|
||||
case RSASHA512:
|
||||
h = sha512.New()
|
||||
ch = crypto.SHA512
|
||||
default:
|
||||
return false // Illegal alg
|
||||
}
|
||||
io.WriteString(h, string(signdata))
|
||||
sighash = h.Sum()
|
||||
|
||||
switch p := k.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
signature, err := rsa.SignPKCS1v15(rand.Reader, p, ch, sighash)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
s.Signature = unpackBase64(signature)
|
||||
case *ecdsa.PrivateKey:
|
||||
r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
signature := r1.Bytes()
|
||||
signature = append(signature, s1.Bytes()...)
|
||||
s.Signature =unpackBase64(signature)
|
||||
default:
|
||||
// Not given the correct key
|
||||
return false
|
||||
}
|
||||
switch p := k.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
signature, err := rsa.SignPKCS1v15(rand.Reader, p, ch, sighash)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
s.Signature = unpackBase64(signature)
|
||||
case *ecdsa.PrivateKey:
|
||||
r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
signature := r1.Bytes()
|
||||
signature = append(signature, s1.Bytes()...)
|
||||
s.Signature = unpackBase64(signature)
|
||||
default:
|
||||
// Not given the correct key
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -394,23 +394,23 @@ func (k *RR_DNSKEY) pubKeyRSA() *rsa.PublicKey {
|
|||
|
||||
// Extract the Curve public key from the Key record
|
||||
func (k *RR_DNSKEY) pubKeyCurve() *ecdsa.PublicKey {
|
||||
keybuf, err := packBase64([]byte(k.PublicKey))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var c *elliptic.Curve
|
||||
switch k.Algorithm {
|
||||
case ECDSAP256SHA256:
|
||||
c = elliptic.P256()
|
||||
case ECDSAP384SHA384:
|
||||
c = elliptic.P384()
|
||||
}
|
||||
x, y := c.Unmarshal(keybuf)
|
||||
pubkey := new(ecdsa.PublicKey)
|
||||
pubkey.X = x
|
||||
pubkey.Y = y
|
||||
pubkey.Curve = c
|
||||
return pubkey
|
||||
keybuf, err := packBase64([]byte(k.PublicKey))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var c *elliptic.Curve
|
||||
switch k.Algorithm {
|
||||
case ECDSAP256SHA256:
|
||||
c = elliptic.P256()
|
||||
case ECDSAP384SHA384:
|
||||
c = elliptic.P384()
|
||||
}
|
||||
x, y := c.Unmarshal(keybuf)
|
||||
pubkey := new(ecdsa.PublicKey)
|
||||
pubkey.X = x
|
||||
pubkey.Y = y
|
||||
pubkey.Curve = c
|
||||
return pubkey
|
||||
}
|
||||
|
||||
// Set the public key (the value E and N)
|
||||
|
@ -426,12 +426,12 @@ func (k *RR_DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
|
|||
|
||||
// Set the public key for Elliptic Curves
|
||||
func (k *RR_DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool {
|
||||
if _X == nil || _Y == nil {
|
||||
return false
|
||||
}
|
||||
buf := curveToBuf(_X, _Y)
|
||||
k.PublicKey = unpackBase64(buf)
|
||||
return true
|
||||
if _X == nil || _Y == nil {
|
||||
return false
|
||||
}
|
||||
buf := curveToBuf(_X, _Y)
|
||||
k.PublicKey = unpackBase64(buf)
|
||||
return true
|
||||
}
|
||||
|
||||
// Set the public key (the values E and N) for RSA
|
||||
|
@ -455,9 +455,9 @@ func exponentToBuf(_E int) []byte {
|
|||
// Set the public key for X and Y for Curve
|
||||
// Experimental
|
||||
func curveToBuf(_X, _Y *big.Int) []byte {
|
||||
buf := _X.Bytes()
|
||||
buf = append(buf, _Y.Bytes()...)
|
||||
return buf
|
||||
buf := _X.Bytes()
|
||||
buf = append(buf, _Y.Bytes()...)
|
||||
return buf
|
||||
}
|
||||
|
||||
// return a saw signature data
|
||||
|
@ -500,13 +500,13 @@ func rawSignatureData(rrset RRset, s *RR_RRSIG) (buf []byte) {
|
|||
|
||||
// Map for algorithm names.
|
||||
var alg_str = map[uint8]string{
|
||||
RSAMD5: "RSAMD5",
|
||||
DH: "DH",
|
||||
DSA: "DSA",
|
||||
RSASHA1: "RSASHA1",
|
||||
RSASHA256: "RSASHA256",
|
||||
RSASHA512: "RSASHA512",
|
||||
ECCGOST: "ECC-GOST",
|
||||
ECDSAP256SHA256: "ECDSAP256SHA256",
|
||||
ECDSAP384SHA384: "ECDSAP384SHA384",
|
||||
RSAMD5: "RSAMD5",
|
||||
DH: "DH",
|
||||
DSA: "DSA",
|
||||
RSASHA1: "RSASHA1",
|
||||
RSASHA256: "RSASHA256",
|
||||
RSASHA512: "RSASHA512",
|
||||
ECCGOST: "ECC-GOST",
|
||||
ECDSAP256SHA256: "ECDSAP256SHA256",
|
||||
ECDSAP384SHA384: "ECDSAP384SHA384",
|
||||
}
|
||||
|
|
|
@ -119,10 +119,10 @@ func TestSignVerify(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKeyGen(t *testing.T) {
|
||||
algs := []uint8{RSASHA256, ECDSAP256SHA256}
|
||||
bits := []int{1024, 256}
|
||||
algs := []uint8{RSASHA256, ECDSAP256SHA256}
|
||||
bits := []int{1024, 256}
|
||||
|
||||
i := 0
|
||||
i := 0
|
||||
key := new(RR_DNSKEY)
|
||||
key.Hdr.Name = "keygen.miek.nl."
|
||||
key.Hdr.Rrtype = TypeDNSKEY
|
||||
|
@ -130,13 +130,13 @@ func TestKeyGen(t *testing.T) {
|
|||
key.Hdr.Ttl = 3600
|
||||
key.Flags = 256
|
||||
key.Protocol = 3
|
||||
for _, v := range algs {
|
||||
key.Algorithm = v
|
||||
key.Generate(bits[i])
|
||||
i++
|
||||
t.Logf("%s\n", key)
|
||||
}
|
||||
//Really hard to figure out what to check here... Parse it back to a proper key?
|
||||
for _, v := range algs {
|
||||
key.Algorithm = v
|
||||
key.Generate(bits[i])
|
||||
i++
|
||||
t.Logf("%s\n", key)
|
||||
}
|
||||
//Really hard to figure out what to check here... Parse it back to a proper key?
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
200
keygen.go
200
keygen.go
|
@ -2,12 +2,12 @@ package dns
|
|||
|
||||
import (
|
||||
"os"
|
||||
"io"
|
||||
"io"
|
||||
"big"
|
||||
"strconv"
|
||||
"crypto/rsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
|
@ -31,14 +31,14 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
|
|||
if bits < 1024 || bits > 4096 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
case ECDSAP256SHA256:
|
||||
if bits != 256 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
case ECDSAP384SHA384:
|
||||
if bits != 384 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
case ECDSAP256SHA256:
|
||||
if bits != 256 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
case ECDSAP384SHA384:
|
||||
if bits != 384 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
}
|
||||
|
||||
switch r.Algorithm {
|
||||
|
@ -47,22 +47,22 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
|
||||
r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
|
||||
return priv, nil
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
var c *elliptic.Curve
|
||||
switch r.Algorithm {
|
||||
case ECDSAP256SHA256:
|
||||
c = elliptic.P256()
|
||||
case ECDSAP384SHA384:
|
||||
c = elliptic.P384()
|
||||
}
|
||||
priv, err := ecdsa.GenerateKey(c, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y)
|
||||
return priv, nil
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
var c *elliptic.Curve
|
||||
switch r.Algorithm {
|
||||
case ECDSAP256SHA256:
|
||||
c = elliptic.P256()
|
||||
case ECDSAP384SHA384:
|
||||
c = elliptic.P384()
|
||||
}
|
||||
priv, err := ecdsa.GenerateKey(c, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y)
|
||||
return priv, nil
|
||||
default:
|
||||
return nil, ErrAlg
|
||||
}
|
||||
|
@ -106,81 +106,81 @@ func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
|
|||
"Exponent1: " + exponent1 + "\n" +
|
||||
"Exponent2: " + exponent2 + "\n" +
|
||||
"Coefficient: " + coefficient + "\n"
|
||||
case *ecdsa.PrivateKey:
|
||||
//
|
||||
case *ecdsa.PrivateKey:
|
||||
//
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (k *RR_DNSKEY) Read(q io.Reader) os.Error {
|
||||
p := NewParser(q)
|
||||
r := p.RR()
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
if _, ok := r.(*RR_DNSKEY); !ok {
|
||||
panic("did not read a DNSKEY")
|
||||
}
|
||||
k.Hdr = r.(*RR_DNSKEY).Hdr
|
||||
k.Flags = r.(*RR_DNSKEY).Flags
|
||||
k.Protocol = r.(*RR_DNSKEY).Protocol
|
||||
k.Algorithm = r.(*RR_DNSKEY).Algorithm
|
||||
k.PublicKey = r.(*RR_DNSKEY).PublicKey
|
||||
return nil
|
||||
p := NewParser(q)
|
||||
r := p.RR()
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
if _, ok := r.(*RR_DNSKEY); !ok {
|
||||
panic("did not read a DNSKEY")
|
||||
}
|
||||
k.Hdr = r.(*RR_DNSKEY).Hdr
|
||||
k.Flags = r.(*RR_DNSKEY).Flags
|
||||
k.Protocol = r.(*RR_DNSKEY).Protocol
|
||||
k.Algorithm = r.(*RR_DNSKEY).Algorithm
|
||||
k.PublicKey = r.(*RR_DNSKEY).PublicKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) {
|
||||
p := NewParser(q)
|
||||
kv, _ := p.PrivateKey()
|
||||
if _, ok := kv["private-key-format"]; !ok {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
if kv["private-key-format"] != "v1.2" && kv["private-key-format"] != "v1.3" {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
switch kv["algorithm"] {
|
||||
case "RSAMD5", "RSASHA1", "RSASHA256", "RSASHA512":
|
||||
return k.readPrivateKeyRSA(kv)
|
||||
case "ECDSAP256SHA256", "ECDSAP384SHA384":
|
||||
return k.readPrivateKeyECDSA(kv)
|
||||
}
|
||||
p := NewParser(q)
|
||||
kv, _ := p.PrivateKey()
|
||||
if _, ok := kv["private-key-format"]; !ok {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
if kv["private-key-format"] != "v1.2" && kv["private-key-format"] != "v1.3" {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
switch kv["algorithm"] {
|
||||
case "RSAMD5", "RSASHA1", "RSASHA256", "RSASHA512":
|
||||
return k.readPrivateKeyRSA(kv)
|
||||
case "ECDSAP256SHA256", "ECDSAP384SHA384":
|
||||
return k.readPrivateKeyECDSA(kv)
|
||||
}
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
|
||||
// Read a private key (file) string and create a public key. Return the private key.
|
||||
func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Error) {
|
||||
p := new(rsa.PrivateKey)
|
||||
p.Primes = []*big.Int{nil,nil}
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
|
||||
v1, err := packBase64([]byte(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch k {
|
||||
case "modulus":
|
||||
p.PublicKey.N = big.NewInt(0)
|
||||
p.PublicKey.N.SetBytes(v1)
|
||||
case "publicexponent":
|
||||
i := big.NewInt(0)
|
||||
i.SetBytes(v1)
|
||||
p.PublicKey.E = int(i.Int64()) // int64 should be large enough
|
||||
case "privateexponent":
|
||||
p.D = big.NewInt(0)
|
||||
p.D.SetBytes(v1)
|
||||
case "prime1":
|
||||
p.Primes[0] = big.NewInt(0)
|
||||
p.Primes[0].SetBytes(v1)
|
||||
case "prime2":
|
||||
p.Primes[1] = big.NewInt(0)
|
||||
p.Primes[1].SetBytes(v1)
|
||||
}
|
||||
case "exponent1", "exponent2", "coefficient":
|
||||
// not used in Go (yet)
|
||||
case "created", "publish", "activate":
|
||||
// not used in Go (yet)
|
||||
}
|
||||
p.Primes = []*big.Int{nil, nil}
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
|
||||
v1, err := packBase64([]byte(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch k {
|
||||
case "modulus":
|
||||
p.PublicKey.N = big.NewInt(0)
|
||||
p.PublicKey.N.SetBytes(v1)
|
||||
case "publicexponent":
|
||||
i := big.NewInt(0)
|
||||
i.SetBytes(v1)
|
||||
p.PublicKey.E = int(i.Int64()) // int64 should be large enough
|
||||
case "privateexponent":
|
||||
p.D = big.NewInt(0)
|
||||
p.D.SetBytes(v1)
|
||||
case "prime1":
|
||||
p.Primes[0] = big.NewInt(0)
|
||||
p.Primes[0].SetBytes(v1)
|
||||
case "prime2":
|
||||
p.Primes[1] = big.NewInt(0)
|
||||
p.Primes[1].SetBytes(v1)
|
||||
}
|
||||
case "exponent1", "exponent2", "coefficient":
|
||||
// not used in Go (yet)
|
||||
case "created", "publish", "activate":
|
||||
// not used in Go (yet)
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
@ -188,18 +188,18 @@ func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Erro
|
|||
func (k *RR_DNSKEY) readPrivateKeyECDSA(kv map[string]string) (PrivateKey, os.Error) {
|
||||
p := new(ecdsa.PrivateKey)
|
||||
p.D = big.NewInt(0)
|
||||
// Need to check if we have everything
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case "privatekey:":
|
||||
v1, err := packBase64([]byte(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.D.SetBytes(v1)
|
||||
case "created:", "publish:", "activate:":
|
||||
/* not used in Go (yet) */
|
||||
}
|
||||
}
|
||||
// Need to check if we have everything
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case "privatekey:":
|
||||
v1, err := packBase64([]byte(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.D.SetBytes(v1)
|
||||
case "created:", "publish:", "activate:":
|
||||
/* not used in Go (yet) */
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
|
10
msg.go
10
msg.go
|
@ -127,7 +127,7 @@ var Class_str = map[uint16]string{
|
|||
ClassCSNET: "CS",
|
||||
ClassCHAOS: "CH",
|
||||
ClassHESIOD: "HS",
|
||||
ClassNONE: "NONE",
|
||||
ClassNONE: "NONE",
|
||||
ClassANY: "ANY",
|
||||
}
|
||||
|
||||
|
@ -363,8 +363,8 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
|
|||
i := fv.Uint()
|
||||
switch fv.Type().Kind() {
|
||||
default:
|
||||
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
|
||||
return len(msg), false
|
||||
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
|
||||
return len(msg), false
|
||||
case reflect.Uint8:
|
||||
if off+1 > len(msg) {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing uint8")
|
||||
|
@ -597,8 +597,8 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
|
|||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
switch fv.Type().Kind() {
|
||||
default:
|
||||
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
|
||||
return len(msg), false
|
||||
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
|
||||
return len(msg), false
|
||||
|
||||
case reflect.Uint8:
|
||||
if off+1 > len(msg) {
|
||||
|
|
198
parse_test.go
198
parse_test.go
|
@ -1,10 +1,10 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
"bufio"
|
||||
"strings"
|
||||
"os"
|
||||
"time"
|
||||
"bufio"
|
||||
"strings"
|
||||
"testing"
|
||||
"crypto/rsa"
|
||||
)
|
||||
|
@ -27,21 +27,21 @@ Publish: 20110302104537
|
|||
Activate: 20110302104537`
|
||||
|
||||
k := new(RR_DNSKEY)
|
||||
k.Read(strings.NewReader(pub))
|
||||
k.Read(strings.NewReader(pub))
|
||||
p, err := k.ReadPrivateKey(strings.NewReader(priv))
|
||||
if err != nil {
|
||||
t.Logf("%v\n", err)
|
||||
t.Fail()
|
||||
}
|
||||
if err != nil {
|
||||
t.Logf("%v\n", err)
|
||||
t.Fail()
|
||||
}
|
||||
switch priv := p.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
if 65537 != priv.PublicKey.E {
|
||||
t.Log("Exponenent should be 65537")
|
||||
t.Fail()
|
||||
}
|
||||
default:
|
||||
t.Logf("We should have read an RSA key: %v", priv)
|
||||
t.Fail()
|
||||
default:
|
||||
t.Logf("We should have read an RSA key: %v", priv)
|
||||
t.Fail()
|
||||
}
|
||||
if k.KeyTag() != 37350 {
|
||||
t.Logf("%d %v\n", k.KeyTag(), k)
|
||||
|
@ -68,113 +68,111 @@ Activate: 20110302104537`
|
|||
sig.Algorithm = k.Algorithm
|
||||
|
||||
sig.Sign(p, []RR{soa})
|
||||
if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
|
||||
t.Log("Signature is not correct")
|
||||
t.Logf("%v\n", sig)
|
||||
t.Fail()
|
||||
}
|
||||
if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
|
||||
t.Log("Signature is not correct")
|
||||
t.Logf("%v\n", sig)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDotInName(t *testing.T) {
|
||||
buf := make([]byte, 20)
|
||||
packDomainName("aa\\.bb.nl.", buf, 0)
|
||||
// index 3 must be a real dot
|
||||
if buf[3] != '.' {
|
||||
t.Log("Dot should be a real dot")
|
||||
t.Fail()
|
||||
}
|
||||
// index 3 must be a real dot
|
||||
if buf[3] != '.' {
|
||||
t.Log("Dot should be a real dot")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if buf[6] != 2 {
|
||||
t.Log("This must have the value 2")
|
||||
t.Fail()
|
||||
}
|
||||
dom, _, _ := unpackDomainName(buf, 0)
|
||||
// printing it should yield the backspace again
|
||||
if dom != "aa\\.bb.nl." {
|
||||
t.Log("Dot should have been escaped: " + dom)
|
||||
t.Fail()
|
||||
}
|
||||
if buf[6] != 2 {
|
||||
t.Log("This must have the value 2")
|
||||
t.Fail()
|
||||
}
|
||||
dom, _, _ := unpackDomainName(buf, 0)
|
||||
// printing it should yield the backspace again
|
||||
if dom != "aa\\.bb.nl." {
|
||||
t.Log("Dot should have been escaped: " + dom)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Make this a decend test case. For now, good enough
|
||||
// New style (Ragel) parsing
|
||||
func TestParse(t *testing.T) {
|
||||
tests := map[string]string{
|
||||
"miek.nl. 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. 3600 IN MX 10 elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.",
|
||||
"miek.nl. IN 3600 A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. A 127.0.0.1": "miek.nl.\t0\tCLASS0\tA\t127.0.0.1",
|
||||
"miek.nl. IN AAAA ::1": "miek.nl.\t0\tIN\tAAAA\t::1",
|
||||
"miek.nl. IN A 127.0.0.1": "miek.nl.\t0\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ":
|
||||
"miek.nl.\t0\tIN\tDNSKEY\t256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ",
|
||||
"nlnetlabs.nl. 3175 IN DNSKEY 256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh":
|
||||
"nlnetlabs.nl.\t3175\tIN\tDNSKEY\t256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh",
|
||||
}
|
||||
for test, result := range tests {
|
||||
p := NewParser(strings.NewReader(test))
|
||||
z, err := p.Zone()
|
||||
if err != nil || z == nil{
|
||||
t.Logf("Error of nil r %v %s\n", err, test)
|
||||
t.Fail()
|
||||
}
|
||||
r := z.Pop().(RR)
|
||||
if r.String() != result {
|
||||
t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
tests := map[string]string{
|
||||
"miek.nl. 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. 3600 IN MX 10 elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.",
|
||||
"miek.nl. IN 3600 A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. A 127.0.0.1": "miek.nl.\t0\tCLASS0\tA\t127.0.0.1",
|
||||
"miek.nl. IN AAAA ::1": "miek.nl.\t0\tIN\tAAAA\t::1",
|
||||
"miek.nl. IN A 127.0.0.1": "miek.nl.\t0\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ": "miek.nl.\t0\tIN\tDNSKEY\t256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ",
|
||||
"nlnetlabs.nl. 3175 IN DNSKEY 256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh": "nlnetlabs.nl.\t3175\tIN\tDNSKEY\t256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh",
|
||||
}
|
||||
for test, result := range tests {
|
||||
p := NewParser(strings.NewReader(test))
|
||||
z, err := p.Zone()
|
||||
if err != nil || z == nil {
|
||||
t.Logf("Error of nil r %v %s\n", err, test)
|
||||
t.Fail()
|
||||
}
|
||||
r := z.Pop().(RR)
|
||||
if r.String() != result {
|
||||
t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetString(t *testing.T) {
|
||||
a := NewRR("miek.nl. IN A 127.0.0.1")
|
||||
if a.String() != "miek.nl.\t0\tIN\tA\t127.0.0.1" {
|
||||
t.Log(a.String(), "!= miek.nl. IN A 127.0.0.1")
|
||||
t.Fail()
|
||||
}
|
||||
b := NewRR("miek.nl. IN AAAA ::1")
|
||||
if b.String() != "miek.nl.\t0\tIN\tAAAA\t::1" {
|
||||
t.Log(b.String(), "!= miek.nl. IN AAAA ::1")
|
||||
t.Fail()
|
||||
}
|
||||
c := NewRR("miek.nl. IN MX 10 miek.nl.")
|
||||
if c.String() != "miek.nl.\t0\tIN\tMX\t10 miek.nl." {
|
||||
t.Log(c.String(), "!= miek.nl. IN MX 10 miek.nl.")
|
||||
t.Fail()
|
||||
}
|
||||
d := NewRR("miek.nl. IN NS ns1.miek.nl")
|
||||
if d.String() != "miek.nl.\t0\tIN\tNS\tns1.miek.nl" {
|
||||
t.Log(d.String(), "!= miek.nl. IN NS ns1.miek.nl")
|
||||
t.Fail()
|
||||
}
|
||||
a := NewRR("miek.nl. IN A 127.0.0.1")
|
||||
if a.String() != "miek.nl.\t0\tIN\tA\t127.0.0.1" {
|
||||
t.Log(a.String(), "!= miek.nl. IN A 127.0.0.1")
|
||||
t.Fail()
|
||||
}
|
||||
b := NewRR("miek.nl. IN AAAA ::1")
|
||||
if b.String() != "miek.nl.\t0\tIN\tAAAA\t::1" {
|
||||
t.Log(b.String(), "!= miek.nl. IN AAAA ::1")
|
||||
t.Fail()
|
||||
}
|
||||
c := NewRR("miek.nl. IN MX 10 miek.nl.")
|
||||
if c.String() != "miek.nl.\t0\tIN\tMX\t10 miek.nl." {
|
||||
t.Log(c.String(), "!= miek.nl. IN MX 10 miek.nl.")
|
||||
t.Fail()
|
||||
}
|
||||
d := NewRR("miek.nl. IN NS ns1.miek.nl")
|
||||
if d.String() != "miek.nl.\t0\tIN\tNS\tns1.miek.nl" {
|
||||
t.Log(d.String(), "!= miek.nl. IN NS ns1.miek.nl")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkZoneParsing(b *testing.B) {
|
||||
file, err := os.Open("miek.nl")
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p := NewParser(bufio.NewReader(file))
|
||||
// Don't care about errors (there shouldn't be any)
|
||||
p.Zone()
|
||||
file, err := os.Open("miek.nl")
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p := NewParser(bufio.NewReader(file))
|
||||
// Don't care about errors (there shouldn't be any)
|
||||
p.Zone()
|
||||
}
|
||||
|
||||
func TestZoneParsing(t *testing.T) {
|
||||
file, err := os.Open("miek.nl")
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p := NewParser(bufio.NewReader(file))
|
||||
file, err := os.Open("miek.nl")
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p := NewParser(bufio.NewReader(file))
|
||||
|
||||
// Don't care about errors (there shouldn't be any)
|
||||
start := time.Nanoseconds()
|
||||
z, err := p.Zone()
|
||||
if err != nil {
|
||||
t.Logf("error %v\n", err.String())
|
||||
t.Fail()
|
||||
}
|
||||
delta := time.Nanoseconds() - start
|
||||
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", z.Len()-1, float32(delta)/1e9, float32(z.Len()-1)/(float32(delta)/1e9))
|
||||
// Don't care about errors (there shouldn't be any)
|
||||
start := time.Nanoseconds()
|
||||
z, err := p.Zone()
|
||||
if err != nil {
|
||||
t.Logf("error %v\n", err.String())
|
||||
t.Fail()
|
||||
}
|
||||
delta := time.Nanoseconds() - start
|
||||
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", z.Len()-1, float32(delta)/1e9, float32(z.Len()-1)/(float32(delta)/1e9))
|
||||
}
|
||||
|
|
16
server.go
16
server.go
|
@ -23,7 +23,7 @@ type Handler interface {
|
|||
type ResponseWriter interface {
|
||||
// RemoteAddr returns the net.Addr of the client that sent the current request.
|
||||
RemoteAddr() net.Addr
|
||||
// Write a reply back to the client.
|
||||
// Write a reply back to the client.
|
||||
Write([]byte) (int, os.Error)
|
||||
}
|
||||
|
||||
|
@ -164,12 +164,12 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
|||
// A Server defines parameters for running an DNS server.
|
||||
// Note how much it starts to look like 'Client struct'
|
||||
type Server struct {
|
||||
Addr string // address to listen on, ":dns" if empty
|
||||
Net string // if "tcp" it will invoke a TCP listener, otherwise an UDP one
|
||||
Handler Handler // handler to invoke, dns.DefaultServeMux if nil
|
||||
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
|
||||
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>
|
||||
Addr string // address to listen on, ":dns" if empty
|
||||
Net string // if "tcp" it will invoke a TCP listener, otherwise an UDP one
|
||||
Handler Handler // handler to invoke, dns.DefaultServeMux if nil
|
||||
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
|
||||
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>
|
||||
}
|
||||
|
||||
// ...
|
||||
|
@ -333,7 +333,7 @@ func (w *response) Write(data []byte) (n int, err os.Error) {
|
|||
case w.conn._UDP != nil:
|
||||
n, err = w.conn._UDP.WriteTo(data, w.conn.remoteAddr)
|
||||
if err != nil {
|
||||
println(err.String())
|
||||
println(err.String())
|
||||
return 0, err
|
||||
}
|
||||
case w.conn._TCP != nil:
|
||||
|
|
|
@ -28,19 +28,19 @@ func TestServing(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkServing(b *testing.B) {
|
||||
b.StopTimer()
|
||||
// Again start a server
|
||||
b.StopTimer()
|
||||
// Again start a server
|
||||
HandleFunc("miek.nl.", HelloServer)
|
||||
go func() {
|
||||
ListenAndServe("127.0.0.1:8053", "udp", nil)
|
||||
ListenAndServe("127.0.0.1:8053", "udp", nil)
|
||||
}()
|
||||
|
||||
c := NewClient()
|
||||
m := new(Msg)
|
||||
m.SetQuestion("miek.nl", TypeSOA)
|
||||
c := NewClient()
|
||||
m := new(Msg)
|
||||
m.SetQuestion("miek.nl", TypeSOA)
|
||||
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Exchange(m, "127.0.0.1:8053")
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Exchange(m, "127.0.0.1:8053")
|
||||
}
|
||||
}
|
||||
|
|
4
types.go
4
types.go
|
@ -149,11 +149,11 @@ func (q *Question) String() string {
|
|||
// NewRR returns the last RR contained in s.
|
||||
func NewRR(s string) RR {
|
||||
p := NewParser(strings.NewReader(s))
|
||||
x := p.RR()
|
||||
x := p.RR()
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
return x
|
||||
return x
|
||||
}
|
||||
|
||||
type RR_CNAME struct {
|
||||
|
|
12
zone.go
12
zone.go
|
@ -5,30 +5,30 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"container/vector"
|
||||
"container/vector"
|
||||
)
|
||||
|
||||
// Zone implements the concept of RFC 1035 master zone files.
|
||||
type Zone struct {
|
||||
v vector.Vector
|
||||
v vector.Vector
|
||||
}
|
||||
|
||||
// Add a new RR to the zone.
|
||||
func (z *Zone) Push(r RR) {
|
||||
z.v.Push(r)
|
||||
z.v.Push(r)
|
||||
}
|
||||
|
||||
// Remove a RR from the zone.
|
||||
func (z *Zone) Pop() RR {
|
||||
return z.v.Pop().(RR)
|
||||
return z.v.Pop().(RR)
|
||||
}
|
||||
|
||||
// Return the RR at index i of zone.
|
||||
func (z *Zone) At(i int) RR {
|
||||
return z.v.At(i).(RR)
|
||||
return z.v.At(i).(RR)
|
||||
}
|
||||
|
||||
// The number of RRs in zone.
|
||||
func (z *Zone) Len() int {
|
||||
return z.v.Len()
|
||||
return z.v.Len()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue