diff --git a/main.go b/main.go index d954dee5..e764517a 100644 --- a/main.go +++ b/main.go @@ -26,20 +26,21 @@ func makeDNSReply(r *dns.Msg, name string, addr net.IP) *dns.Msg { return m } -var mdnsClient *weavedns.MDNSClient +var ( + mdnsClient *weavedns.MDNSClient + mdnsServer *weavedns.MDNSServer +) func handleMDNS(w dns.ResponseWriter, r *dns.Msg) { - // Here we have to handle both requests incoming, responses to queries - // we sent out, and responses to queries that other nodes sent - if len(r.Answer) > 0 { - mdnsClient.ResponseCallback(r) - } else if len(r.Question) > 0 { + // Ignore answers to other questions + if len(r.Answer) == 0 && len(r.Question) > 0 { q := r.Question[0] ip, err := zone.MatchLocal(q.Name) if err == nil { m := makeDNSReply(r, q.Name, ip) - mdnsClient.SendResponse(m) + mdnsServer.SendResponse(m) } else if mdnsClient.IsInflightQuery(r) { + log.Println("Inflight Query", w.RemoteAddr(), w.LocalAddr()) // ignore this - it's our own query received via multicast } else { log.Printf("Failed MDNS lookup for %s", q.Name) @@ -135,7 +136,14 @@ func main() { } else { log.Printf("Using mDNS on %s", ifaceName) } - mdnsClient.Start() + err = mdnsClient.Start(iface) + if err != nil { + log.Fatal(err) + } + mdnsServer, err = weavedns.NewMDNSServer() + if err != nil { + log.Fatal(err) + } go dns.ActivateAndServe(nil, conn, MDNSServeMux) diff --git a/server/mdns_client.go b/server/mdns_client.go index 1164dcb6..cc541c11 100644 --- a/server/mdns_client.go +++ b/server/mdns_client.go @@ -59,7 +59,6 @@ type mDNSQueryInfo struct { func NewMDNSClient() (*MDNSClient, error) { conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) if err != nil { - log.Println(err) return nil, err } retval := &MDNSClient{ @@ -69,10 +68,27 @@ func NewMDNSClient() (*MDNSClient, error) { return retval, nil } -func (c *MDNSClient) Start() { +func (c *MDNSClient) Start(ifi *net.Interface) error { + multicast, err := LinkLocalMulticastListener(ifi) + if err != nil { + return err + } + + handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) { + //log.Println("client received:", r) + // Only handle responses here + if len(r.Answer) > 0 { + c.ResponseCallback(r) + } + } + + go dns.ActivateAndServe(nil, multicast, dns.HandlerFunc(handleMDNS)) + queryChan := make(chan *MDNSInteraction, 4) c.queryChan = queryChan go c.queryLoop(queryChan) + + return nil } func LinkLocalMulticastListener(ifi *net.Interface) (net.PacketConn, error) { @@ -80,15 +96,6 @@ func LinkLocalMulticastListener(ifi *net.Interface) (net.PacketConn, error) { return conn, err } -func (c *MDNSClient) SendResponse(m *dns.Msg) error { - buf, err := m.Pack() - if err != nil { - return err - } - _, err = c.conn.WriteTo(buf, c.addr) - return err -} - // ACTOR client API const ( diff --git a/server/mdns_client_test.go b/server/mdns_client_test.go index 7201152b..a3956002 100644 --- a/server/mdns_client_test.go +++ b/server/mdns_client_test.go @@ -10,11 +10,6 @@ import ( var ( test_addr = net.ParseIP("9.8.7.6") - sendconn *net.UDPConn - sendAddr = &net.UDPAddr{ - IP: net.ParseIP(ipv4mdns), - Port: 0, - } ) func minimalServer(w dns.ResponseWriter, req *dns.Msg) { @@ -39,7 +34,13 @@ func minimalServer(w dns.ResponseWriter, req *dns.Msg) { log.Fatal("Nil buffer") } //log.Println("minimalServer sending:", buf) - _, err = sendconn.WriteTo(buf, ipv4Addr) + // This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work + sendconn, err := net.DialUDP("udp", nil, ipv4Addr) + if err != nil { + log.Fatal(err) + } + _, err = sendconn.Write(buf) + sendconn.Close() if err != nil { log.Fatal(err) } @@ -62,24 +63,7 @@ func TestSimpleQuery(t *testing.T) { if err != nil { t.Fatal(err) } - mdnsClient.Start() - mux := dns.NewServeMux() - - handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) { - //log.Println("test received:", r) - // Only handle responses here - if len(r.Answer) > 0 { - mdnsClient.ResponseCallback(r) - } - } - - mux.HandleFunc("weave", handleMDNS) - multicast, err := net.ListenMulticastUDP("udp", nil, ipv4Addr) - if err != nil { - t.Fatal(err) - } - go dns.ActivateAndServe(nil, multicast, mux) - sendconn, err = net.ListenUDP("udp", sendAddr) + err = mdnsClient.Start(nil) if err != nil { t.Fatal(err) } @@ -98,9 +82,10 @@ func TestSimpleQuery(t *testing.T) { received_addr = resp.Addr } }() + mdnsClient.SendQuery("test.weave.", dns.TypeA, channel) - time.Sleep(1 * time.Second) + time.Sleep(200 * time.Millisecond) if !received_addr.Equal(test_addr) { t.Log("Unexpected result for test.weave", received_addr) diff --git a/server/mdns_server.go b/server/mdns_server.go new file mode 100644 index 00000000..89aaa340 --- /dev/null +++ b/server/mdns_server.go @@ -0,0 +1,30 @@ +package weavedns + +import ( + "github.com/miekg/dns" + "net" +) + +type MDNSServer struct { + sendconn *net.UDPConn +} + +func NewMDNSServer() (*MDNSServer, error) { + //log.Println("minimalServer sending:", buf) + // This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work + sendconn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) + if err != nil { + return nil, err + } + retval := &MDNSServer{sendconn: sendconn} + return retval, nil +} + +func (s *MDNSServer) SendResponse(m *dns.Msg) error { + buf, err := m.Pack() + if err != nil { + return err + } + _, err = s.sendconn.WriteTo(buf, ipv4Addr) + return err +}