85 lines
3.3 KiB
Go
85 lines
3.3 KiB
Go
package mdns
|
|
|
|
import "github.com/miekg/dns"
|
|
|
|
// DNSSDService is a service that complies with the DNS-SD (RFC 6762) and MDNS
|
|
// (RFC 6762) specs for local, multicast-DNS-based discovery.
|
|
//
|
|
// DNSSDService implements the Zone interface and wraps an MDNSService instance.
|
|
// To deploy an mDNS service that is compliant with DNS-SD, it's recommended to
|
|
// register only the wrapped instance with the server.
|
|
//
|
|
// Example usage:
|
|
// service := &mdns.DNSSDService{
|
|
// MDNSService: &mdns.MDNSService{
|
|
// Instance: "My Foobar Service",
|
|
// Service: "_foobar._tcp",
|
|
// Port: 8000,
|
|
// }
|
|
// }
|
|
// server, err := mdns.NewServer(&mdns.Config{Zone: service})
|
|
// if err != nil {
|
|
// log.Fatalf("Error creating server: %v", err)
|
|
// }
|
|
// defer server.Shutdown()
|
|
type DNSSDService struct {
|
|
MDNSService *MDNSService
|
|
}
|
|
|
|
// Records returns DNS records in response to a DNS question.
|
|
//
|
|
// This function returns the DNS response of the underlying MDNSService
|
|
// instance. It also returns a PTR record for a request for "
|
|
// _services._dns-sd._udp.<Domain>", as described in section 9 of RFC 6763
|
|
// ("Service Type Enumeration"), to allow browsing of the underlying MDNSService
|
|
// instance.
|
|
func (s *DNSSDService) Records(q dns.Question) []dns.RR {
|
|
var recs []dns.RR
|
|
if q.Name == "_services._dns-sd._udp."+s.MDNSService.Domain+"." {
|
|
recs = s.dnssdMetaQueryRecords(q)
|
|
}
|
|
return append(recs, s.MDNSService.Records(q)...)
|
|
}
|
|
|
|
// dnssdMetaQueryRecords returns the DNS records in response to a "meta-query"
|
|
// issued to browse for DNS-SD services, as per section 9. of RFC6763.
|
|
//
|
|
// A meta-query has a name of the form "_services._dns-sd._udp.<Domain>" where
|
|
// Domain is a fully-qualified domain, such as "local."
|
|
func (s *DNSSDService) dnssdMetaQueryRecords(q dns.Question) []dns.RR {
|
|
// Intended behavior, as described in the RFC:
|
|
// ...it may be useful for network administrators to find the list of
|
|
// advertised service types on the network, even if those Service Names
|
|
// are just opaque identifiers and not particularly informative in
|
|
// isolation.
|
|
//
|
|
// For this purpose, a special meta-query is defined. A DNS query for PTR
|
|
// records with the name "_services._dns-sd._udp.<Domain>" yields a set of
|
|
// PTR records, where the rdata of each PTR record is the two-abel
|
|
// <Service> name, plus the same domain, e.g., "_http._tcp.<Domain>".
|
|
// Including the domain in the PTR rdata allows for slightly better name
|
|
// compression in Unicast DNS responses, but only the first two labels are
|
|
// relevant for the purposes of service type enumeration. These two-label
|
|
// service types can then be used to construct subsequent Service Instance
|
|
// Enumeration PTR queries, in this <Domain> or others, to discover
|
|
// instances of that service type.
|
|
return []dns.RR{
|
|
&dns.PTR{
|
|
Hdr: dns.RR_Header{
|
|
Name: q.Name,
|
|
Rrtype: dns.TypePTR,
|
|
Class: dns.ClassINET,
|
|
Ttl: defaultTTL,
|
|
},
|
|
Ptr: s.MDNSService.serviceAddr,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Announcement returns DNS records that should be broadcast during the initial
|
|
// availability of the service, as described in section 8.3 of RFC 6762.
|
|
// TODO(reddaly): Add this when Announcement is added to the mdns.Zone interface.
|
|
//func (s *DNSSDService) Announcement() []dns.RR {
|
|
// return s.MDNSService.Announcement()
|
|
//}
|