101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"github.com/miekg/dns"
|
|
"github.com/zettio/weavedns"
|
|
"log"
|
|
"net"
|
|
)
|
|
|
|
var zone = new(weavedns.ZoneDb)
|
|
|
|
func makeDNSReply(r *dns.Msg, name string, addr net.IP) *dns.Msg {
|
|
m := new(dns.Msg)
|
|
m.SetReply(r)
|
|
hdr := dns.RR_Header{Name: name, Rrtype: dns.TypeA,
|
|
Class: dns.ClassINET, Ttl: 3600}
|
|
a := &dns.A{hdr, addr}
|
|
m.Answer = append(m.Answer, a)
|
|
return m
|
|
}
|
|
|
|
var mdnsClient *weavedns.MDNSClient
|
|
|
|
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.HandleResponse(r)
|
|
} else if len(r.Question) > 0 {
|
|
q := r.Question[0]
|
|
ip, err := zone.MatchLocal(q.Name)
|
|
if err == nil {
|
|
m := makeDNSReply(r, q.Name, net.ParseIP(ip))
|
|
mdnsClient.SendResponse(m)
|
|
} else if mdnsClient.IsInflightQuery(r) {
|
|
// ignore this - it's our own query received via multicast
|
|
} else {
|
|
log.Printf("Failed MDNS lookup for %s", q.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleLocal(w dns.ResponseWriter, r *dns.Msg) {
|
|
log.Printf("Received message: %s", r)
|
|
q := r.Question[0]
|
|
ip, err := zone.MatchLocal(q.Name)
|
|
if err == nil {
|
|
m := makeDNSReply(r, q.Name, net.ParseIP(ip))
|
|
w.WriteMsg(m)
|
|
} else {
|
|
log.Printf("Failed lookup for %s", q.Name)
|
|
// We don't know the answer; see if someone else does
|
|
channel := make(chan *weavedns.ResponseA, 4)
|
|
go func() {
|
|
for resp := range channel {
|
|
log.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
|
|
m := makeDNSReply(r, resp.Name, resp.Addr)
|
|
w.WriteMsg(m)
|
|
}
|
|
// FIXME: need to add a time-out either here or in mdnsClient
|
|
}()
|
|
mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
|
|
}
|
|
return
|
|
}
|
|
|
|
func main() {
|
|
var (
|
|
dnsPort int
|
|
)
|
|
|
|
flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to dns requests (defaults to 53)")
|
|
flag.Parse()
|
|
|
|
LocalServeMux := dns.NewServeMux()
|
|
LocalServeMux.HandleFunc("local", handleLocal)
|
|
go weavedns.ListenHttp(zone)
|
|
|
|
MDNSServeMux := dns.NewServeMux()
|
|
MDNSServeMux.HandleFunc("local", handleMDNS)
|
|
|
|
conn, err := weavedns.LinkLocalMulticastListener()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
mdnsClient, err = weavedns.NewMDNSClient()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
go dns.ActivateAndServe(nil, conn, MDNSServeMux)
|
|
|
|
address := fmt.Sprintf(":%d", dnsPort)
|
|
err = dns.ListenAndServe(address, "udp", LocalServeMux)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|