123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- package zone
- import (
- "fmt"
- "net"
- "git.giaever.org/joachimmg/m-dns/config"
- "git.giaever.org/joachimmg/m-dns/errors"
- "git.giaever.org/joachimmg/m-dns/host"
- "github.com/miekg/dns"
- )
- type Zone interface {
- Records(q dns.Question)
- }
- type ZoneRecord struct {
- Instance host.HostString
- TXT []string
- sAddr string
- iAddr string
- eAddr string
- *host.Host
- }
- func New(instance, service, domain, hostname string, port int, ips []net.IP, txt []string) (*ZoneRecord, error) {
- zr := new(ZoneRecord)
- zr.Host = new(host.Host)
- if len(instance) == 0 {
- return nil, errors.ZoneInstanseIsEmpty
- }
- zr.Instance = host.HostString(instance)
- if err := zr.SetService(service); err != nil {
- return nil, err
- }
- if err := zr.SetDomain(domain); err != nil {
- return nil, err
- }
- if err := zr.SetHostname(hostname); err != nil {
- return nil, err
- }
- if err := zr.SetPort(port); err != nil {
- return nil, err
- }
- zr.TXT = txt
- zr.sAddr = fmt.Sprintf("%s.%s.",
- zr.GetService().TrimDot(),
- zr.GetDomain().TrimDot(),
- )
- zr.iAddr = fmt.Sprintf("%s.%s.%s.",
- zr.Instance.TrimDot,
- zr.GetService().TrimDot(),
- zr.GetDomain().TrimDot(),
- )
- zr.eAddr = fmt.Sprintf("_services._dns-ds._udp.%s.",
- zr.GetDomain().TrimDot(),
- )
- return zr, nil
- }
- func (zr *ZoneRecord) Records(q dns.Question) []dns.RR {
- switch q.Name {
- case zr.sAddr:
- return zr.sRecords(q)
- case zr.iAddr:
- return zr.iRecords(q)
- case zr.eAddr:
- return zr.sEnum(q)
- case zr.GetHostname().String():
- switch q.Qtype {
- case dns.TypeA, dns.TypeAAAA:
- return zr.iRecords(q)
- }
- fallthrough
- default:
- return nil
- }
- }
- func (zr *ZoneRecord) sRecords(q dns.Question) []dns.RR {
- switch q.Qtype {
- case dns.TypeANY, dns.TypePTR:
- sr := []dns.RR{
- &dns.PTR{
- Hdr: dns.RR_Header{
- Name: q.Name,
- Rrtype: dns.TypePTR,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- Ptr: zr.iAddr,
- },
- }
- return append(sr, zr.Records(
- dns.Question{
- Name: zr.iAddr,
- Qtype: dns.TypeANY,
- },
- )...)
- default:
- return nil
- }
- }
- func (zr *ZoneRecord) iRecords(q dns.Question) []dns.RR {
- switch q.Qtype {
- case dns.TypeANY:
- ir := zr.Records(
- dns.Question{
- Name: zr.iAddr,
- Qtype: dns.TypeSRV,
- },
- )
- return append(ir, zr.Records(
- dns.Question{
- Name: zr.iAddr,
- Qtype: dns.TypeTXT,
- },
- )...)
- case dns.TypeA:
- var ir []dns.RR
- for _, ip := range zr.GetIPs() {
- switch ip.Type() {
- case host.IPv4:
- ir = append(ir, &dns.A{
- Hdr: dns.RR_Header{
- Name: zr.GetHostname().String(),
- Rrtype: dns.TypeA,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- })
- case host.IPv6:
- continue
- }
- }
- return ir
- case dns.TypeAAAA:
- var ir []dns.RR
- for _, ip := range zr.GetIPs() {
- switch ip.Type() {
- case host.IPv4:
- continue
- case host.IPv6:
- ir = append(ir, &dns.AAAA{
- Hdr: dns.RR_Header{
- Name: zr.GetHostname().String(),
- Rrtype: dns.TypeAAAA,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- AAAA: ip.AsIP().To16(),
- })
- }
- }
- return ir
- case dns.TypeSRV:
- ir := []dns.RR{
- &dns.SRV{
- Hdr: dns.RR_Header{
- Name: q.Name,
- Rrtype: dns.TypeSRV,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- Priority: 10,
- Weight: 1,
- Port: zr.GetPort().Uint16(),
- Target: zr.GetHostname().String(),
- },
- }
- ir = append(ir, zr.Records(
- dns.Question{
- Name: zr.iAddr,
- Qtype: dns.TypeA,
- },
- )...)
- return append(ir, zr.Records(
- dns.Question{
- Name: zr.iAddr,
- Qtype: dns.TypeAAAA,
- },
- )...)
- case dns.TypeTXT:
- return []dns.RR{
- &dns.TXT{
- Hdr: dns.RR_Header{
- Name: q.Name,
- Rrtype: dns.TypeTXT,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- },
- }
- default:
- return nil
- }
- }
- func (zr *ZoneRecord) sEnum(q dns.Question) []dns.RR {
- switch q.Qtype {
- case dns.TypeANY, dns.TypePTR:
- return []dns.RR{
- &dns.PTR{
- Hdr: dns.RR_Header{
- Name: q.Name,
- Rrtype: dns.TypePTR,
- Class: dns.ClassINET,
- Ttl: config.DefaultTTL,
- },
- Ptr: zr.sAddr,
- },
- }
- default:
- return nil
- }
- }
|