/*
* Copyright (C) 2024 Jonni Liljamo <jonni@liljamo.com>
*
* This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for
* more information.
*/
// Package dns implements all required DNS functionality for the program.
package dns
import (
"git.src.quest/~liljamo/felu/internal/config"
"github.com/miekg/dns"
)
// Run starts the DNS server.
func Run(addr string, net string) error {
dns.HandleFunc(config.FeluConfig.Domain, handleDNSRequest)
server := &dns.Server{
Addr: addr,
Net: net,
MsgAcceptFunc: msgAcceptFunc,
TsigProvider: tsigProvider{},
}
return server.ListenAndServe()
}
// https://github.com/miekg/dns/blob/b77d1ed8e9282cadf21c4124f53a660fed55c8ca/types.go#L192
const _QR = 1 << 15 // query/response (response=1)
// Otherwise the same as the original, but:
//
// 1: Commented out dynamic update rejection.
// 2: Commented out dh.Nscount > 1, for dynamic updates.
//
// TODO: Consider looking this over properly, and maybe ditching the default.
//
// https://github.com/miekg/dns/blob/b77d1ed8e9282cadf21c4124f53a660fed55c8ca/acceptfunc.go
func msgAcceptFunc(dh dns.Header) dns.MsgAcceptAction {
if isResponse := dh.Bits&_QR != 0; isResponse {
return dns.MsgIgnore
}
/*
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
opcode := int(dh.Bits>>11) & 0xF
if opcode != dns.OpcodeQuery && opcode != dns.OpcodeNotify {
return dns.MsgRejectNotImplemented
}
*/
if dh.Qdcount != 1 {
return dns.MsgReject
}
// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
if dh.Ancount > 1 {
return dns.MsgReject
}
/*
// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
if dh.Nscount > 1 {
return dns.MsgReject
}
*/
if dh.Arcount > 2 {
return dns.MsgReject
}
return dns.MsgAccept
}