mosdns/pkg/dnsutils/msg.go
dengxiongjian cd761e8145
Some checks are pending
Test mosdns / build (push) Waiting to run
新增Mikrotik API 插入解析ip
2025-07-31 11:28:55 +08:00

161 lines
3.5 KiB
Go

/*
* Copyright (C) 2020-2022, IrineSistiana
*
* This file is part of mosdns.
*
* mosdns is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mosdns is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package dnsutils
import (
"github.com/miekg/dns"
"strconv"
)
// GetMinimalTTL returns the minimal ttl of this msg.
// If msg m has no record, it returns 0.
func GetMinimalTTL(m *dns.Msg) uint32 {
minTTL := ^uint32(0)
hasRecord := false
for _, section := range [...][]dns.RR{m.Answer, m.Ns, m.Extra} {
for _, rr := range section {
hdr := rr.Header()
if hdr.Rrtype == dns.TypeOPT {
continue // opt record ttl is not ttl.
}
hasRecord = true
ttl := hdr.Ttl
if ttl < minTTL {
minTTL = ttl
}
}
}
if !hasRecord { // no ttl applied
return 0
}
return minTTL
}
// SetTTL updates all records' ttl to ttl, except opt record.
func SetTTL(m *dns.Msg, ttl uint32) {
for _, section := range [...][]dns.RR{m.Answer, m.Ns, m.Extra} {
for _, rr := range section {
hdr := rr.Header()
if hdr.Rrtype == dns.TypeOPT {
continue // opt record ttl is not ttl.
}
hdr.Ttl = ttl
}
}
}
func ApplyMaximumTTL(m *dns.Msg, ttl uint32) {
applyTTL(m, ttl, true)
}
func ApplyMinimalTTL(m *dns.Msg, ttl uint32) {
applyTTL(m, ttl, false)
}
// SubtractTTL subtract delta from every m's RR.
// If RR's TTL is smaller than delta, SubtractTTL
// will return overflowed = true.
func SubtractTTL(m *dns.Msg, delta uint32) (overflowed bool) {
for _, section := range [...][]dns.RR{m.Answer, m.Ns, m.Extra} {
for _, rr := range section {
hdr := rr.Header()
if hdr.Rrtype == dns.TypeOPT {
continue // opt record ttl is not ttl.
}
if ttl := hdr.Ttl; ttl > delta {
hdr.Ttl = ttl - delta
} else {
hdr.Ttl = 1
overflowed = true
}
}
}
return
}
func applyTTL(m *dns.Msg, ttl uint32, maximum bool) {
for _, section := range [...][]dns.RR{m.Answer, m.Ns, m.Extra} {
for _, rr := range section {
hdr := rr.Header()
if hdr.Rrtype == dns.TypeOPT {
continue // opt record ttl is not ttl.
}
if maximum {
if hdr.Ttl > ttl {
hdr.Ttl = ttl
}
} else {
if hdr.Ttl < ttl {
hdr.Ttl = ttl
}
}
}
}
}
func uint16Conv(u uint16, m map[uint16]string) string {
if s, ok := m[u]; ok {
return s
}
return strconv.Itoa(int(u))
}
func QclassToString(u uint16) string {
return uint16Conv(u, dns.ClassToString)
}
func QtypeToString(u uint16) string {
return uint16Conv(u, dns.TypeToString)
}
func GenEmptyReply(q *dns.Msg, rcode int) *dns.Msg {
r := new(dns.Msg)
r.SetRcode(q, rcode)
var name string
if len(q.Question) > 1 {
name = q.Question[0].Name
} else {
name = "."
}
r.Ns = []dns.RR{FakeSOA(name)}
return r
}
func FakeSOA(name string) *dns.SOA {
return &dns.SOA{
Hdr: dns.RR_Header{
Name: name,
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 300,
},
Ns: "fake-ns.mosdns.fake.root.",
Mbox: "fake-mbox.mosdns.fake.root.",
Serial: 2021110400,
Refresh: 1800,
Retry: 900,
Expire: 604800,
Minttl: 86400,
}
}