Fix outing TSIG on axfr

This commit is contained in:
Miek Gieben 2011-03-30 16:34:17 +02:00
parent ef4d85fa6d
commit 76daa7f08b
2 changed files with 76 additions and 58 deletions

View File

@ -1,64 +1,72 @@
package main
import (
"os"
"os"
"dns"
"fmt"
"fmt"
)
func handleXfr(d *dns.Conn, i *dns.Msg) {
if i.IsAxfr() {
fmt.Printf("Axfr request seen\n")
if i.Question[0].Name == Zone.name {
fmt.Printf("Matching current zone\n")
m := make(chan *dns.Xfr)
go d.XfrWrite(i, m)
for j := 0; j < Zone.size; j++ {
m <- &dns.Xfr{Add: true, RR: Zone.rrs[j]}
}
close(m)
}
}
func handleXfr(d *dns.Conn, i *dns.Msg) os.Error {
if i.IsAxfr() {
fmt.Printf("Axfr request seen\n")
if i.Question[0].Name == Zone.name {
fmt.Printf("Matching current zone\n")
m := make(chan *dns.Xfr)
e := make(chan os.Error)
defer close(m)
defer close(e)
go d.XfrWrite(i, m, e)
for j := 0; j < Zone.size; j++ {
select {
case m <- &dns.Xfr{Add: true, RR: Zone.rrs[j]}: //
case err := <-e:
return err
}
}
}
}
return nil
}
func handleNotify(d *dns.Conn, i *dns.Msg) {
if i.IsNotify() {
fmt.Printf("Notify seen\n")
q := new(dns.Msg)
q.SetReply(i)
err := d.WriteMsg(q)
if err != nil {
return
}
doXfrIn(i)
}
func handleNotify(d *dns.Conn, i *dns.Msg) os.Error {
if i.IsNotify() {
fmt.Printf("Notify seen\n")
q := new(dns.Msg)
q.SetReply(i)
err := d.WriteMsg(q)
if err != nil {
return err
}
doXfrIn(i)
}
return nil
}
func doXfrIn(i *dns.Msg) ([]dns.RR, os.Error) {
q := new(dns.Msg)
q.SetAxfr(i.Question[0].Name)
q := new(dns.Msg)
q.SetAxfr(i.Question[0].Name)
m := make(chan *dns.Xfr)
fmt.Printf("Preparing Xfr for %s\n", i.Question[0].Name)
m := make(chan *dns.Xfr)
fmt.Printf("Preparing Xfr for %s\n", i.Question[0].Name)
d := new(dns.Conn)
d.RemoteAddr = "127.0.0.1:53"
err := d.Dial("tcp")
if err != nil {
return nil, err
}
defer d.Close()
d := new(dns.Conn)
d.RemoteAddr = "127.0.0.1:53"
err := d.Dial("tcp")
if err != nil {
return nil, err
}
defer d.Close()
fmt.Printf("Calling 127.0.0.1 successful\n")
go d.XfrRead(q, m)
fmt.Printf("Calling 127.0.0.1 successful\n")
go d.XfrRead(q, m)
Zone.name = i.Question[0].Name
j := 0
for x := range m {
fmt.Printf("%v %v\n", x.Add, x.RR)
Zone.rrs[j] = x.RR
j++
}
Zone.size = j
return nil, nil
Zone.name = i.Question[0].Name
j := 0
for x := range m {
fmt.Printf("%v %v\n", x.Add, x.RR)
Zone.rrs[j] = x.RR
j++
}
Zone.size = j
return nil, nil
}

30
xfr.go
View File

@ -16,6 +16,7 @@ type Xfr struct {
// be considered to have faild.
Err os.Error
}
// todo maybe add the SOA serial too?
// Perform an incoming Ixfr or Axfr. If the message q's question
// section contains an AXFR type an Axfr is performed. If q's question
@ -50,15 +51,16 @@ func (d *Conn) XfrRead(q *Msg, m chan *Xfr) {
// Perform an outgoing Ixfr or Axfr. If the message q's question
// section contains an AXFR type an Axfr is performed. If q's question
// section contains an IXFR type an Ixfr is performed.
// The message q is written to the connection in d.
func (d *Conn) XfrWrite(q *Msg, m chan *Xfr) {
// The actual records to send are given on the channel m. And errors
// during transport are return on channel e.
func (d *Conn) XfrWrite(q *Msg, m chan *Xfr, e chan os.Error) {
switch q.Question[0].Qtype {
case TypeAXFR:
d.axfrWrite(q, m)
d.axfrWrite(q, m, e)
case TypeIXFR:
// d.ixfrWrite(q, m)
default:
m <- &Xfr{true, nil, &Error{Error: "Xfr Qtype not recognized"}}
e <- &Xfr{true, nil, &Error{Error: "Xfr Qtype not recognized"}}
close(m)
}
}
@ -105,20 +107,22 @@ func (d *Conn) axfrRead(q *Msg, m chan *Xfr) {
}
// Just send the zone
func (d *Conn) axfrWrite(q *Msg, m chan *Xfr) {
func (d *Conn) axfrWrite(q *Msg, m chan *Xfr, e chan os.Error) {
out := new(Msg)
out.Id = q.Id
out.Question = q.Question
out.Answer = make([]RR, 1001)
out.Answer = make([]RR, 1001) // TODO(mg) look at this number
out.MsgHdr.Response = true
out.MsgHdr.Authoritative = true
first := true
var soa *RR_SOA
i := 0
for r := range m {
out.Answer[i] = r.RR
if soa == nil {
if r.RR.Header().Rrtype != TypeSOA {
/* ... */
e <- ErrXfrSoa
return
} else {
soa = r.RR.(*RR_SOA)
}
@ -128,20 +132,26 @@ func (d *Conn) axfrWrite(q *Msg, m chan *Xfr) {
// Send it
err := d.WriteMsg(out)
if err != nil {
/* ... */
e <- err
return
}
i = 0
// Gaat dit goed?
out.Answer = out.Answer[:0]
if first {
if d.Tsig != nil {
d.Tsig.TimersOnly = true
}
first = !first
}
}
// TimersOnly foo for TSIG
}
// Everything is sent, only the closing soa is left.
out.Answer[i] = soa
out.Answer = out.Answer[:i+1]
err := d.WriteMsg(out)
if err != nil {
println(err.String())
e <- err
}
}