From 3be560038332a4cbeaecfa5efafcc377ef729946 Mon Sep 17 00:00:00 2001 From: Alvaro Saurin Date: Tue, 10 Feb 2015 10:37:17 +0100 Subject: [PATCH] zettio/weave#362 - reorganize the DNS server code, so it looks like the mDNS server, with a proper class with Start() and so... Listen on TCP on port 53 by default --- nameserver/server.go | 131 ++++++++++++++++++++++++------------------- nameserver/util.go | 17 ++++++ weavedns/main.go | 13 ++++- 3 files changed, 100 insertions(+), 61 deletions(-) create mode 100644 nameserver/util.go diff --git a/nameserver/server.go b/nameserver/server.go index 3975053c..dc303b40 100644 --- a/nameserver/server.go +++ b/nameserver/server.go @@ -12,18 +12,6 @@ const ( UDPBufSize = 4096 // bigger than the default 512 ) -func checkFatal(e error) { - if e != nil { - Error.Fatal(e) - } -} - -func checkWarn(e error) { - if e != nil { - Warning.Println(e) - } -} - func makeDNSFailResponse(r *dns.Msg) *dns.Msg { m := new(dns.Msg) m.SetReply(r) @@ -32,7 +20,72 @@ func makeDNSFailResponse(r *dns.Msg) *dns.Msg { return m } -func queryHandler(lookups []Lookup) dns.HandlerFunc { +type DNSServer struct { + config *dns.ClientConfig + zone Zone + iface *net.Interface + udpPort int + tcpPort int +} + +// Creates a new DNS server +func NewDNSServer(zone Zone, iface *net.Interface, udpPort int, tcpPort int) (*DNSServer, error) { + config, err := dns.ClientConfigFromFile("/etc/resolv.conf") + if err != nil { + return nil, err + } + + return &DNSServer{ + config: config, + zone: zone, + iface: iface, + udpPort: udpPort, + tcpPort: tcpPort, + }, nil +} + +// Start the DNS server +func (s *DNSServer) Start() error { + mdnsClient, err := NewMDNSClient() + checkFatal(err) + + ifaceName := "default interface" + if s.iface != nil { + ifaceName = s.iface.Name + } + Info.Printf("Using mDNS on %s", ifaceName) + err = mdnsClient.Start(s.iface) + checkFatal(err) + + LocalServeMux := dns.NewServeMux() + LocalServeMux.HandleFunc(LOCAL_DOMAIN, s.queryHandler([]Lookup{s.zone, mdnsClient})) + LocalServeMux.HandleFunc(RDNS_DOMAIN, s.rdnsHandler([]Lookup{s.zone, mdnsClient})) + LocalServeMux.HandleFunc(".", s.notUsHandler()) + + mdnsServer, err := NewMDNSServer(s.zone) + checkFatal(err) + + err = mdnsServer.Start(s.iface) + checkFatal(err) + + go func() { + udpAddress := fmt.Sprintf(":%d", s.udpPort) + Info.Printf("Listening for DNS on %s (UDP)", udpAddress) + err = dns.ListenAndServe(udpAddress, "udp", LocalServeMux) + checkFatal(err) + }() + + go func() { + tcpAddress := fmt.Sprintf(":%d", s.tcpPort) + Info.Printf("Listening for DNS on %s (TCP)", tcpAddress) + err = dns.ListenAndServe(tcpAddress, "tcp", LocalServeMux) + checkFatal(err) + }() + + return nil +} + +func (s *DNSServer) queryHandler(lookups []Lookup) dns.HandlerFunc { return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] Debug.Printf("Query: %+v", q) @@ -51,8 +104,8 @@ func queryHandler(lookups []Lookup) dns.HandlerFunc { } } -func rdnsHandler(config *dns.ClientConfig, lookups []Lookup) dns.HandlerFunc { - fallback := notUsHandler(config) +func (s *DNSServer) rdnsHandler(lookups []Lookup) dns.HandlerFunc { + fallback := s.notUsHandler() return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] Debug.Printf("Reverse query: %+v", q) @@ -72,17 +125,16 @@ func rdnsHandler(config *dns.ClientConfig, lookups []Lookup) dns.HandlerFunc { } } -/* When we receive a request for a name outside of our '.weave.local.' - domain, ask the configured DNS server as a fallback. -*/ -func notUsHandler(config *dns.ClientConfig) dns.HandlerFunc { +// When we receive a request for a name outside of our '.weave.local.' +// domain, ask the configured DNS server as a fallback. +func (s *DNSServer) notUsHandler() dns.HandlerFunc { dnsClient := new(dns.Client) dnsClient.UDPSize = UDPBufSize return func(w dns.ResponseWriter, r *dns.Msg) { q := r.Question[0] Debug.Printf("[dns msgid %d] Fallback query: %+v", r.MsgHdr.Id, q) - for _, server := range config.Servers { - reply, _, err := dnsClient.Exchange(r, fmt.Sprintf("%s:%s", server, config.Port)) + for _, server := range s.config.Servers { + reply, _, err := dnsClient.Exchange(r, fmt.Sprintf("%s:%s", server, s.config.Port)) if err != nil { Debug.Printf("[dns msgid %d] Network error trying %s (%s)", r.MsgHdr.Id, server, err) @@ -103,40 +155,3 @@ func notUsHandler(config *dns.ClientConfig) dns.HandlerFunc { w.WriteMsg(makeDNSFailResponse(r)) } } - -func StartServer(zone Zone, iface *net.Interface, dnsPort int, wait int) error { - config, err := dns.ClientConfigFromFile("/etc/resolv.conf") - checkFatal(err) - return startServerWithConfig(config, zone, iface, dnsPort, wait) -} - -func startServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, dnsPort int, wait int) error { - mdnsClient, err := NewMDNSClient() - checkFatal(err) - - ifaceName := "default interface" - if iface != nil { - ifaceName = iface.Name - } - Info.Printf("Using mDNS on %s", ifaceName) - err = mdnsClient.Start(iface) - checkFatal(err) - - LocalServeMux := dns.NewServeMux() - LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler([]Lookup{zone, mdnsClient})) - LocalServeMux.HandleFunc(RDNS_DOMAIN, rdnsHandler(config, []Lookup{zone, mdnsClient})) - LocalServeMux.HandleFunc(".", notUsHandler(config)) - - mdnsServer, err := NewMDNSServer(zone) - checkFatal(err) - - err = mdnsServer.Start(iface) - checkFatal(err) - - address := fmt.Sprintf(":%d", dnsPort) - Info.Printf("Listening for DNS on %s", address) - err = dns.ListenAndServe(address, "udp", LocalServeMux) - checkFatal(err) - - return nil -} diff --git a/nameserver/util.go b/nameserver/util.go new file mode 100644 index 00000000..9e25dfc2 --- /dev/null +++ b/nameserver/util.go @@ -0,0 +1,17 @@ +package nameserver + +import ( + . "github.com/zettio/weave/common" +) + +func checkFatal(e error) { + if e != nil { + Error.Fatal(e) + } +} + +func checkWarn(e error) { + if e != nil { + Warning.Println(e) + } +} diff --git a/weavedns/main.go b/weavedns/main.go index 2898b96e..d5053686 100644 --- a/weavedns/main.go +++ b/weavedns/main.go @@ -18,7 +18,8 @@ func main() { justVersion bool ifaceName string apiPath string - dnsPort int + udpPort int + tcpPort int httpPort int wait int watch bool @@ -29,7 +30,8 @@ func main() { flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast") flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket") flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up") - flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to dns requests") + flag.IntVar(&udpPort, "udpport", 53, "UDP port to listen to DNS requests") + flag.IntVar(&tcpPort, "tcpport", 53, "TCP port to listen to DNS requests") flag.IntVar(&httpPort, "httpport", 6785, "port to listen to HTTP requests") flag.BoolVar(&watch, "watch", true, "watch the docker socket for container events") flag.BoolVar(&debug, "debug", false, "output debugging info to stderr") @@ -64,7 +66,12 @@ func main() { } go weavedns.ListenHttp(weavedns.LOCAL_DOMAIN, zone, httpPort) - err := weavedns.StartServer(zone, iface, dnsPort, wait) + srv, err := weavedns.NewDNSServer(zone, iface, udpPort, tcpPort) + if err != nil { + Error.Fatal("Failed to start server", err) + } + + srv.Start() if err != nil { Error.Fatal("Failed to start server", err) }