From a8a4397315d36d8cd82402dcf68123b609f95c94 Mon Sep 17 00:00:00 2001 From: richtr Date: Thu, 11 Sep 2014 14:16:20 +0200 Subject: [PATCH] General updates to DNS SRV handling and decreased reliance on IP addressing (use FQDNs where we can) --- client.go | 16 +++++++++++----- zone.go | 56 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/client.go b/client.go index d8e67ea..21c003d 100644 --- a/client.go +++ b/client.go @@ -15,17 +15,21 @@ import ( // ServiceEntry is returned after we query for a service type ServiceEntry struct { Name string - Addr net.IP + Host string + AddrV4 net.IP + AddrV6 net.IP Port int Info string + Addr net.IP // @Deprecated + hasTXT bool sent bool } // complete is used to check if we have all the info we need func (s *ServiceEntry) complete() bool { - return s.Addr != nil && s.Port != 0 && s.hasTXT + return (s.AddrV4 != nil || s.AddrV6 != nil || s.Addr != nil) && s.Port != 0 && s.hasTXT } // QueryParam is used to customize how a Lookup is performed @@ -195,7 +199,7 @@ func (c *client) query(params *QueryParam) error { // Get the port inp = ensureName(inprogress, rr.Hdr.Name) - inp.Name = rr.Target + inp.Host = rr.Target inp.Port = int(rr.Port) case *dns.TXT: @@ -207,12 +211,14 @@ func (c *client) query(params *QueryParam) error { case *dns.A: // Pull out the IP inp = ensureName(inprogress, rr.Hdr.Name) - inp.Addr = rr.A + inp.Addr = rr.A // @Deprecated + inp.AddrV4 = rr.A case *dns.AAAA: // Pull out the IP inp = ensureName(inprogress, rr.Hdr.Name) - inp.Addr = rr.AAAA + inp.Addr = rr.AAAA // @Deprecated + inp.AddrV6 = rr.AAAA } } diff --git a/zone.go b/zone.go index 431676e..237534b 100644 --- a/zone.go +++ b/zone.go @@ -22,10 +22,15 @@ type Zone interface { type MDNSService struct { Instance string // Instance name (e.g. host name) Service string // Service name (e.g. _http._tcp.) - Addr net.IP // Service IP + HostName string // Host machine DNS name Port int // Service Port Info string // Service info served as a TXT record - Domain string // If blank, assumes ".local" + Domain string // If blank, assumes "local" + + Addr net.IP // @Deprecated. Service IP + + ipv4Addr net.IP // Host machine IPv4 address + ipv6Addr net.IP // Host machine IPv6 address serviceAddr string // Fully qualified service address instanceAddr string // Fully qualified instance address @@ -45,13 +50,42 @@ func (m *MDNSService) Init() error { if m.Service == "" { return fmt.Errorf("Missing service name") } - if m.Addr == nil { - return fmt.Errorf("Missing service address") + if m.Addr == nil && m.HostName == nil { + return fmt.Errorf("Missing service host/address") } if m.Port == 0 { return fmt.Errorf("Missing service port") } + // Get host information + hostName, err := os.Hostname() + if err == nil { + m.HostName = fmt.Sprintf("%s.", m.HostName) + + addrs, err := net.LookupIP(m.GostName) + if err != nil { + // Try appending the host domain suffix and lookup again + // (required for Linux-based hosts) + tmpHostName := fmt.Sprintf("%s%s.", m.HostName, m.Domain) + + addrs, err = net.LookupIP(tmpHostName) + + if err != nil { + return fmt.Errorf("Could not determine host IP addresses for %s", m.HostName) + } + } + + for i := 0; i < len(addrs); i++ { + if ipv4 := addrs[i].To4(); ipv4 != nil { + m.ipv4Addr = addrs[i] + } else if ipv6 := addrs[i].To16(); ipv6 != nil { + m.ipv6Addr = addrs[i] + } + } + } else { + return fmt.Errorf("Could not determine host") + } + // Create the full addresses m.serviceAddr = fmt.Sprintf("%s.%s.", trimDot(m.Service), trimDot(m.Domain)) @@ -127,34 +161,34 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR { case dns.TypeA: // Only handle if we have a ipv4 addr ipv4 := m.Addr.To4() - if ipv4 == nil { + if m.ipv4Addr == nil || ipv4 == nil { return nil } a := &dns.A{ Hdr: dns.RR_Header{ - Name: q.Name, + Name: m.HostName, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: defaultTTL, }, - A: ipv4, + A: m.ipv4Addr || ipv4, } return []dns.RR{a} case dns.TypeAAAA: // Only handle if we have a ipv6 addr ipv6 := m.Addr.To16() - if m.Addr.To4() != nil { + if m.ipv6Addr == nil || m.Addr.To4() != nil { return nil } a4 := &dns.AAAA{ Hdr: dns.RR_Header{ - Name: q.Name, + Name: m.HostName, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: defaultTTL, }, - AAAA: ipv6, + AAAA: m.ipv6Addr || ipv6, } return []dns.RR{a4} @@ -170,7 +204,7 @@ func (m *MDNSService) instanceRecords(q dns.Question) []dns.RR { Priority: 10, Weight: 1, Port: uint16(m.Port), - Target: q.Name, + Target: m.HostName, } recs := []dns.RR{srv}