fix reflect

This commit is contained in:
Miek Gieben 2011-03-21 22:53:15 +01:00
parent fd0704f111
commit a7a8b616f0
7 changed files with 95 additions and 84 deletions

2
TODO
View File

@ -5,6 +5,8 @@ o clean, small API
o fast data structures (rb-tree, when they come available)
o api-use should lead to self documenting code
o compression (only ownernames?)
o Tsig will probably become an interface which has all configuration
stuff, but this will come later
Todo:

View File

@ -18,99 +18,78 @@ package main
import (
"os"
"os/signal"
"net"
"dns"
"fmt"
"os/signal"
"strconv"
)
func reply(a net.Addr, in *dns.Msg, tcp bool) *dns.Msg {
if in.MsgHdr.Response == true {
return nil // Don't answer responses
}
func reply(c *dns.Conn, in *dns.Msg) []byte {
m := new(dns.Msg)
m.MsgHdr.Id = in.MsgHdr.Id
m.MsgHdr.Authoritative = true
m.MsgHdr.Response = true
m.MsgHdr.Opcode = dns.OpcodeQuery
m.SetReply(in.MsgHdr.Id)
m.MsgHdr.Rcode = dns.RcodeSuccess
m.Question = make([]dns.Question, 1)
m.Answer = make([]dns.RR, 1)
m.Extra = make([]dns.RR, 1)
r := new(dns.RR_A)
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
ip, _ := net.ResolveUDPAddr(a.String())
r.A = ip.IP
m.Question[0] = in.Question[0]
var ad net.IP
if c.UDP != nil {
ad = c.Addr.(*net.UDPAddr).IP
} else {
ad = c.Addr.(*net.TCPAddr).IP
}
if ad.To4() != nil {
r := new(dns.RR_A)
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
if c.UDP != nil {
r.A = c.Addr.(*net.UDPAddr).IP
} else {
r.A = c.Addr.(*net.TCPAddr).IP
}
m.Answer[0] = r
} else {
r := new(dns.RR_AAAA)
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
if c.UDP != nil {
r.AAAA = c.Addr.(*net.UDPAddr).IP
} else {
r.AAAA = c.Addr.(*net.TCPAddr).IP
}
m.Answer[0] = r
}
t := new(dns.RR_TXT)
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
if tcp {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
if c.TCP != nil {
t.Txt = "Port: " + strconv.Itoa(c.Port) + " (tcp)"
} else {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
t.Txt = "Port: " + strconv.Itoa(c.Port) + " (udp)"
}
m.Question[0] = in.Question[0]
m.Answer[0] = r
m.Extra[0] = t
return m
b, _ := m.Pack()
return b
}
func replyUDP(c *net.UDPConn, a net.Addr, in *dns.Msg) {
m := reply(a, in, false)
if m == nil {
return
func handle(c *dns.Conn, in *dns.Msg) {
if in.MsgHdr.Response == true {
return // We don't do responses
}
fmt.Fprintf(os.Stderr, "%v\n", m)
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
dns.SendUDP(out, c, a)
}
func replyTCP(c *net.TCPConn, a net.Addr, in *dns.Msg) {
m := reply(a, in, true)
if m == nil {
return
}
fmt.Fprintf(os.Stderr, "%v\n", m)
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
dns.SendTCP(out, c, a)
answer := reply(c, in)
c.Write(answer)
}
func tcp(addr string, e chan os.Error) {
a, err := net.ResolveTCPAddr(addr)
if err != nil {
e <- err
}
l, err := net.ListenTCP("tcp", a)
if err != nil {
e <- err
}
err = dns.ServeTCP(l, replyTCP)
err := dns.ListenAndServeTCP(addr, handle)
e <- err
return
}
func udp(addr string, e chan os.Error) {
a, err := net.ResolveUDPAddr(addr)
if err != nil {
e <- err
}
l, err := net.ListenUDP("udp", a)
if err != nil {
e <- err
}
err = dns.ServeUDP(l, replyUDP)
err := dns.ListenAndServeUDP(addr, handle)
e <- err
return
}

View File

@ -1,5 +1,14 @@
package dns
// Create a reply packet.
func (dns *Msg) SetReply(id uint16) {
dns.MsgHdr.Id = id
dns.MsgHdr.Authoritative = true
dns.MsgHdr.Response = true
dns.MsgHdr.Opcode = OpcodeQuery
dns.MsgHdr.Rcode = RcodeSuccess
}
// Create a notify packet.
func (dns *Msg) SetNotify(z string, class uint16) {
dns.MsgHdr.Opcode = OpcodeNotify

27
dns.go
View File

@ -58,6 +58,9 @@ type Conn struct {
// The remote side of the connection.
Addr net.Addr
// The remote port number of the connection.
Port int
// If TSIG is used, this holds all the information
Tsig *Tsig
@ -68,6 +71,20 @@ type Conn struct {
Attempts int
}
// Create a new buffer of the appropiate size.
func (d *Conn) NewBuffer() []byte {
if d.TCP != nil {
b := make([]byte, MaxMsgSize)
return b
}
if d.UDP != nil {
b := make([]byte, DefaultMsgSize)
return b
}
return nil
}
func (d *Conn) Read(p []byte) (n int, err os.Error) {
if d.UDP != nil && d.TCP != nil {
return 0, &Error{Error: "UDP and TCP or both non-nil"}
@ -80,6 +97,7 @@ func (d *Conn) Read(p []byte) (n int, err os.Error) {
return n, err
}
d.Addr = addr
d.Port = addr.(*net.UDPAddr).Port
case d.TCP != nil:
if len(p) < 1 {
return 0, &Error{Error: "Buffer too small to read"}
@ -88,6 +106,8 @@ func (d *Conn) Read(p []byte) (n int, err os.Error) {
if err != nil || n != 2 {
return n, err
}
d.Addr = d.TCP.RemoteAddr()
d.Port = d.TCP.RemoteAddr().(*net.TCPAddr).Port
l, _ := unpackUint16(p[0:2], 0)
if l == 0 {
return 0, &Error{Error: "received nil msg length", Server: d.Addr}
@ -132,7 +152,6 @@ func (d *Conn) Write(p []byte) (n int, err os.Error) {
attempts = d.Attempts
}
d.SetTimeout()
if d.Tsig != nil {
// Create a new buffer with the TSIG added.
q, err = d.Tsig.Generate(p)
@ -233,11 +252,7 @@ func (d *Conn) Exchange(request []byte, nosend bool) (reply []byte, err os.Error
}
}
// Layer violation to save memory. Its okay then...
if d.UDP == nil {
reply = make([]byte, MaxMsgSize)
} else {
reply = make([]byte, DefaultMsgSize)
}
reply = d.NewBuffer()
n, err = d.Read(reply)
if err != nil {
return nil, err

View File

@ -43,7 +43,11 @@ type Resolver struct {
// in, err := res.Query(m, nil) // Ask the question
//
// Note that message id checking is left to the caller.
func (res *Resolver) Query(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
return res.QueryTsig(q, nil)
}
func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
var c net.Conn
var inb []byte
in := new(Msg)
@ -88,7 +92,11 @@ func (res *Resolver) Query(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
return in, nil
}
func (res *Resolver) Xfr(q *Msg, t *Tsig, m chan Xfr) {
func (res *Resolver) Xfr(q *Msg, m chan Xfr) {
res.XfrTsig(q, nil, m)
}
func (res *Resolver) XfrTsig(q *Msg, t *Tsig, m chan Xfr) {
port, err := check(res, q)
if err != nil {
return

View File

@ -12,8 +12,9 @@ import (
)
// For both -> logging
// Add tsig stuff as in resolver.go
func ServeUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error {
func HandleUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error {
for {
m := make([]byte, DefaultMsgSize)
n, addr, e := l.ReadFromUDP(m)
@ -25,6 +26,7 @@ func ServeUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error {
d := new(Conn)
d.UDP = l
d.Addr = addr
d.Port = addr.Port // Why not the same as in dns.go, line 96
msg := new(Msg)
if !msg.Unpack(m) {
@ -35,7 +37,7 @@ func ServeUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error {
panic("not reached")
}
func ServeTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error {
func HandleTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error {
for {
c, e := l.AcceptTCP()
if e != nil {
@ -44,8 +46,9 @@ func ServeTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error {
d := new(Conn)
d.TCP = c
d.Addr = c.RemoteAddr()
d.Port = d.TCP.RemoteAddr().(*net.TCPAddr).Port
m := make([]byte, MaxMsgSize) // This may start to hurt someday.
m := d.NewBuffer()
n, e := d.Read(m)
if e != nil {
continue
@ -75,7 +78,7 @@ func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error {
if err != nil {
return err
}
err = ServeTCP(l, f)
err = HandleTCP(l, f)
return err
}
@ -88,6 +91,6 @@ func ListenAndServeUDP(addr string, f func(*Conn, *Msg)) os.Error {
if err != nil {
return err
}
err = ServeUDP(l, f)
err = HandleUDP(l, f)
return err
}

9
xfr.go
View File

@ -39,7 +39,7 @@ func (d *Conn) axfrRead(q *Msg, m chan Xfr) {
first := true
in := new(Msg)
for {
inb := make([]byte, MaxMsgSize)
inb := d.NewBuffer()
n, err := d.Read(inb)
if err != nil {
m <- Xfr{true, nil, err}
@ -128,12 +128,7 @@ func (d *Conn) ixfrRead(q *Msg, m chan Xfr) {
first := true
in := new(Msg)
for {
var inb []byte
if d.TCP != nil {
inb = make([]byte, MaxMsgSize)
} else {
inb = make([]byte, DefaultMsgSize)
}
inb := d.NewBuffer()
n, err := d.Read(inb)
if err != nil {
m <- Xfr{true, nil, err}