dns/_examples/funkensturm/config_rproxy.go
2011-08-01 14:13:13 +02:00

99 lines
2.5 KiB
Go

package main
// Keep a local cache of DNS packets. Match incoming
// qname,qclass,qtype and return the saved packet.
// On a cache miss consult the nameserver
import (
"dns"
)
// Keep everything in the cache for 60 seconds
const (
CACHETTL = 60
_CLASS = 2 << 16
)
// Number in the second map denotes the class + type.
func intval(c, t uint16) int {
return int(c)*_CLASS + int(t)
}
// Ala Zone in zone.go, but slightly different
type Cache map[string]map[int][]byte
func NewCache() Cache {
c := make(Cache)
return c
}
// Remove an entry from the cache
func (c Cache) evict(q dns.Msg) {
// todo
}
// Add an entry from the cache. The old entry (if any) gets
// overwritten
func (c Cache) add(q *dns.Msg) {
qname := q.Question[0].Name
i := intval(q.Question[0].Qclass, q.Question[0].Qtype)
if c[qname] == nil {
im := make(map[int][]byte)
c[qname] = im
}
buf, _ := q.Pack()
im := c[qname]
im[i] = buf
}
// Lookup an entry in the cache. Returns null
// when nothing found.
func (c Cache) lookup(q *dns.Msg) []byte {
// Use the question section for looking up
i := intval(q.Question[0].Qclass, q.Question[0].Qtype)
if im, ok := c[q.Question[0].Name]; ok {
// we have the name
if d, ok := im[i]; ok {
e := make([]byte, len(d))
copy(e, d)
return e
}
}
return nil
}
func checkcache(m *dns.Msg) (o []byte) {
// Check if we have the packet in Cache
// if so, return it. Otherwise ask the
// server, return that answer and put it
// in the cache.
o = cache.lookup(m)
if o != nil {
// octet 1 and 2 contain the Id, set the one for the current pkt
o[0] = byte(m.MsgHdr.Id >> 8)
o[1] = byte(m.MsgHdr.Id)
return
}
println("Cache miss")
var p *dns.Msg
for _, c := range qr {
p = c.Client.Exchange(m, c.Addr)
}
cache.add(p)
o, _ = p.Pack()
return
}
var cache Cache
// Return the configration
func NewFunkenSturm() *FunkenSturm {
f := new(FunkenSturm)
f.Funk = make([]*Funk, 1)
f.Setup = func() bool { cache = NewCache(); return true }
f.Funk[0] = new(Funk)
f.Funk[0].Match = func(m *dns.Msg) (*dns.Msg, bool) { return m, true }
f.Funk[0].Action = checkcache
return f
}