Fix documentation
This commit is contained in:
parent
96a55dee9b
commit
9eea4682fd
12
TODO
12
TODO
|
@ -1,11 +1,8 @@
|
||||||
Todo:
|
Todo:
|
||||||
* NSEC3 - need base32 for Nsec3
|
* NSEC3 - need base32 for Nsec3
|
||||||
* Documentation
|
|
||||||
* Cleanup the code
|
|
||||||
* Cleanup the API
|
|
||||||
* Tsig testing
|
* Tsig testing
|
||||||
* Private key file parsing, exponent 65536 does not work
|
* Private key file parsing use io.Reader (or the like)
|
||||||
* Parsing from /etc/resolv.conf - clean up the code
|
* Parsing from /etc/resolv.conf - clean up the code, use normal packages
|
||||||
|
|
||||||
Longer term:
|
Longer term:
|
||||||
* Parsing from strings, going with goyacc and own lexer
|
* Parsing from strings, going with goyacc and own lexer
|
||||||
|
@ -18,13 +15,12 @@ Issues:
|
||||||
* Check the network order, it works now, but this is on Intel
|
* Check the network order, it works now, but this is on Intel
|
||||||
* Make the testsuite work with public DNS servers
|
* Make the testsuite work with public DNS servers
|
||||||
* shortened ipv6 addresses are not parsed correctly (maybe net issue)
|
* shortened ipv6 addresses are not parsed correctly (maybe net issue)
|
||||||
* Convenience functions?
|
* Convenience functions? Not sure if I want them??
|
||||||
- NXDomain pkt
|
- NXDomain pkt
|
||||||
- FormErr pkt
|
- FormErr pkt
|
||||||
- for new(RR*)
|
- for new(RR*)
|
||||||
- nsupdate
|
- nsupdate
|
||||||
- printing??
|
|
||||||
* query-time, server in string ouput of resolver.Msg
|
* query-time, server in string ouput of resolver.Msg
|
||||||
- resolver.Msg when doing resolver querying, extend msg...?
|
- resolver.Msg when doing resolver querying, extend msg...?
|
||||||
- also for the server?
|
- also for the server?
|
||||||
* Fix remaining records: LOC, NAPTR, ..., ...
|
* Fix remaining records: LOC and others
|
||||||
|
|
11
dns.go
11
dns.go
|
@ -3,7 +3,6 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
// Extended and bugfixes by Miek Gieben
|
// Extended and bugfixes by Miek Gieben
|
||||||
|
|
||||||
// Package dns implements a full featured interface to the DNS.
|
|
||||||
// Supported RFCs and features include:
|
// Supported RFCs and features include:
|
||||||
// * 1034/1035 - DNS standard
|
// * 1034/1035 - DNS standard
|
||||||
// * 1982 - Serial Arithmetic
|
// * 1982 - Serial Arithmetic
|
||||||
|
@ -24,8 +23,10 @@
|
||||||
// * 5011 - NSID
|
// * 5011 - NSID
|
||||||
// * 5936 - AXFR
|
// * 5936 - AXFR
|
||||||
// * IP6 support
|
// * IP6 support
|
||||||
//
|
|
||||||
// The package allows full control over what is send out to the DNS.
|
// Package dns implements a full featured interface to the DNS.
|
||||||
|
// The package allows full control over what is send out to the DNS. All RR types are converted
|
||||||
|
// to Go types.
|
||||||
//
|
//
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -33,8 +34,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// For RFC1982 (Serial Arithmetic) calculations.
|
||||||
const Year68 = 2 << (32 - 1)
|
const Year68 = 2 << (32 - 1)
|
||||||
|
|
||||||
|
// Error represents a DNS error
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Error string
|
Error string
|
||||||
Name string
|
Name string
|
||||||
|
@ -61,7 +64,7 @@ func (r RRset) Len() int { return len(r) }
|
||||||
func (r RRset) Less(i, j int) bool { return r[i].Header().Name < r[j].Header().Name }
|
func (r RRset) Less(i, j int) bool { return r[i].Header().Name < r[j].Header().Name }
|
||||||
func (r RRset) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
func (r RRset) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||||
|
|
||||||
// Check if the RRset is 2181 compliant
|
// Check if the RRset is RFC 2181 compliant
|
||||||
func (r RRset) Ok() bool {
|
func (r RRset) Ok() bool {
|
||||||
ttl := r[0].Header().Ttl
|
ttl := r[0].Header().Ttl
|
||||||
name := r[0].Header().Name
|
name := r[0].Header().Name
|
||||||
|
|
46
dnssec.go
46
dnssec.go
|
@ -19,7 +19,6 @@ import (
|
||||||
|
|
||||||
// DNSSEC encryption algorithm codes.
|
// DNSSEC encryption algorithm codes.
|
||||||
const (
|
const (
|
||||||
// DNSSEC algorithms
|
|
||||||
AlgRSAMD5 = 1
|
AlgRSAMD5 = 1
|
||||||
AlgDH = 2
|
AlgDH = 2
|
||||||
AlgDSA = 3
|
AlgDSA = 3
|
||||||
|
@ -58,6 +57,7 @@ type dnskeyWireFmt struct {
|
||||||
Protocol uint8
|
Protocol uint8
|
||||||
Algorithm uint8
|
Algorithm uint8
|
||||||
PubKey string "base64"
|
PubKey string "base64"
|
||||||
|
/* Nothing is left out */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the keytag of the DNSKEY.
|
// Calculate the keytag of the DNSKEY.
|
||||||
|
@ -139,19 +139,18 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
|
||||||
io.WriteString(s, string(digest))
|
io.WriteString(s, string(digest))
|
||||||
ds.Digest = hex.EncodeToString(s.Sum())
|
ds.Digest = hex.EncodeToString(s.Sum())
|
||||||
case HashGOST94:
|
case HashGOST94:
|
||||||
|
/* I have no clue */
|
||||||
default:
|
default:
|
||||||
// wrong hash value
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ds
|
return ds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign an RRSet. The Signature needs to be filled in with
|
// Sign an RRSet. The Signature needs to be filled in with
|
||||||
// all the values: Inception, Expiration, KeyTag(?), SignerName
|
// all the values: Inception, Expiration, KeyTag and SignerName
|
||||||
// the rest is copied from the RRset. Return true when all ok.
|
// The rest is copied from the RRset. Return true when the signing went OK.
|
||||||
// The Signature data is filled by this method
|
// The Signature data is the RRSIG is filled by this method.
|
||||||
// There is no check if rrset is a proper (RFC 2181) RRSet
|
// There is no check if rrset is a proper (RFC 2181) RRSet.
|
||||||
func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
||||||
if k == nil {
|
if k == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -161,14 +160,13 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
||||||
s.Hdr.Class = rrset[0].Header().Class
|
s.Hdr.Class = rrset[0].Header().Class
|
||||||
s.Hdr.Rrtype = TypeRRSIG
|
s.Hdr.Rrtype = TypeRRSIG
|
||||||
s.Hdr.Ttl = rrset[0].Header().Ttl // re-use TTL of RRset
|
s.Hdr.Ttl = rrset[0].Header().Ttl // re-use TTL of RRset
|
||||||
/* Check that these are there */
|
|
||||||
/*
|
if s.KeyTag == 0 || len(s.SignerName) == 0 {
|
||||||
s.Inception = inception
|
// Must be set
|
||||||
s.Expiration = expiration
|
return false
|
||||||
s.KeyTag = k.KeyTag()
|
}
|
||||||
s.SignerName = k.Hdr.Name
|
// Algorithm is check below
|
||||||
s.Algorithm = ??
|
// s.Inception and s.Expiration may be 0 (rollover etc.)
|
||||||
*/
|
|
||||||
s.Labels = LabelCount(rrset[0].Header().Name)
|
s.Labels = LabelCount(rrset[0].Header().Name)
|
||||||
s.TypeCovered = rrset[0].Header().Rrtype
|
s.TypeCovered = rrset[0].Header().Rrtype
|
||||||
|
|
||||||
|
@ -247,6 +245,9 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
||||||
case AlgRSASHA512:
|
case AlgRSASHA512:
|
||||||
h = sha512.New()
|
h = sha512.New()
|
||||||
ch = rsa.HashSHA512
|
ch = rsa.HashSHA512
|
||||||
|
default:
|
||||||
|
// Illegal Alg
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
// Need privakey representation in godns TODO(mg) see keygen.go
|
// Need privakey representation in godns TODO(mg) see keygen.go
|
||||||
io.WriteString(h, string(signdata))
|
io.WriteString(h, string(signdata))
|
||||||
|
@ -273,26 +274,20 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate an rrset with the signature and key. This is the
|
// Validate an rrset with the signature and key. This is only the
|
||||||
// cryptographic test, the validity period most be check separately.
|
// cryptographic test, the signature validity period most be check separately.
|
||||||
func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
|
func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
|
||||||
// Frist the easy checks
|
// Frist the easy checks
|
||||||
if s.KeyTag != k.KeyTag() {
|
if s.KeyTag != k.KeyTag() {
|
||||||
println(s.KeyTag)
|
|
||||||
println(k.KeyTag())
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if s.Hdr.Class != k.Hdr.Class {
|
if s.Hdr.Class != k.Hdr.Class {
|
||||||
println("Class")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if s.Algorithm != k.Algorithm {
|
if s.Algorithm != k.Algorithm {
|
||||||
println("Class")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if s.SignerName != k.Hdr.Name {
|
if s.SignerName != k.Hdr.Name {
|
||||||
println(s.SignerName)
|
|
||||||
println(k.Hdr.Name)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, r := range rrset {
|
for _, r := range rrset {
|
||||||
|
@ -390,12 +385,13 @@ func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
|
||||||
case AlgDSA:
|
case AlgDSA:
|
||||||
case AlgECC:
|
case AlgECC:
|
||||||
case AlgECCGOST:
|
case AlgECCGOST:
|
||||||
|
default:
|
||||||
|
// Unknown Alg
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beter name for this function
|
|
||||||
// Using RFC1982 calculate if a signature period is valid
|
// Using RFC1982 calculate if a signature period is valid
|
||||||
func (s *RR_RRSIG) PeriodOK() bool {
|
func (s *RR_RRSIG) PeriodOK() bool {
|
||||||
utc := time.UTC().Seconds()
|
utc := time.UTC().Seconds()
|
||||||
|
|
19
edns.go
19
edns.go
|
@ -33,7 +33,7 @@ type Option struct {
|
||||||
|
|
||||||
type RR_OPT struct {
|
type RR_OPT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Option []Option "OPT" // Tag is used in pack and unpack
|
Option []Option "OPT" // Tag is used in Pack and Unpack
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *RR_OPT) Header() *RR_Header {
|
func (rr *RR_OPT) Header() *RR_Header {
|
||||||
|
@ -66,12 +66,12 @@ func (rr *RR_OPT) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the version
|
// Get the EDNS version (always 0 currently)
|
||||||
func (rr *RR_OPT) Version() uint8 {
|
func (rr *RR_OPT) Version() uint8 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the version of edns
|
// Set the version of EDNS
|
||||||
func (rr *RR_OPT) SetVersion(v uint8) {
|
func (rr *RR_OPT) SetVersion(v uint8) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func (rr *RR_OPT) UDPSize() uint16 {
|
||||||
return rr.Hdr.Class
|
return rr.Hdr.Class
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set/Get the UDP buffer size
|
// Set the UDP buffer size
|
||||||
func (rr *RR_OPT) SetUDPSize(size uint16) {
|
func (rr *RR_OPT) SetUDPSize(size uint16) {
|
||||||
rr.Hdr.Class = size
|
rr.Hdr.Class = size
|
||||||
}
|
}
|
||||||
|
@ -116,15 +116,8 @@ func (rr *RR_OPT) Nsid() string {
|
||||||
return "NSID: " + rr.Option[0].Data
|
return "NSID: " + rr.Option[0].Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of NSID is in Hex
|
// Set the NSID from a string which is represented as hex characters.
|
||||||
|
func (rr *RR_OPT) SetNsid(hexnsid string) {
|
||||||
// Set the NSID
|
|
||||||
func (rr *RR_OPT) SetNsidToHex(hexnsid string) {
|
|
||||||
rr.Option[0].Code = OptionCodeNSID
|
rr.Option[0].Code = OptionCodeNSID
|
||||||
rr.Option[0].Data = hexnsid
|
rr.Option[0].Data = hexnsid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *RR_OPT) SetNsidToString(nsid string) {
|
|
||||||
rr.Option[0].Code = OptionCodeNSID
|
|
||||||
rr.Option[0].Data = hex.EncodeToString([]byte(nsid))
|
|
||||||
}
|
|
||||||
|
|
15
keygen.go
15
keygen.go
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Empty interface that is used a wrapper around all possible
|
// Empty interface that is used a wrapper around all possible
|
||||||
// private key implementation from the crypto package.
|
// private key implementations from the crypto package.
|
||||||
type PrivateKey interface{}
|
type PrivateKey interface{}
|
||||||
|
|
||||||
// io.Reader
|
// io.Reader
|
||||||
|
@ -53,20 +53,14 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a PrivateKey to a string. This
|
// Convert a PrivateKey to a string. This
|
||||||
// string has the same format as the private-key-file
|
// string has the same format as the private-key-file of BIND9 (Private-key-format: v1.3).
|
||||||
// of BIND9 (Private-key-format: v1.3). It needs some
|
// It needs some info from the key (hashing, keytag), so its a method of the RR_DNSKEY.
|
||||||
// info from the key (hashing, keytag), so its a method
|
|
||||||
// of the RR_DNSKEY.
|
|
||||||
func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
|
func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
|
||||||
switch t := p.(type) {
|
switch t := p.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + alg_str[r.Algorithm] + ")"
|
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + alg_str[r.Algorithm] + ")"
|
||||||
modulus := unpackBase64(t.PublicKey.N.Bytes())
|
modulus := unpackBase64(t.PublicKey.N.Bytes())
|
||||||
e := big.NewInt(int64(t.PublicKey.E))
|
e := big.NewInt(int64(t.PublicKey.E))
|
||||||
/*
|
|
||||||
pub := make([]byte, 1)
|
|
||||||
pub[0] = uint8(t.PublicKey.E) // Todo does not fit with binds 65537 exp!
|
|
||||||
*/
|
|
||||||
publicExponent := unpackBase64(e.Bytes())
|
publicExponent := unpackBase64(e.Bytes())
|
||||||
privateExponent := unpackBase64(t.D.Bytes())
|
privateExponent := unpackBase64(t.D.Bytes())
|
||||||
prime1 := unpackBase64(t.P.Bytes())
|
prime1 := unpackBase64(t.P.Bytes())
|
||||||
|
@ -99,8 +93,7 @@ func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a private key file and create a public key and
|
// Read a private key (file) string and create a public key. Return a private key
|
||||||
// return a private key
|
|
||||||
func (k *RR_DNSKEY) PrivateKeySetString(s string) (PrivateKey, os.Error) {
|
func (k *RR_DNSKEY) PrivateKeySetString(s string) (PrivateKey, os.Error) {
|
||||||
p := new(rsa.PrivateKey)
|
p := new(rsa.PrivateKey)
|
||||||
r := bufio.NewReader(strings.NewReader(s))
|
r := bufio.NewReader(strings.NewReader(s))
|
||||||
|
|
1
msg.go
1
msg.go
|
@ -675,6 +675,7 @@ func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) {
|
||||||
return rr, off, ok
|
return rr, off, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse a map
|
||||||
func reverse(m map[uint16]string) map[string]uint16 {
|
func reverse(m map[uint16]string) map[string]uint16 {
|
||||||
n := make(map[string]uint16)
|
n := make(map[string]uint16)
|
||||||
for u, s := range m {
|
for u, s := range m {
|
||||||
|
|
|
@ -41,10 +41,6 @@ type Msg struct {
|
||||||
Dns *dns.Msg
|
Dns *dns.Msg
|
||||||
Error os.Error
|
Error os.Error
|
||||||
}
|
}
|
||||||
// ^ prolly extend this so that servers can use this too. We need
|
|
||||||
// to also encode some client side stuff in here, like client addr
|
|
||||||
// I think that is the *only* thing we need.
|
|
||||||
|
|
||||||
|
|
||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
Servers []string // servers to use
|
Servers []string // servers to use
|
||||||
|
@ -138,7 +134,7 @@ func query(res *Resolver, msg chan Msg) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new xfr as a goroutine, return a channel.
|
// Start a new xfr as a goroutine, return a channel of Msg.
|
||||||
// Channel will be closed when the axfr is finished, until
|
// Channel will be closed when the axfr is finished, until
|
||||||
// that time new messages will appear on the channel
|
// that time new messages will appear on the channel
|
||||||
func (res *Resolver) NewXfer() (ch chan Msg) {
|
func (res *Resolver) NewXfer() (ch chan Msg) {
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
|
|
||||||
// DNS server implementation
|
// DNS server implementation
|
||||||
|
|
||||||
// Package responder implements a DNS server. A nameserver needs to implement
|
// Package responder implements a DNS server. Any nameserver needs to implement
|
||||||
// the Responder interface:
|
// the Responder interface to get things going.
|
||||||
|
//
|
||||||
|
// Typical usage of the package:
|
||||||
//
|
//
|
||||||
// type myserv Server
|
// type myserv Server
|
||||||
// func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { /* UDP reply */ }
|
// func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { /* UDP reply */ }
|
||||||
// func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { /* TCP reply */}
|
// func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { /* TCP reply */}
|
||||||
|
//
|
||||||
// su := new(Server) // create new sever
|
// su := new(Server) // create new sever
|
||||||
// su.Address = "127.0.0.1" // listen address
|
// su.Address = "127.0.0.1" // listen address
|
||||||
// su.Port = "8053" // listen port
|
// su.Port = "8053" // listen port
|
||||||
|
@ -44,17 +47,19 @@ type msg struct {
|
||||||
// the kind of nameserver
|
// the kind of nameserver
|
||||||
type Responder interface {
|
type Responder interface {
|
||||||
// Receives the raw message content and writes back
|
// Receives the raw message content and writes back
|
||||||
// an udp response. An UDP connection needs a remote
|
// an UDP response. An UDP connection needs a remote
|
||||||
// address to write to.
|
// address to write to. ResponderUDP() must take care of sending
|
||||||
|
// any response back to the requestor.
|
||||||
ResponderUDP(c *net.UDPConn, a net.Addr, in []byte)
|
ResponderUDP(c *net.UDPConn, a net.Addr, in []byte)
|
||||||
// Receives the raw message content and writes back
|
// Receives the raw message content and writes back
|
||||||
// a tcp response. A TCP connection does need to
|
// a TCP response. A TCP connection does need to
|
||||||
// know explicitly be told the remote address.
|
// know explicitly be told the remote address. ResponderTCP() must
|
||||||
|
// take care of sending back a response to the requestor.
|
||||||
ResponderTCP(c *net.TCPConn, in []byte)
|
ResponderTCP(c *net.TCPConn, in []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new responder. The returned channel is only used
|
// Start a new responder. The returned channel is only used to stop the responder.
|
||||||
// to stop the responder.
|
// Send 'true' to make it stop
|
||||||
func (res *Server) NewResponder(h Responder, ch chan bool) os.Error {
|
func (res *Server) NewResponder(h Responder, ch chan bool) os.Error {
|
||||||
var port string
|
var port string
|
||||||
if len(res.Address) == 0 {
|
if len(res.Address) == 0 {
|
||||||
|
@ -109,6 +114,7 @@ func (res *Server) NewResponder(h Responder, ch chan bool) os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for UDP requests.
|
||||||
func listenerUDP(a *net.UDPAddr, ch chan msg) {
|
func listenerUDP(a *net.UDPAddr, ch chan msg) {
|
||||||
c, err := net.ListenUDP("udp", a)
|
c, err := net.ListenUDP("udp", a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -128,6 +134,7 @@ func listenerUDP(a *net.UDPAddr, ch chan msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for TCP requests.
|
||||||
func listenerTCP(a *net.TCPAddr, ch chan msg) {
|
func listenerTCP(a *net.TCPAddr, ch chan msg) {
|
||||||
t, err := net.ListenTCP("tcp", a)
|
t, err := net.ListenTCP("tcp", a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -171,7 +178,7 @@ func listenerTCP(a *net.TCPAddr, ch chan msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a buffer on the TCP connection
|
// Send a buffer on the TCP connection.
|
||||||
func SendTCP(m []byte, c *net.TCPConn) os.Error {
|
func SendTCP(m []byte, c *net.TCPConn) os.Error {
|
||||||
l := make([]byte, 2)
|
l := make([]byte, 2)
|
||||||
l[0] = byte(len(m) >> 8)
|
l[0] = byte(len(m) >> 8)
|
||||||
|
@ -189,8 +196,8 @@ func SendTCP(m []byte, c *net.TCPConn) os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Small helper function to help sending UDP packets. Mostly
|
// Send a buffer to the remove address. Only here because
|
||||||
// done for the symmetry. see SendTCP.
|
// of the symmetry with SendTCP().
|
||||||
func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error {
|
func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error {
|
||||||
_, err := c.WriteTo(m, a)
|
_, err := c.WriteTo(m, a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,8 +12,8 @@ const (
|
||||||
w = 7 * d
|
w = 7 * d
|
||||||
)
|
)
|
||||||
|
|
||||||
// Convert a Ttl to a value. Supported value 'm' for minutes, 'h' for hours
|
// Convert a Ttl to a value. Supported values: 'm' for minutes, 'h' for hours
|
||||||
// 'w' for week and 'd' for days. Stuff like '1d1d' is legal and return the value of '2d'
|
// 'w' for week and 'd' for days. Stuff like '1d1d' is legal and returns the value of '2d'
|
||||||
func StringToSeconds(ttl string) (sec uint32, ok bool) {
|
func StringToSeconds(ttl string) (sec uint32, ok bool) {
|
||||||
num := ""
|
num := ""
|
||||||
for _, k := range ttl {
|
for _, k := range ttl {
|
||||||
|
@ -41,6 +41,7 @@ func StringToSeconds(ttl string) (sec uint32, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a value to a (string) Ttl. Reverse of StringToSeconds()
|
||||||
func SecondsToString(val uint32) (str string) {
|
func SecondsToString(val uint32) (str string) {
|
||||||
mod := val / w
|
mod := val / w
|
||||||
if mod > 0 {
|
if mod > 0 {
|
||||||
|
|
20
tsig.go
20
tsig.go
|
@ -1,13 +1,12 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
// Implementation of TSIG
|
// Implementation of TSIG: generation and validation
|
||||||
// Generation an Validation
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"io"
|
"crypto/hmac"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ type RR_TSIG struct {
|
||||||
Fudge uint16
|
Fudge uint16
|
||||||
MACSize uint16
|
MACSize uint16
|
||||||
MAC string
|
MAC string
|
||||||
OrigId uint16 // msg id
|
OrigId uint16
|
||||||
Error uint16
|
Error uint16
|
||||||
OtherLen uint16
|
OtherLen uint16
|
||||||
OtherData string
|
OtherData string
|
||||||
|
@ -46,9 +45,8 @@ func (rr *RR_TSIG) String() string {
|
||||||
" " + rr.OtherData
|
" " + rr.OtherData
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following values must be put in wireformat, so that
|
// The following values must be put in wireformat, so that the MAC can be calculated.
|
||||||
// the MAC can be calculated
|
// RFC 2845, section 3.4.2. TSIG Variables.
|
||||||
// RFC 2845, section 3.4.2. TSIG Variables
|
|
||||||
type tsigWireFmt struct {
|
type tsigWireFmt struct {
|
||||||
// From RR_HEADER
|
// From RR_HEADER
|
||||||
Name string "domain-name"
|
Name string "domain-name"
|
||||||
|
@ -66,8 +64,8 @@ type tsigWireFmt struct {
|
||||||
|
|
||||||
// Generate the HMAC for msg. The TSIG RR is modified
|
// Generate the HMAC for msg. The TSIG RR is modified
|
||||||
// to include the MAC and MACSize. Note the the msg Id must
|
// to include the MAC and MACSize. Note the the msg Id must
|
||||||
// be set, otherwise the MAC is not correct
|
// be set, otherwise the MAC is not correct.
|
||||||
// secret is encoded in base64 in BIND9
|
// The string 'secret' must be encoded in base64
|
||||||
func (rr *RR_TSIG) Generate(msg *Msg, secret string) bool {
|
func (rr *RR_TSIG) Generate(msg *Msg, secret string) bool {
|
||||||
buf := make([]byte, 4096) // TODO(mg) bufsize!
|
buf := make([]byte, 4096) // TODO(mg) bufsize!
|
||||||
tsig := new(tsigWireFmt)
|
tsig := new(tsigWireFmt)
|
||||||
|
@ -104,7 +102,7 @@ func (rr *RR_TSIG) Generate(msg *Msg, secret string) bool {
|
||||||
|
|
||||||
// Verify a TSIG. The msg should be the complete message with
|
// Verify a TSIG. The msg should be the complete message with
|
||||||
// the TSIG record still attached (as the last rr in the Additional
|
// the TSIG record still attached (as the last rr in the Additional
|
||||||
// section)
|
// section) TODO(mg)
|
||||||
func (rr *RR_TSIG) Verify(msg *Msg, secret string) bool {
|
func (rr *RR_TSIG) Verify(msg *Msg, secret string) bool {
|
||||||
// copy the mesg, strip (and check) the tsig rr
|
// copy the mesg, strip (and check) the tsig rr
|
||||||
// perform the opposite of Generate() and then
|
// perform the opposite of Generate() and then
|
||||||
|
|
2
types.go
2
types.go
|
@ -6,8 +6,8 @@
|
||||||
// Basic usage pattern for creating new Resource Record:
|
// Basic usage pattern for creating new Resource Record:
|
||||||
//
|
//
|
||||||
// r := new(RR_TXT)
|
// r := new(RR_TXT)
|
||||||
// r.TXT = "This is the content of the TXT record"
|
|
||||||
// r.Hdr = RR_Header{Name: "a.miek.nl", Rrtype: TypeTXT, Class: ClassINET, Ttl: 3600}
|
// r.Hdr = RR_Header{Name: "a.miek.nl", Rrtype: TypeTXT, Class: ClassINET, Ttl: 3600}
|
||||||
|
// r.TXT = "This is the content of the TXT record"
|
||||||
//
|
//
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue