Start intel package adjustments
This commit is contained in:
164
intel/rrcache.go
Normal file
164
intel/rrcache.go
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright Safing ICS Technologies GmbH. Use of this source code is governed by the AGPL license that can be found in the LICENSE file.
|
||||
|
||||
package intel
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// RRCache is used to cache DNS data
|
||||
type RRCache struct {
|
||||
Domain string
|
||||
Question dns.Type
|
||||
|
||||
Answer []dns.RR
|
||||
Ns []dns.RR
|
||||
Extra []dns.RR
|
||||
TTL int64
|
||||
|
||||
updated int64
|
||||
servedFromCache bool
|
||||
requestingNew bool
|
||||
}
|
||||
|
||||
// Clean sets all TTLs to 17 and sets cache expiry with specified minimum.
|
||||
func (m *RRCache) Clean(minExpires uint32) {
|
||||
var lowestTTL uint32 = 0xFFFFFFFF
|
||||
var header *dns.RR_Header
|
||||
|
||||
// set TTLs to 17
|
||||
// TODO: double append? is there something more elegant?
|
||||
for _, rr := range append(m.Answer, append(m.Ns, m.Extra...)...) {
|
||||
header = rr.Header()
|
||||
if lowestTTL > header.Ttl {
|
||||
lowestTTL = header.Ttl
|
||||
}
|
||||
header.Ttl = 17
|
||||
}
|
||||
|
||||
// TTL must be at least minExpires
|
||||
if lowestTTL < minExpires {
|
||||
lowestTTL = minExpires
|
||||
}
|
||||
|
||||
m.TTL = time.Now().Unix() + int64(lowestTTL)
|
||||
}
|
||||
|
||||
// ExportAllARecords return of a list of all A and AAAA IP addresses.
|
||||
func (m *RRCache) ExportAllARecords() (ips []net.IP) {
|
||||
for _, rr := range m.Answer {
|
||||
if rr.Header().Class != dns.ClassINET {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rr.Header().Rrtype {
|
||||
case dns.TypeA:
|
||||
aRecord, ok := rr.(*dns.A)
|
||||
if ok {
|
||||
ips = append(ips, aRecord.A)
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
aaaaRecord, ok := rr.(*dns.AAAA)
|
||||
if ok {
|
||||
ips = append(ips, aaaaRecord.AAAA)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ToNameRecord converts the RRCache to a NameRecord for cleaner persistence.
|
||||
func (m *RRCache) ToNameRecord() *NameRecord {
|
||||
new := &NameRecord{
|
||||
Domain: m.Domain,
|
||||
Question: m.Question.String(),
|
||||
TTL: m.TTL,
|
||||
}
|
||||
|
||||
// stringify RR entries
|
||||
for _, entry := range m.Answer {
|
||||
new.Answer = append(new.Answer, entry.String())
|
||||
}
|
||||
for _, entry := range m.Ns {
|
||||
new.Ns = append(new.Ns, entry.String())
|
||||
}
|
||||
for _, entry := range m.Extra {
|
||||
new.Extra = append(new.Extra, entry.String())
|
||||
}
|
||||
|
||||
return new
|
||||
}
|
||||
|
||||
// Save saves the RRCache to the database as a NameRecord.
|
||||
func (m *RRCache) Save() error {
|
||||
return m.ToNameRecord().Save()
|
||||
}
|
||||
|
||||
// GetRRCache tries to load the corresponding NameRecord from the database and convert it.
|
||||
func GetRRCache(domain string, question dns.Type) (*RRCache, error) {
|
||||
var m RRCache
|
||||
rr := &RRCache{
|
||||
Domain: domain,
|
||||
Question: question,
|
||||
}
|
||||
|
||||
nameRecord, err := GetNameRecord(domain, question.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr.TTL = nameRecord.TTL
|
||||
for _, entry := range nameRecord.Answer {
|
||||
rr, err := dns.NewRR(entry)
|
||||
if err == nil {
|
||||
m.Answer = append(m.Answer, rr)
|
||||
}
|
||||
}
|
||||
for _, entry := range nameRecord.Ns {
|
||||
rr, err := dns.NewRR(entry)
|
||||
if err == nil {
|
||||
m.Ns = append(m.Ns, rr)
|
||||
}
|
||||
}
|
||||
for _, entry := range nameRecord.Extra {
|
||||
rr, err := dns.NewRR(entry)
|
||||
if err == nil {
|
||||
m.Extra = append(m.Extra, rr)
|
||||
}
|
||||
}
|
||||
|
||||
m.servedFromCache = true
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
// ServedFromCache marks the RRCache as served from cache.
|
||||
func (m *RRCache) ServedFromCache() bool {
|
||||
return m.servedFromCache
|
||||
}
|
||||
|
||||
// RequestingNew informs that it has expired and new RRs are being fetched.
|
||||
func (m *RRCache) RequestingNew() bool {
|
||||
return m.requestingNew
|
||||
}
|
||||
|
||||
// Flags formats ServedFromCache and RequestingNew to a condensed, flag-like format.
|
||||
func (m *RRCache) Flags() string {
|
||||
switch {
|
||||
case m.servedFromCache && m.requestingNew:
|
||||
return " [CR]"
|
||||
case m.servedFromCache:
|
||||
return " [C]"
|
||||
case m.requestingNew:
|
||||
return " [R]" // should never enter this state, but let's leave it here, just in case
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// IsNXDomain returnes whether the result is nxdomain.
|
||||
func (m *RRCache) IsNXDomain() bool {
|
||||
return len(m.Answer) == 0
|
||||
}
|
||||
Reference in New Issue
Block a user