Implement zone lookup with MDNSCLient
This separates Zone into the DB ops and the Lookup ops, and implements the latter for MDNSClient so it can be used just like the zonedb. A notable change is that Lookup methods only ever return one result, while MDNSClient.SendQuery could in theory return multiple results (though it wouldn't, because no server would supply more than one result in a response, and it stops waiting after getting one response ..). ReverseLookupLocal is implemented even though no MDNSServer will answer at present (hence no test yet). Lastly, the handler (creating) functions can now be given a list of Lookup implementations to try in order.
This commit is contained in:
1 parent
3866bd5e63
commit
bf752d2d1f
4 files changed
+85
-41
No files matched your search
@@ -152,3 +152,18 @@ outerloop:
|
||||
t.Fatal("Unexpected result for", successTestName, context1.receivedAddr, context2.receivedAddr, context1.receivedCount, context2.receivedCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAsLookup(t *testing.T) {
|
||||
mdnsClient, server, _ := setup(t)
|
||||
defer mdnsClient.Shutdown()
|
||||
defer server.Shutdown()
|
||||
|
||||
ip, err := mdnsClient.LookupLocal(successTestName)
|
||||
wt.AssertNoErr(t, err)
|
||||
if !testAddr.Equal(ip) {
|
||||
t.Fatalf("Returned address incorrect %s", ip)
|
||||
}
|
||||
|
||||
ip, err = mdnsClient.LookupLocal("foo.example.com.")
|
||||
wt.AssertErrorType(t, err, (*LookupError)(nil), "unknown hostname")
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package nameserver
|
||||
|
||||
import (
|
||||
"github.com/miekg/dns"
|
||||
. "github.com/zettio/weave/common"
|
||||
"net"
|
||||
)
|
||||
|
||||
func mdnsLookup(client *MDNSClient, name string, qtype uint16) (*ResponseA, error) {
|
||||
channel := make(chan *ResponseA)
|
||||
client.SendQuery(name, qtype, channel)
|
||||
for resp := range channel {
|
||||
Debug.Printf("Got response name %s addr %s", resp.Name, resp.Addr)
|
||||
if err := resp.Err; err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
return nil, LookupError(name)
|
||||
}
|
||||
|
||||
func (client *MDNSClient) LookupLocal(name string) (net.IP, error) {
|
||||
if r, e := mdnsLookup(client, name, dns.TypeA); r != nil {
|
||||
return r.Addr, nil
|
||||
} else {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
|
||||
func (client *MDNSClient) ReverseLookupLocal(inaddr string) (string, error) {
|
||||
if r, e := mdnsLookup(client, inaddr, dns.TypePTR); r != nil {
|
||||
return r.Name, nil
|
||||
} else {
|
||||
return "", e
|
||||
}
|
||||
}
|
||||
+27
-39
@@ -31,57 +31,45 @@ func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
|
||||
return m
|
||||
}
|
||||
|
||||
func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
|
||||
func queryHandler(lookups []Lookup) dns.HandlerFunc {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
q := r.Question[0]
|
||||
Debug.Printf("Local query: %+v", q)
|
||||
Debug.Printf("Query: %+v", q)
|
||||
if q.Qtype == dns.TypeA {
|
||||
if ip, err := zone.LookupLocal(q.Name); err == nil {
|
||||
m := makeAddressReply(r, &q, []net.IP{ip})
|
||||
w.WriteMsg(m)
|
||||
} else {
|
||||
Debug.Printf("Failed lookup for %s; sending mDNS query", q.Name)
|
||||
// We don't know the answer; see if someone else does
|
||||
channel := make(chan *ResponseA)
|
||||
replies := make([]net.IP, 0)
|
||||
go func() {
|
||||
for resp := range channel {
|
||||
Debug.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
|
||||
replies = append(replies, resp.Addr)
|
||||
}
|
||||
var responseMsg *dns.Msg
|
||||
if len(replies) > 0 {
|
||||
responseMsg = makeAddressReply(r, &q, replies)
|
||||
} else {
|
||||
responseMsg = makeDNSFailResponse(r)
|
||||
}
|
||||
w.WriteMsg(responseMsg)
|
||||
}()
|
||||
mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
|
||||
for _, lookup := range lookups {
|
||||
if ip, err := lookup.LookupLocal(q.Name); err == nil {
|
||||
m := makeAddressReply(r, &q, []net.IP{ip})
|
||||
w.WriteMsg(m)
|
||||
return
|
||||
}
|
||||
}
|
||||
Debug.Printf("Query failed for %s", q.Name)
|
||||
w.WriteMsg(makeDNSFailResponse(r))
|
||||
} else {
|
||||
Warning.Printf("Local query not handled: %+v", q)
|
||||
m := makeDNSFailResponse(r)
|
||||
w.WriteMsg(m)
|
||||
Warning.Printf("Query not handled: %+v", q)
|
||||
w.WriteMsg(makeDNSFailResponse(r))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func rdnsHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
|
||||
func rdnsHandler(lookups []Lookup) dns.HandlerFunc {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
q := r.Question[0]
|
||||
Debug.Printf("Local rdns query: %+v", q)
|
||||
Debug.Printf("Reverse query: %+v", q)
|
||||
if q.Qtype == dns.TypePTR {
|
||||
if name, err := zone.ReverseLookupLocal(q.Name); err == nil {
|
||||
Debug.Printf("Found name: %s", name)
|
||||
m := makePTRReply(r, &q, []string{name})
|
||||
w.WriteMsg(m)
|
||||
} else {
|
||||
Debug.Printf("Failed lookup for %s; sending mDNS query", q.Name)
|
||||
// We don't know the answer; see if someone else does
|
||||
// TODO
|
||||
for _, lookup := range lookups {
|
||||
if name, err := lookup.ReverseLookupLocal(q.Name); err == nil {
|
||||
m := makePTRReply(r, &q, []string{name})
|
||||
w.WriteMsg(m)
|
||||
return
|
||||
}
|
||||
}
|
||||
Debug.Printf("Reverse query failed for %s", q.Name)
|
||||
w.WriteMsg(makeDNSFailResponse(r))
|
||||
} else {
|
||||
Warning.Printf("Reverse query not handled: %+v", q)
|
||||
w.WriteMsg(makeDNSFailResponse(r))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,8 +113,8 @@ func StartServer(zone Zone, iface *net.Interface, dnsPort int, httpPort int, wai
|
||||
checkFatal(err)
|
||||
|
||||
LocalServeMux := dns.NewServeMux()
|
||||
LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler(zone, mdnsClient))
|
||||
LocalServeMux.HandleFunc(RDNS_DOMAIN, rdnsHandler(zone, mdnsClient))
|
||||
LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler([]Lookup{zone, mdnsClient}))
|
||||
LocalServeMux.HandleFunc(RDNS_DOMAIN, rdnsHandler([]Lookup{zone, mdnsClient}))
|
||||
LocalServeMux.HandleFunc(".", notUsHandler())
|
||||
|
||||
mdnsServer, err := NewMDNSServer(zone)
|
||||
|
||||
+6
-2
@@ -14,12 +14,16 @@ const (
|
||||
// +1 to also exclude a dot
|
||||
var rdnsDomainLen = len(RDNS_DOMAIN) + 1
|
||||
|
||||
type Lookup interface {
|
||||
LookupLocal(name string) (net.IP, error)
|
||||
ReverseLookupLocal(inaddr string) (string, error)
|
||||
}
|
||||
|
||||
type Zone interface {
|
||||
AddRecord(ident string, name string, ip net.IP) error
|
||||
DeleteRecord(ident string, ip net.IP) error
|
||||
DeleteRecordsFor(ident string) error
|
||||
LookupLocal(name string) (net.IP, error)
|
||||
ReverseLookupLocal(inaddr string) (string, error)
|
||||
Lookup
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
|
||||
Reference in new issue
Block a user