refactoring

pull/18/head
Hugo Landau 10 years ago
parent 13d64f59a7
commit 3f88db348f

@ -0,0 +1,16 @@
package abstract
import "github.com/miekg/dns"
type Backend interface {
// Lookup all resource records having a given fully-qualified owner name,
// regardless of type or class. Returns a slice of all those resource records
// or an error.
//
// The returned slice may contain both authoritative and non-authoritative records
// (for example, NS records for delegations and glue records.)
//
// The existence of wildcard records will be determined by doing a lookup for a name
// like "*.example.com", so there is no need to process the wildcard logic other than
// to make sure such a lookup functions correctly.
Lookup(qname string) (rrs []dns.RR, err error)
}

@ -1,4 +1,4 @@
package main
package backend
import "github.com/golang/groupcache/lru"
import "github.com/miekg/dns"
import "github.com/hlandau/degoutils/log"
@ -10,43 +10,62 @@ import "strings"
import "net"
import "github.com/hlandau/ncdns/namecoin"
import "github.com/hlandau/ncdns/ncerr"
type Backend interface {
// Lookup all resource records having a given fully-qualified owner name,
// regardless of type or class. Returns a slice of all those resource records
// or an error.
//
// The returned slice may contain both authoritative and non-authoritative records
// (for example, NS records for delegations and glue records.)
//
// The existence of wildcard records will be determined by doing a lookup for a name
// like "*.example.com", so there is no need to process the wildcard logic other than
// to make sure such a lookup functions correctly.
Lookup(qname string) (rrs []dns.RR, err error)
}
import "github.com/hlandau/ncdns/util"
import "github.com/hlandau/ncdns/abstract"
type ncBackend struct {
s *Server
//s *Server
nc namecoin.NamecoinConn
cache lru.Cache // items are of type *Domain
cfg Config
}
const (
defaultMaxEntries = 100
)
type Config struct {
// Username and password to use for connecting to the Namecoin JSON-RPC interface.
RPCUsername string
RPCPassword string
// hostname:port to use for connecting to the Namecoin JSON-RPC interface.
RPCAddress string
// Maximum entries to permit in name cache. If zero, a default value is used.
CacheMaxEntries int
// The hostname which should be advertised as the primary nameserver for the zone.
// If left empty, a psuedo-hostname resolvable to SelfIP is used.
SelfName string
// Used only if SelfName is left blank. An IP which the internal psuedo-hostname
// should resolve to. This should be the public IP of the nameserver serving the
// zone expressed by this backend.
SelfIP string
}
func NewNCBackend(s *Server) (b *ncBackend, err error) {
b = &ncBackend{}
// Creates a new Namecoin backend.
func New(cfg *Config) (backend abstract.Backend, err error) {
b := &ncBackend{}
b.s = s
b.cfg = *cfg
b.nc.Username = cfg.RPCUsername
b.nc.Password = cfg.RPCPassword
b.nc.Server = cfg.RPCAddress
b.nc.Username = s.cfg.NamecoinRPCUsername
b.nc.Password = s.cfg.NamecoinRPCPassword
b.nc.Server = s.cfg.NamecoinRPCAddress
b.cache.MaxEntries = cfg.CacheMaxEntries
if b.cache.MaxEntries == 0 {
b.cache.MaxEntries = defaultMaxEntries
}
b.cache.MaxEntries = b.s.cfg.CacheMaxEntries
backend = b
return
}
// Keep domains in DNS format.
type Domain struct {
type domain struct {
ncv *ncValue
}
@ -59,15 +78,16 @@ type ncValue struct {
NS interface{} `json:"ns"`
Map map[string]*ncValue `json:"map"` // may contain "" and "*"
DS [][]interface{} `json:"ds"`
TXT interface{} `json:"txt"`
}
func toNamecoinName(basename string) (string, error) {
return "d/" + basename, nil
}
func (b *ncBackend) getNamecoinEntry(name string) (*Domain, error) {
func (b *ncBackend) getNamecoinEntry(name string) (*domain, error) {
if dd, ok := b.cache.Get(name); ok {
d := dd.(*Domain)
d := dd.(*domain)
return d, nil
}
@ -80,7 +100,7 @@ func (b *ncBackend) getNamecoinEntry(name string) (*Domain, error) {
return d, nil
}
func (b *ncBackend) getNamecoinEntryLL(name string) (*Domain, error) {
func (b *ncBackend) getNamecoinEntryLL(name string) (*domain, error) {
v, err := b.nc.Query(name)
if err != nil {
log.Infoe(err, "namecoin query failed: ", err)
@ -98,8 +118,8 @@ func (b *ncBackend) getNamecoinEntryLL(name string) (*Domain, error) {
return d, nil
}
func (b *ncBackend) jsonToDomain(v string) (dd *Domain, err error) {
d := &Domain{}
func (b *ncBackend) jsonToDomain(v string) (dd *domain, err error) {
d := &domain{}
ncv := &ncValue{}
err = json.Unmarshal([]byte(v), ncv)
@ -114,14 +134,14 @@ func (b *ncBackend) jsonToDomain(v string) (dd *Domain, err error) {
return
}
type Btx struct {
type btx struct {
b *ncBackend
qname string
subname, basename, rootname string
}
func (tx *Btx) determineDomain() (subname, basename, rootname string, err error) {
func (tx *btx) determineDomain() (subname, basename, rootname string, err error) {
qname := tx.qname
qname = strings.TrimRight(qname, ".")
parts := strings.Split(qname, ".")
@ -156,7 +176,7 @@ func (tx *Btx) determineDomain() (subname, basename, rootname string, err error)
return
}
func (tx *Btx) Do() (rrs []dns.RR, err error) {
func (tx *btx) Do() (rrs []dns.RR, err error) {
tx.subname, tx.basename, tx.rootname, err = tx.determineDomain()
if err != nil {
log.Infoe(err, "couldn't determine domain")
@ -174,7 +194,7 @@ func (tx *Btx) Do() (rrs []dns.RR, err error) {
return tx.doRootDomain()
}
if tx.basename == "x--nmc" && tx.b.s.cfg.SelfName == "" {
if tx.basename == "x--nmc" && tx.b.cfg.SelfName == "" {
return tx.doMetaDomain()
}
@ -188,20 +208,20 @@ func (tx *Btx) Do() (rrs []dns.RR, err error) {
return
}
func (tx *Btx) doRootDomain() (rrs []dns.RR, err error) {
nsname := tx.b.s.cfg.SelfName
func (tx *btx) doRootDomain() (rrs []dns.RR, err error) {
nsname := tx.b.cfg.SelfName
if nsname == "" {
nsname = "this.x--nmc." + tx.rootname
}
soa := &dns.SOA {
Hdr: dns.RR_Header {
Name: absname(tx.rootname),
Name: util.Absname(tx.rootname),
Ttl: 86400,
Class: dns.ClassINET,
Rrtype: dns.TypeSOA,
},
Ns: absname(nsname),
Ns: util.Absname(nsname),
Mbox: ".",
Serial: 1,
Refresh: 600,
@ -212,20 +232,20 @@ func (tx *Btx) doRootDomain() (rrs []dns.RR, err error) {
ns := &dns.NS {
Hdr: dns.RR_Header {
Name: absname(tx.rootname),
Name: util.Absname(tx.rootname),
Ttl: 86400,
Class: dns.ClassINET,
Rrtype: dns.TypeNS,
},
Ns: absname(nsname),
Ns: util.Absname(nsname),
}
rrs = []dns.RR{ soa, ns, }
return
}
func (tx *Btx) doMetaDomain() (rrs []dns.RR, err error) {
ip := net.ParseIP(tx.b.s.cfg.SelfIP)
func (tx *btx) doMetaDomain() (rrs []dns.RR, err error) {
ip := net.ParseIP(tx.b.cfg.SelfIP)
if ip == nil || ip.To4() == nil {
return nil, fmt.Errorf("invalid value specified for SelfIP")
}
@ -235,7 +255,7 @@ func (tx *Btx) doMetaDomain() (rrs []dns.RR, err error) {
rrs = []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: absname("this." + tx.basename + "." + tx.rootname),
Name: util.Absname("this." + tx.basename + "." + tx.rootname),
Ttl: 86400,
Class: dns.ClassINET,
Rrtype: dns.TypeA,
@ -250,7 +270,7 @@ func (tx *Btx) doMetaDomain() (rrs []dns.RR, err error) {
return
}
func (tx *Btx) doUserDomain() (rrs []dns.RR, err error) {
func (tx *btx) doUserDomain() (rrs []dns.RR, err error) {
ncname, err := toNamecoinName(tx.basename)
if err != nil {
log.Infoe(err, "cannot determine namecoin name")
@ -272,7 +292,7 @@ func (tx *Btx) doUserDomain() (rrs []dns.RR, err error) {
return rrs, nil
}
func (tx *Btx) doUnderDomain(d *Domain) (rrs []dns.RR, err error) {
func (tx *btx) doUnderDomain(d *domain) (rrs []dns.RR, err error) {
rrs, err = tx.addAnswersUnderNCValue(d.ncv, tx.subname)
if err == ncerr.ErrNoResults {
err = nil
@ -281,7 +301,7 @@ func (tx *Btx) doUnderDomain(d *Domain) (rrs []dns.RR, err error) {
return
}
func (tx *Btx) addAnswersUnderNCValue(rncv *ncValue, subname string) (rrs []dns.RR, err error) {
func (tx *btx) addAnswersUnderNCValue(rncv *ncValue, subname string) (rrs []dns.RR, err error) {
ncv, sn, err := tx.findNCValue(rncv, subname, nil /*hasNS*/)
if err != nil {
return
@ -296,11 +316,11 @@ func hasNS(ncv *ncValue) bool {
return err == nil && len(nss) > 0
}
func (tx *Btx) findNCValue(ncv *ncValue, subname string, shortCircuitFunc func(curNCV *ncValue) bool) (xncv *ncValue, sn string, err error) {
func (tx *btx) findNCValue(ncv *ncValue, subname string, shortCircuitFunc func(curNCV *ncValue) bool) (xncv *ncValue, sn string, err error) {
return tx._findNCValue(ncv, subname, "", 0, shortCircuitFunc)
}
func (tx *Btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
func (tx *btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
shortCircuitFunc func(curNCV *ncValue) bool) (xncv *ncValue, sn string, err error) {
if shortCircuitFunc != nil && shortCircuitFunc(ncv) {
@ -308,7 +328,7 @@ func (tx *Btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
}
if isubname != "" {
head, rest, err := splitDomainHead(isubname)
head, rest, err := util.SplitDomainHead(isubname)
if err != nil {
return nil, "", err
}
@ -330,7 +350,7 @@ func (tx *Btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
return ncv, subname, nil
}
func (tx *Btx) addAnswersUnderNCValueActual(ncv *ncValue, sn string) (rrs []dns.RR, err error) {
func (tx *btx) addAnswersUnderNCValueActual(ncv *ncValue, sn string) (rrs []dns.RR, err error) {
// A
ips, err := ncv.GetIPs()
if err != nil {
@ -343,7 +363,7 @@ func (tx *Btx) addAnswersUnderNCValueActual(ncv *ncValue, sn string) (rrs []dns.
continue
}
rrs = append(rrs, &dns.A {
Hdr: dns.RR_Header { Name: absname(tx.qname), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 600, },
Hdr: dns.RR_Header { Name: util.Absname(tx.qname), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 600, },
A: pip })
}
@ -359,7 +379,7 @@ func (tx *Btx) addAnswersUnderNCValueActual(ncv *ncValue, sn string) (rrs []dns.
continue
}
rrs = append(rrs, &dns.AAAA {
Hdr: dns.RR_Header { Name: absname(tx.qname), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 600, },
Hdr: dns.RR_Header { Name: util.Absname(tx.qname), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 600, },
AAAA: pip })
}
@ -370,23 +390,35 @@ func (tx *Btx) addAnswersUnderNCValueActual(ncv *ncValue, sn string) (rrs []dns.
}
for _, ns := range nss {
ns = absname(ns)
ns = util.Absname(ns)
rrs = append(rrs, &dns.NS {
Hdr: dns.RR_Header { Name: absname(tx.qname), Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 600, },
Hdr: dns.RR_Header { Name: util.Absname(tx.qname), Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 600, },
Ns: ns })
}
// TODO: TXT
// TXT
txts, err := ncv.GetTXTs()
if err != nil {
return
}
for _, txt := range txts {
rrs = append(rrs, &dns.TXT {
Hdr: dns.RR_Header { Name: util.Absname(tx.qname), Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 600, },
Txt: txt })
}
// TODO: MX
// TODO: SRV
// DS
dss, err := ncv.GetDSs()
if err != nil {
return
}
for i := range dss {
dss[i].Hdr.Name = absname(tx.qname)
dss[i].Hdr.Name = util.Absname(tx.qname)
rrs = append(rrs, &dss[i])
}
@ -413,7 +445,7 @@ func (ncv *ncValue) getArray(a interface{}) (ips []string, err error) {
}
}
} else {
s, ok := ncv.IP.(string)
s, ok := a.(string)
if ok {
ips = []string{s}
} else {
@ -435,6 +467,49 @@ func (ncv *ncValue) GetNSs() (nss []string, err error) {
return ncv.getArray(ncv.NS)
}
func (ncv *ncValue) getArrayTXT(a interface{}) (txts [][]string, err error) {
if a == nil {
return
}
if txta, ok := a.([]interface{}); ok {
// ["...", "..."] or [["...","..."], ["...","..."]]
for _, v := range txta {
if sa, ok := v.([]string); ok {
// [["...", "..."], ["...","..."]]
txts = append(txts, sa)
} else if s, ok := v.(string); ok {
// ["...", "..."]
txts = append(txts, segmentizeTXT(s))
} else {
err = fmt.Errorf("malformed TXT value")
return
}
}
} else {
// "..."
if s, ok := a.(string); ok {
txts = append(txts, segmentizeTXT(s))
} else {
err = fmt.Errorf("malformed TXT value")
}
}
return
}
func (ncv *ncValue) GetTXTs() (txts [][]string, err error) {
return ncv.getArrayTXT(ncv.TXT)
}
func segmentizeTXT(txt string) (a []string) {
for len(txt) > 255 {
a = append(a, txt[0:255])
txt = txt[255:]
}
a = append(a, txt)
return
}
func (ncv *ncValue) GetDSs() (dss []dns.DS, err error) {
for _, ds := range ncv.DS {
//log.Info(" - DS: ", ds)
@ -497,7 +572,7 @@ func (ncv *ncValue) GetDSs() (dss []dns.DS, err error) {
// Do low-level queries against an abstract zone file.
func (b *ncBackend) Lookup(qname string) (rrs []dns.RR, err error) {
btx := &Btx{}
btx := &btx{}
btx.b = b
btx.qname = qname
return btx.Do()

@ -0,0 +1,65 @@
// This package contains extensions to btcjson used by the namecoin package.
// It is not intended for public use.
package extratypes
import "github.com/hlandauf/btcjson"
import "encoding/json"
type NameShowCmd struct {
id interface{}
Name string `json:"name"`
}
func NewNameShowCmd(id interface{}, name string) (*NameShowCmd, error) {
return &NameShowCmd {
id: id,
Name: name,
}, nil
}
func (c *NameShowCmd) Id() interface{} {
return c.id
}
func (c *NameShowCmd) Method() string {
return "name_show"
}
func (c *NameShowCmd) MarshalJSON() ([]byte, error) {
params := []interface{}{
c.Name,
}
raw, err := btcjson.NewRawCmd(c.id, c.Method(), params)
if err != nil {
return nil, err
}
return json.Marshal(raw)
}
func (c *NameShowCmd) UnmarshalJSON(b []byte) error {
// We don't need to implement this as we are only ever the client.
panic("not implemented")
return nil
}
type NameShowReply struct {
Name string `json:"name"`
Value string `json:"value"`
ExpiresIn int `json:"expires_in"`
}
func replyParser(m json.RawMessage) (interface{}, error) {
nsr := &NameShowReply{}
err := json.Unmarshal(m, nsr)
if err != nil {
return nil, err
}
return nsr, nil
}
func init() {
btcjson.RegisterCustomCmd("name_show", nil, replyParser, "name_show <name>")
}

@ -3,8 +3,8 @@ package namecoin
// btcjson had to be modified a bit to get correct error reporting.
import "github.com/hlandauf/btcjson"
import "github.com/hlandau/ncdns/ncerr"
import "github.com/hlandau/ncdns/namecoin/extratypes"
import "encoding/json"
import "sync/atomic"
import "fmt"
@ -15,71 +15,17 @@ func newID() int32 {
return atomic.AddInt32(&idCounter, 1)
}
type NameShowCmd struct {
id interface{}
Name string `json:"name"`
}
func NewNameShowCmd(id interface{}, name string) (*NameShowCmd, error) {
return &NameShowCmd {
id: id,
Name: name,
}, nil
}
func (c *NameShowCmd) Id() interface{} {
return c.id
}
func (c *NameShowCmd) Method() string {
return "name_show"
}
func (c *NameShowCmd) MarshalJSON() ([]byte, error) {
params := []interface{}{
c.Name,
}
raw, err := btcjson.NewRawCmd(c.id, c.Method(), params)
if err != nil {
return nil, err
}
return json.Marshal(raw)
}
func (c *NameShowCmd) UnmarshalJSON(b []byte) error {
// We don't need to implement this as we are only ever the client.
panic("not implemented")
return nil
}
type NameShowReply struct {
Name string `json:"name"`
Value string `json:"value"`
ExpiresIn int `json:"expires_in"`
}
func replyParser(m json.RawMessage) (interface{}, error) {
nsr := &NameShowReply{}
err := json.Unmarshal(m, nsr)
if err != nil {
return nil, err
}
return nsr, nil
}
func init() {
btcjson.RegisterCustomCmd("name_show", nil, replyParser, "name_show <name>")
}
// Used to query a Namecoin JSON-RPC interface. Initialize the struct with a
// username, password, and address (hostname:port).
type NamecoinConn struct {
Username string
Password string
Server string
}
// Query the Namecoin daemon for a Namecoin domain (e.g. d/example).
// If the domain exists, returns the value stored in Namecoin, which should be JSON.
// Note that this will return domain data even if the domain is expired.
func (nc *NamecoinConn) Query(name string) (v string, err error) {
if name == "d/badger2" {
v = `{"ns":["ns1.badger.bit","ns2.badger.bit"],"map":{"ns1":{"ip":["1.2.3.4"],"ip6":["::beef:1"]},"ns2":{"ip":["2.3.4.5"],"ip6":["::beef:2"]}},"ds":[[12345,8,2,"lu6y/9mwDNRpTngni179qwqARGVntp9jTaB48NkPAbo="]]}`
@ -98,7 +44,7 @@ func (nc *NamecoinConn) Query(name string) (v string, err error) {
return
}
cmd, err := NewNameShowCmd(newID(), name)
cmd, err := extratypes.NewNameShowCmd(newID(), name)
if err != nil {
//log.Info("NC NEWCMD ", err)
return "", err
@ -122,7 +68,7 @@ func (nc *NamecoinConn) Query(name string) (v string, err error) {
return "", fmt.Errorf("got nil result")
}
if nsr, ok := r.Result.(*NameShowReply); ok {
if nsr, ok := r.Result.(*extratypes.NameShowReply); ok {
//log.Info("NC OK")
return nsr.Value, nil
} else {

@ -9,6 +9,9 @@ import "strings"
import "sort"
import "github.com/hlandau/degoutils/config"
import "github.com/hlandau/ncdns/ncerr"
import "github.com/hlandau/ncdns/abstract"
import "github.com/hlandau/ncdns/backend"
import "github.com/hlandau/ncdns/util"
// A Go daemon to serve Namecoin domain records via DNS.
// This daemon is intended to be used in one of the following situations:
@ -101,7 +104,16 @@ func (s *Server) Run() {
log.Fatale(err)
}
s.b, err = NewNCBackend(s)
bcfg := &backend.Config {
RPCUsername: s.cfg.NamecoinRPCUsername,
RPCPassword: s.cfg.NamecoinRPCPassword,
RPCAddress: s.cfg.NamecoinRPCAddress,
CacheMaxEntries: s.cfg.CacheMaxEntries,
SelfName: s.cfg.SelfName,
SelfIP: s.cfg.SelfIP,
}
s.b, err = backend.New(bcfg)
log.Fatale(err)
// run
@ -129,7 +141,7 @@ type Server struct {
zsk *dns.DNSKEY
zskPrivate dns.PrivateKey
cfg ServerConfig
b Backend
b abstract.Backend
}
type ServerConfig struct {
@ -353,7 +365,7 @@ A:
if firstNSAtLen < 0 {
firstNSAtLen = len(n)
tx.delegationPoint = absname(n)
tx.delegationPoint = util.Absname(n)
log.Info("DELEGATION POINT: ", tx.delegationPoint)
if n == norig {
@ -559,7 +571,7 @@ func (tx *Tx) addNSEC3RRActual(name string, tset map[uint16]struct{}) error {
nsr1nn := stepName(nsr1n)
nsr1 := &dns.NSEC3 {
Hdr: dns.RR_Header {
Name: absname(nsr1n + "." + tx.soa.Hdr.Name),
Name: util.Absname(nsr1n + "." + tx.soa.Hdr.Name),
Rrtype: dns.TypeNSEC3,
Class: dns.ClassINET,
Ttl: 600,

@ -1,35 +1,57 @@
// Error types for processing DNS requests.
package ncerr
import "github.com/miekg/dns"
import "fmt"
// An Error interface which allows an associated rcode to be queried.
type Error interface {
error
// Returns the rcode which this error should be represented as in the DNS protocol.
Rcode() int
}
type Rerr struct {
type rerr struct {
error
e error
rcode int
}
func (re *Rerr) Error() string {
func (re *rerr) Error() string {
return re.e.Error()
}
func (re *Rerr) Rcode() int {
func (re *rerr) Rcode() int {
return re.rcode
}
func rerrorf(rcode int, fmts string, args ...interface{}) Error {
re := &Rerr{}
// Used to generate an Error which has a particular rcode. Otherwise like fmt.Errorf.
func Rerrorf(rcode int, fmts string, args ...interface{}) Error {
re := &rerr{}
re.e = fmt.Errorf(fmts, args...)
re.rcode = rcode
return re
}
// Standard errors.
var ErrNoSuchDomain = rerrorf(dns.RcodeNameError, "no such domain")
var ErrNotInZone = rerrorf(dns.RcodeRefused, "domain not in zone")
var ErrNoResults = rerrorf(0, "no results")
// Represents NXDOMAIN. Used when the name requested lies within a zone for
// which this server is authoritative, but does not exist.
//
// Note that a name is considered to exist if there exist any records of any
// type at a name, even if those records were not requested or sent. A name is
// also considered to exist if there are any names under it.
//
// In other words, b.c should return NOERROR even if it has no records of any
// type if there is a record at a.b.c, or so on.
var ErrNoSuchDomain = Rerrorf(dns.RcodeNameError, "no such domain")
// Represents REFUSED, which we use when a request is received for a zone for
// which the server is not authoritative.
var ErrNotInZone = Rerrorf(dns.RcodeRefused, "domain not in zone")
// Represents NOERROR. This error is used when NXDOMAIN is not an appropriate
// response code, but no results were returned. (DNS also uses NOERROR when results
// are returned, but we return nil in that case.)
var ErrNoResults = Rerrorf(0, "no results")

@ -1,34 +1,10 @@
package main
import "encoding/base32"
import "fmt"
import "strings"
import "github.com/miekg/dns"
import "github.com/hlandau/degoutils/log"
import "time"
// miekg/dns demands a superflous trailing dot, this makes sure it is correctly appended.
func absname(n string) string {
if n == "" {
return "."
}
if n[len(n)-1] != '.' {
return n + "."
}
return n
}
// Split a domain name a.b.c.d.e into parts a (the head) and b.c.d.e (the rest).
func splitDomainHead(name string) (head string, rest string, err error) {
parts := strings.Split(name, ".")
head = parts[len(parts)-1]
if len(parts) >= 2 {
rest = strings.Join(parts[0:len(parts)-1], ".")
}
return
}
import "github.com/hlandau/ncdns/util"
// Determines if a transaction should be considered to have the given query type.
// Returns true iff the query type was qtype or ANY.
@ -121,7 +97,7 @@ func (tx *Tx) signRRs(rra []dns.RR, useKSK bool) (dns.RR, error) {
Algorithm: dns.RSASHA256,
Expiration: uint32(now.Add(exp).Unix()),
Inception: uint32(now.Add(time.Duration(-10)*time.Minute).Unix()),
SignerName: absname(tx.soa.Hdr.Name),
SignerName: util.Absname(tx.soa.Hdr.Name),
}
pk := tx.s.zskPrivate
if useKSK {

@ -0,0 +1,26 @@
package util
import "strings"
// miekg/dns demands a superflous trailing dot, this makes sure it is correctly appended.
func Absname(n string) string {
if n == "" {
return "."
}
if n[len(n)-1] != '.' {
return n + "."
}
return n
}
// Split a domain name a.b.c.d.e into parts a (the head) and b.c.d.e (the rest).
func SplitDomainHead(name string) (head string, rest string, err error) {
parts := strings.Split(name, ".")
head = parts[len(parts)-1]
if len(parts) >= 2 {
rest = strings.Join(parts[0:len(parts)-1], ".")
}
return
}
Loading…
Cancel
Save