Browse Source

initial prototype

master
Brett Langdon 10 years ago
parent
commit
86727eae2d
5 changed files with 156 additions and 0 deletions
  1. +2
    -0
      .gitignore
  2. +10
    -0
      Makefile
  3. +50
    -0
      cmd/realm/main.go
  4. +35
    -0
      server.go
  5. +59
    -0
      zone.go

+ 2
- 0
.gitignore View File

@ -0,0 +1,2 @@
/realm
*.zone

+ 10
- 0
Makefile View File

@ -0,0 +1,10 @@
realm: ./cmd/realm/main.go ./server.go ./zone.go
go build ./cmd/realm
clean:
rm -f ./realm
run:
go run ./cmd/realm/main.go
.PHONY: clean run

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

@ -0,0 +1,50 @@
package main
import (
"log"
"github.com/brettlangdon/realm"
"github.com/codegangsta/cli"
)
func main() {
var app *cli.App = cli.NewApp()
app.Name = "realm"
app.Version = "0.1.0"
app.Author = "Brett Langdon"
app.Email = "me@brett.is"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "zone, z",
EnvVar: "REALM_ZONE",
Usage: "location to DNS zone file [required]",
},
cli.StringFlag{
Name: "bind, b",
EnvVar: "REALM_BIND",
Value: ":53",
Usage: "'[<host>]:<port>' to bind too",
},
}
app.Action = func(c *cli.Context) {
var filename string = c.String("zone")
if filename == "" {
log.Fatal("must supply zone file via \"--zone\" flag or \"REALM_ZONE\" environment variable")
}
var zone *realm.Zone
var err error
log.Printf("parsing zone file \"%s\"\n", filename)
zone, err = realm.ParseZone(filename)
if err != nil {
log.Fatal(err)
}
var bind string = c.String("bind")
log.Printf("starting the server on \"%s\"\n", bind)
var server *realm.Server = realm.NewServer(bind, zone)
log.Fatal(server.ListenAndServe())
}
app.RunAndExitOnError()
}

+ 35
- 0
server.go View File

@ -0,0 +1,35 @@
package realm
import "github.com/miekg/dns"
type Server struct {
server *dns.Server
zone *Zone
}
func NewServer(listen string, zone *Zone) *Server {
var server *Server = &Server{zone: zone}
server.server = &dns.Server{
Addr: listen,
Net: "udp",
Handler: server,
}
return server
}
func (server *Server) ListenAndServe() error {
return server.server.ListenAndServe()
}
func (server *Server) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
var response *dns.Msg = &dns.Msg{}
response.SetReply(request)
response.Compress = true
for _, question := range request.Question {
var records []dns.RR = server.zone.Lookup(question.Name, question.Qtype, question.Qclass)
response.Answer = append(response.Answer, records...)
}
w.WriteMsg(response)
}

+ 59
- 0
zone.go View File

@ -0,0 +1,59 @@
package realm
import (
"fmt"
"os"
"github.com/miekg/dns"
)
type Zone struct {
records []dns.RR
}
func ParseZone(filename string) (*Zone, error) {
var zone *Zone
var err error
zone = &Zone{
records: make([]dns.RR, 0),
}
var file *os.File
file, err = os.Open(filename)
if err != nil {
return nil, fmt.Errorf("could not parse zone file \"%s\": \"%s\"", filename, err)
}
defer file.Close()
var tokens chan *dns.Token
tokens = dns.ParseZone(file, "", "")
for token := range tokens {
if token.Error != nil {
return nil, fmt.Errorf("could not parse zone file \"%s\": \"%s\"", filename, token.Error)
}
zone.records = append(zone.records, token.RR)
}
return zone, nil
}
func (zone *Zone) Lookup(name string, reqType uint16, reqClass uint16) []dns.RR {
name = dns.Fqdn(name)
var records []dns.RR = make([]dns.RR, 0)
for _, record := range zone.records {
var header *dns.RR_Header = record.Header()
if header.Name != name || (header.Class != reqClass && reqClass != dns.ClassANY) {
continue
}
if reqType == dns.TypeANY || reqType == header.Rrtype {
records = append(records, record)
} else if header.Rrtype == dns.TypeCNAME {
records = append(records, record)
var cname *dns.CNAME = record.(*dns.CNAME)
var cnameRecords []dns.RR = zone.Lookup(dns.Fqdn(cname.Target), reqType, reqClass)
records = append(records, cnameRecords...)
}
}
return records
}

Loading…
Cancel
Save