DEVELOPMENT ENVIRONMENT

~liljamo/felu

3f2c5e507f91280dc48837725387ace4899189e1 — Jonni Liljamo a month ago 2f76e37
feat: initial NS and SOA responses
1 files changed, 63 insertions(+), 0 deletions(-)

M internal/dns/query.go
M internal/dns/query.go => internal/dns/query.go +63 -0
@@ 12,6 12,7 @@ import (
	"net"
	"strings"

	"git.src.quest/~liljamo/felu/internal/config"
	"git.src.quest/~liljamo/felu/internal/db"
	"github.com/miekg/dns"
)


@@ 27,6 28,12 @@ func parseQuery(m *dns.Msg, r *dns.Msg) {
		switch q.Qtype {
		case dns.TypeA:
			handleARecord(&q, m, r)
		case dns.TypeNS:
			handleNSRecord(&q, m, r)
		case dns.TypeSOA:
			handleSOARecord(&q, m, r)
		default:
			m.SetRcode(r, dns.RcodeNotImplemented)
		}

		slog.Info("Responding to Query",


@@ 51,3 58,59 @@ func handleARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
		m.SetRcode(r, dns.RcodeNameError)
	}
}

func handleNSRecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
	ns := &dns.NS{
		Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0},
		Ns:  dns.Fqdn(config.FeluConfig.DDNSDomain),
	}

	// "Root" DDNS domain NS.
	if q.Name == dns.Fqdn(config.FeluConfig.DDNSDomain) {
		m.Answer = append(m.Answer, ns)
		return
	}

	if index := strings.IndexByte(q.Name, '.'); index >= 0 {
		// FIXME: other way of checking that the domain exists
		_, err := db.FetchDomainARecord(strings.ToLower(q.Name[:index]))
		if err != nil {
			m.SetRcode(r, dns.RcodeNameError)
		} else {
			m.Answer = append(m.Answer, ns)
		}
	} else {
		m.SetRcode(r, dns.RcodeNameError)
	}
}

func handleSOARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
	soa := &dns.SOA{
		Hdr:     dns.RR_Header{Name: q.Name, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 0},
		Ns:      dns.Fqdn(config.FeluConfig.DDNSDomain),
		Mbox:    dns.Fqdn(config.FeluConfig.SOAEmail),
		Serial:  2024100301,
		Refresh: 86400,
		Retry:   7200,
		Expire:  3600000,
		Minttl:  172800,
	}

	// "Root" DDNS domain SOA.
	if q.Name == dns.Fqdn(config.FeluConfig.DDNSDomain) {
		m.Answer = append(m.Answer, soa)
		return
	}

	if index := strings.IndexByte(q.Name, '.'); index >= 0 {
		// FIXME: other way of checking that the domain exists
		_, err := db.FetchDomainARecord(strings.ToLower(q.Name[:index]))
		if err != nil {
			m.SetRcode(r, dns.RcodeNameError)
		} else {
			m.Answer = append(m.Answer, soa)
		}
	} else {
		m.SetRcode(r, dns.RcodeNameError)
	}
}