Browse Source

add comments

master
Brett Langdon 10 years ago
parent
commit
1a718de165
3 changed files with 45 additions and 11 deletions
  1. +7
    -0
      cmd/realm/main.go
  2. +18
    -7
      server.go
  3. +20
    -4
      zone.go

+ 7
- 0
cmd/realm/main.go View File

@ -8,6 +8,7 @@ import (
) )
func main() { func main() {
// Setup our CLI app
var app *cli.App = cli.NewApp() var app *cli.App = cli.NewApp()
app.Name = "realm" app.Name = "realm"
app.Version = "0.1.0" app.Version = "0.1.0"
@ -26,12 +27,16 @@ func main() {
Usage: "'[<host>]:<port>' to bind too", Usage: "'[<host>]:<port>' to bind too",
}, },
} }
// This action is called for all commands
app.Action = func(c *cli.Context) { app.Action = func(c *cli.Context) {
// Ensure that a zone filename was provided
var filename string = c.String("zone") var filename string = c.String("zone")
if filename == "" { if filename == "" {
log.Fatal("must supply zone file via \"--zone\" flag or \"REALM_ZONE\" environment variable") log.Fatal("must supply zone file via \"--zone\" flag or \"REALM_ZONE\" environment variable")
} }
// Load and parse the zone file
var zone *realm.Zone var zone *realm.Zone
var err error var err error
log.Printf("parsing zone file \"%s\"\n", filename) log.Printf("parsing zone file \"%s\"\n", filename)
@ -40,11 +45,13 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
// Create and start the server
var bind string = c.String("bind") var bind string = c.String("bind")
log.Printf("starting the server on \"%s\"\n", bind) log.Printf("starting the server on \"%s\"\n", bind)
var server *realm.Server = realm.NewServer(bind, zone) var server *realm.Server = realm.NewServer(bind, zone)
log.Fatal(server.ListenAndServe()) log.Fatal(server.ListenAndServe())
} }
// Parse command arguments and run `app.Action`
app.RunAndExitOnError() app.RunAndExitOnError()
} }

+ 18
- 7
server.go View File

@ -2,34 +2,45 @@ package realm
import "github.com/miekg/dns" import "github.com/miekg/dns"
// A Server listens for DNS requests over UDP and responds with answers from the provided Zone.
type Server struct { type Server struct {
server *dns.Server server *dns.Server
zone *Zone zone *Zone
} }
// NewServer returns a new initialized *Server that will bind to listen and will look up answers from zone.
func NewServer(listen string, zone *Zone) *Server { func NewServer(listen string, zone *Zone) *Server {
var server *Server = &Server{zone: zone}
server.server = &dns.Server{
var server *Server
s = &Server{zone: zone}
s.server = &dns.Server{
Addr: listen, Addr: listen,
Net: "udp", Net: "udp",
Handler: server, Handler: server,
} }
return server
return s
} }
func (server *Server) ListenAndServe() error {
// ListenAndServe will start the nameserver on the configured address.
func (s *Server) ListenAndServe() error {
return server.server.ListenAndServe() return server.server.ListenAndServe()
} }
func (server *Server) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
var response *dns.Msg = &dns.Msg{}
// ServeDNS will be called for every DNS request to this server.
// It will attempt to provide answers to all questions from the configured zone.
func (s *Server) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
// Setup the default response
var response *dns.Msg
response = &dns.Msg{}
response.SetReply(request) response.SetReply(request)
response.Compress = true response.Compress = true
// Lookup answers to any of the questions
for _, question := range request.Question { for _, question := range request.Question {
var records []dns.RR = server.zone.Lookup(question.Name, question.Qtype, question.Qclass)
var records []dns.RR
records = s.zone.Lookup(question.Name, question.Qtype, question.Qclass)
response.Answer = append(response.Answer, records...) response.Answer = append(response.Answer, records...)
} }
// Respond to the request
w.WriteMsg(response) w.WriteMsg(response)
} }

+ 20
- 4
zone.go View File

@ -7,10 +7,13 @@ import (
"github.com/miekg/dns" "github.com/miekg/dns"
) )
// A Zone a container for records parsed from a zone file.
type Zone struct { type Zone struct {
records []dns.RR records []dns.RR
} }
// ParseZone will attempt to parse a zone file from the provided filename and return a Zone.
// ParseZone will return an error if the file provided does not exist or could not be properly parsed.
func ParseZone(filename string) (*Zone, error) { func ParseZone(filename string) (*Zone, error) {
var zone *Zone var zone *Zone
var err error var err error
@ -18,6 +21,7 @@ func ParseZone(filename string) (*Zone, error) {
records: make([]dns.RR, 0), records: make([]dns.RR, 0),
} }
// Open the file
var file *os.File var file *os.File
file, err = os.Open(filename) file, err = os.Open(filename)
if err != nil { if err != nil {
@ -25,6 +29,7 @@ func ParseZone(filename string) (*Zone, error) {
} }
defer file.Close() defer file.Close()
// Parse the file into records
var tokens chan *dns.Token var tokens chan *dns.Token
tokens = dns.ParseZone(file, "", "") tokens = dns.ParseZone(file, "", "")
for token := range tokens { for token := range tokens {
@ -37,21 +42,32 @@ func ParseZone(filename string) (*Zone, error) {
return zone, nil return zone, nil
} }
// Lookup will find all records which we should respond with for the given name, request type, and request class.
func (zone *Zone) Lookup(name string, reqType uint16, reqClass uint16) []dns.RR { func (zone *Zone) Lookup(name string, reqType uint16, reqClass uint16) []dns.RR {
name = dns.Fqdn(name) name = dns.Fqdn(name)
var records []dns.RR = make([]dns.RR, 0)
var records []dns.RR
records = make([]dns.RR, 0)
for _, record := range zone.records { for _, record := range zone.records {
var header *dns.RR_Header = record.Header()
var header *dns.RR_Header
header = record.Header()
// Skip this record if the name or class do not match
if header.Name != name || (header.Class != reqClass && reqClass != dns.ClassANY) { if header.Name != name || (header.Class != reqClass && reqClass != dns.ClassANY) {
continue continue
} }
// Collect this record if the types match or this record is a CNAME
if reqType == dns.TypeANY || reqType == header.Rrtype { if reqType == dns.TypeANY || reqType == header.Rrtype {
records = append(records, record) records = append(records, record)
} else if header.Rrtype == dns.TypeCNAME { } else if header.Rrtype == dns.TypeCNAME {
// Append this CNAME record as a response
records = append(records, record) records = append(records, record)
var cname *dns.CNAME = record.(*dns.CNAME)
var cnameRecords []dns.RR = zone.Lookup(dns.Fqdn(cname.Target), reqType, reqClass)
// Attempt to resolve this CNAME record
var cname *dns.CNAME
cname = record.(*dns.CNAME)
var cnameRecords []dns.RR
cnameRecords = zone.Lookup(dns.Fqdn(cname.Target), reqType, reqClass)
records = append(records, cnameRecords...) records = append(records, cnameRecords...)
} }
} }


Loading…
Cancel
Save