@@ -91,12 +91,15 @@ func (s *MDNSServer) makeHandler(qtype uint16, lookup LookupFunc) dns.HandlerFun
 			q := &r.Question[0]
 			if q.Qtype == qtype {
 				if m := lookup(s.zone, r, q); m != nil {
-					Debug.Printf("Found local answer to mDNS query %s", q.Name)
+					Debug.Printf("[mdns msgid %d] Found local answer to mDNS query %s",
+						r.MsgHdr.Id, q.Name)
 					if err := s.sendResponse(m); err != nil {
-						Warning.Printf("Error writing to %s", s.sendconn)
+						Warning.Printf("[mdns msgid %d] Error writing to %s",
+							r.MsgHdr.Id, s.sendconn)
 					}
 				} else {
-					Debug.Printf("No local answer for mDNS query %s", q.Name)
+					Debug.Printf("[mdns msgid %d] No local answer for mDNS query %s",
+						r.MsgHdr.Id, q.Name)
 				}
 			}
 		}
package nameserver

import (
	"github.com/miekg/dns"
	. "github.com/zettio/weave/common"
	"net"
)

type MDNSServer struct {
	localAddrs []net.Addr
	sendconn   *net.UDPConn
	zone       Zone
}

func NewMDNSServer(zone Zone) (*MDNSServer, error) {
	// 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
	}
	return &MDNSServer{sendconn: sendconn, zone: zone}, nil
}

// Return true if testaddr is a UDP address with IP matching my local i/f
func (s *MDNSServer) addrIsLocal(testaddr net.Addr) bool {
	if udpaddr, ok := testaddr.(*net.UDPAddr); ok {
		for _, localaddr := range s.localAddrs {
			if ipnetlocal, ok := localaddr.(*net.IPNet); ok {
				if ipnetlocal.IP.Equal(udpaddr.IP) {
					return true
				}
			}
		}
	}
	return false
}

func (s *MDNSServer) Start(ifi *net.Interface) error {
	conn, err := LinkLocalMulticastListener(ifi)
	if err != nil {
		return err
	}

	if ifi == nil {
		s.localAddrs, err = net.InterfaceAddrs()
	} else {
		s.localAddrs, err = ifi.Addrs()
	}
	if err != nil {
		return err
	}

	handleLocal := s.makeHandler(dns.TypeA,
		func(zone Lookup, r *dns.Msg, q *dns.Question) *dns.Msg {
			if ip, err := zone.LookupLocal(q.Name); err == nil {
				return makeAddressReply(r, q, []net.IP{ip})
			} else {
				return nil
			}
		})

	handleReverse := s.makeHandler(dns.TypePTR,
		func(zone Lookup, r *dns.Msg, q *dns.Question) *dns.Msg {
			if name, err := zone.ReverseLookupLocal(q.Name); err == nil {
				return makePTRReply(r, q, []string{name})
			} else {
				return nil
			}
		})

	mux := dns.NewServeMux()
	mux.HandleFunc(LOCAL_DOMAIN, handleLocal)
	mux.HandleFunc(RDNS_DOMAIN, handleReverse)

	go dns.ActivateAndServe(nil, conn, mux)
	return err
}

type LookupFunc func(Lookup, *dns.Msg, *dns.Question) *dns.Msg

func (s *MDNSServer) makeHandler(qtype uint16, lookup LookupFunc) dns.HandlerFunc {
	return func(_ dns.ResponseWriter, r *dns.Msg) {
		// Handle only questions, ignore answers. We might also ignore
		// questions that arise locally (i.e., that come from an IP we
		// think is local), but in the interest of avoiding
		// complication, and easier testing, this is elided on the
		// assumption that the client wouldn't ask if it already knew
		// the answer, and if it does ask, it'll be happy to get an
		// answer.
		if len(r.Answer) == 0 && len(r.Question) > 0 {
			q := &r.Question[0]
			if q.Qtype == qtype {
				if m := lookup(s.zone, r, q); m != nil {
					Debug.Printf("Found local answer to mDNS query %s", q.Name)
					if err := s.sendResponse(m); err != nil {
						Warning.Printf("Error writing to %s", s.sendconn)
					}
				} else {
					Debug.Printf("No local answer for mDNS query %s", q.Name)
				}
			}
		}
	}
}

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
}

`go vet` says: arg s.sendconn for printf verb %s of wrong type: *net.UDPConn (although this seems to have been what it did before)