fixed
This commit is contained in:
commit
4ad4de1178
8
TODO
8
TODO
|
@ -1,13 +1,13 @@
|
|||
|
||||
Guidelines for the API:
|
||||
o symmetrical, client side should be mirrored in the server
|
||||
o clean, small API
|
||||
o fast data structures (rb-tree, when they come available)
|
||||
o api-use should be self documenting
|
||||
o Functionally of the net package is not be reimplemented (unless
|
||||
really needed)
|
||||
|
||||
o zone structure -- only as rb-tree
|
||||
|
||||
o build simple: just query function, built on the cool stuff
|
||||
o make questions fqdns -- add last dot
|
||||
o zone structure -- only as rb-tree or other radix tree
|
||||
o compression (only ownernames?)
|
||||
|
||||
o Key2DS, also for offline keys -- need to parse them ofcourse
|
||||
|
|
|
@ -89,10 +89,10 @@ Flags:
|
|||
m.MsgHdr.RecursionDesired = *rd
|
||||
m.Question = make([]dns.Question, 1)
|
||||
if *dnssec || *nsid {
|
||||
opt := new(dns.RR_OPT)
|
||||
opt := new(dns.RR_OPT)
|
||||
opt.SetDo()
|
||||
opt.SetVersion(0)
|
||||
opt.SetUDPSize(dns.DefaultMsgSize)
|
||||
opt.SetVersion(0)
|
||||
opt.SetUDPSize(dns.DefaultMsgSize)
|
||||
if *nsid {
|
||||
opt.SetNsid("")
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ func shortMsg(in *dns.Msg) *dns.Msg {
|
|||
for i := 0; i < len(in.Extra); i++ {
|
||||
in.Extra[i] = shortRR(in.Extra[i])
|
||||
}
|
||||
return in
|
||||
return in
|
||||
}
|
||||
|
||||
func shortRR(r dns.RR) dns.RR {
|
||||
|
@ -138,8 +138,8 @@ func shortRR(r dns.RR) dns.RR {
|
|||
t.PublicKey = "( ... )"
|
||||
case *dns.RR_RRSIG:
|
||||
t.Signature = "( ... )"
|
||||
case *dns.RR_NSEC3:
|
||||
t.Salt = "-" // nobody cares
|
||||
case *dns.RR_NSEC3:
|
||||
t.Salt = "-" // nobody cares
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
40
dns.go
40
dns.go
|
@ -16,24 +16,30 @@
|
|||
// The package dns supports querying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0,
|
||||
// dynamic updates, notifies and DNSSEC validation/signing.
|
||||
//
|
||||
// Querying the DNS is done by using a Resolver structure. Basic use pattern for creating
|
||||
// Querying the DNS is done by using the Conn structure. Basic use pattern for creating
|
||||
// a resolver:
|
||||
//
|
||||
// res := new(Resolver)
|
||||
// res.Servers = []string{"127.0.0.1"}
|
||||
// func handle(d *Conn, m *Msg, q chan Query) { /* handle query */ }
|
||||
//
|
||||
// in := make(chan Query)
|
||||
// out := QueryAndServeUDP(in, handle)
|
||||
// d := new(Conn)
|
||||
// d.RemoteAddr = "8.8.8.8:53"
|
||||
// m := new(Msg)
|
||||
// m.MsgHdr.Recursion_desired = true
|
||||
// m.Question = make([]Question, 1)
|
||||
// m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET}
|
||||
// in, err := res.Query(m)
|
||||
//
|
||||
// Server side programming is also supported.
|
||||
// in <- Query{Msg: m, Conn: d} // Send query
|
||||
// reply := <-out // Listen for replie(s)
|
||||
//
|
||||
// Server side programming is also supported also by using a Conn structure.
|
||||
// Basic use pattern for creating an UDP DNS server:
|
||||
//
|
||||
// func handle(d *dns.Conn, i *dns.Msg) { /* handle request */ }
|
||||
// func handle(d *Conn, m *Msg) { /* handle request */ }
|
||||
//
|
||||
// func listen(addr string, e chan os.Error) {
|
||||
// err := dns.ListenAndServeUDP(addr, handle)
|
||||
// err := ListenAndServeUDP(addr, handle)
|
||||
// e <- err
|
||||
// }
|
||||
// err := make(chan os.Error)
|
||||
|
@ -80,13 +86,14 @@ type Conn struct {
|
|||
// The current TCP connection.
|
||||
TCP *net.TCPConn
|
||||
|
||||
// The remote side of the connection.
|
||||
// The remote side of open the connection.
|
||||
Addr net.Addr
|
||||
|
||||
// The remote port number of the connection.
|
||||
// The remote port number of open the connection.
|
||||
Port int
|
||||
|
||||
// If TSIG is used, this holds all the information.
|
||||
// If unused is must be nil.
|
||||
Tsig *Tsig
|
||||
|
||||
// Timeout in sec before giving up on a connection.
|
||||
|
@ -95,6 +102,15 @@ type Conn struct {
|
|||
// Number of attempts to try to Read/Write from/to a
|
||||
// connection.
|
||||
Attempts int
|
||||
|
||||
// The remote addr which is going to be dialed.
|
||||
RemoteAddr string
|
||||
|
||||
// Mangle the packet before writing it be feeding
|
||||
// it through this function.
|
||||
Mangle func([]byte) []byte
|
||||
|
||||
// rtt times?
|
||||
}
|
||||
|
||||
// Dial connects to the remote address raddr on the network net.
|
||||
|
@ -258,6 +274,11 @@ func (d *Conn) Write(p []byte) (n int, err os.Error) {
|
|||
} else {
|
||||
attempts = d.Attempts
|
||||
}
|
||||
// Mangle before TSIG?
|
||||
if d.Mangle != nil {
|
||||
p = d.Mangle(p)
|
||||
}
|
||||
|
||||
d.SetTimeout()
|
||||
if d.Tsig != nil {
|
||||
// Create a new buffer with the TSIG added.
|
||||
|
@ -366,7 +387,6 @@ func (d *Conn) Exchange(request []byte, nosend bool) (reply []byte, err os.Error
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
// Layer violation to save memory. Its okay then...
|
||||
reply = d.NewBuffer()
|
||||
n, err = d.Read(reply)
|
||||
if err != nil {
|
||||
|
|
1
msg.go
1
msg.go
|
@ -44,6 +44,7 @@ var (
|
|||
ErrSigGen os.Error = &Error{Error: "bad signature generation"}
|
||||
ErrAuth os.Error = &Error{Error: "bad authentication"}
|
||||
ErrXfrSoa os.Error = &Error{Error: "no SOA seen"}
|
||||
ErrHandle os.Error = &Error{Error: "the handle is nill"}
|
||||
)
|
||||
|
||||
// A manually-unpacked version of (id, bits).
|
||||
|
|
77
resolver.go
77
resolver.go
|
@ -12,6 +12,74 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Query is used to communicate with the Query* functions.
|
||||
type Query struct {
|
||||
// The query message.
|
||||
Msg *Msg
|
||||
// A Conn. Its only required to fill out Conn.RemoteAddr.
|
||||
// The rest of the structure is filled in by the Query Functions.
|
||||
Conn *Conn
|
||||
// Any erros when querying are returned in Err. The caller
|
||||
// should just set this to nil.
|
||||
Err os.Error
|
||||
}
|
||||
|
||||
// QueryUDP handles one query. It reads an incoming request from
|
||||
// the in channel. The function f is executed in a seperate
|
||||
// goroutine and performs the actual UDP query.
|
||||
func QueryUDP(in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||
query("udp", in, out, f)
|
||||
}
|
||||
|
||||
// QueryTCP handles one query. It reads an incoming request from
|
||||
// the in channel. The function f is executed in a seperate
|
||||
// goroutine and performas the actual TCP query.
|
||||
func QueryTCP(in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||
query("tcp", in, out, f)
|
||||
}
|
||||
|
||||
// helper function.
|
||||
func query(n string, in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||
for {
|
||||
select {
|
||||
case q := <-in:
|
||||
c, err := net.Dial(n, "", q.Conn.RemoteAddr)
|
||||
if err != nil {
|
||||
//out <- nil
|
||||
}
|
||||
if n == "tcp" {
|
||||
q.Conn.SetTCPConn(c.(*net.TCPConn), nil)
|
||||
} else {
|
||||
q.Conn.SetUDPConn(c.(*net.UDPConn), nil)
|
||||
}
|
||||
if f == nil {
|
||||
out <- Query{Err: ErrHandle}
|
||||
} else {
|
||||
go f(q.Conn, q.Msg, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
// QueryAndServeTCP listens for incoming requests on channel in and
|
||||
// then calls QueryTCP with f to the handle the request.
|
||||
// It returns a channel on which the response is returned.
|
||||
func QueryAndServeTCP(in chan Query, f func(*Conn, *Msg, chan Query)) chan Query {
|
||||
out := make(chan Query)
|
||||
go QueryTCP(in, out, f)
|
||||
return out
|
||||
}
|
||||
|
||||
// QueryAndServeUDP listens for incoming requests on channel in and
|
||||
// then calls QueryUDP with f to the handle the request.
|
||||
// It returns a channel on which the response is returned.
|
||||
func QueryAndServeUDP(in chan Query, f func(*Conn, *Msg, chan Query)) chan Query {
|
||||
out := make(chan Query)
|
||||
go QueryUDP(in, out, f)
|
||||
return out
|
||||
}
|
||||
|
||||
type Resolver struct {
|
||||
Servers []string // servers to use
|
||||
Search []string // suffixes to append to local name (not implemented)
|
||||
|
@ -48,7 +116,7 @@ func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
|
|||
}
|
||||
|
||||
for i := 0; i < len(res.Servers); i++ {
|
||||
var d *Conn
|
||||
var d *Conn
|
||||
server := res.Servers[i] + ":" + port
|
||||
t := time.Nanoseconds()
|
||||
if res.Tcp {
|
||||
|
@ -69,7 +137,7 @@ func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
|
|||
}
|
||||
in.Unpack(inb) // Discard error.
|
||||
res.Rtt[server] = time.Nanoseconds() - t
|
||||
d.Close()
|
||||
d.Close()
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -103,13 +171,10 @@ func (res *Resolver) XfrTsig(q *Msg, t *Tsig, m chan Xfr) {
|
|||
Server:
|
||||
for i := 0; i < len(res.Servers); i++ {
|
||||
server := res.Servers[i] + ":" + port
|
||||
c, err := net.Dial("tcp", "", server)
|
||||
d, err := Dial("tcp", "", server)
|
||||
if err != nil {
|
||||
continue Server
|
||||
}
|
||||
d := new(Conn)
|
||||
d.TCP = c.(*net.TCPConn)
|
||||
d.Addr = d.TCP.RemoteAddr()
|
||||
d.Tsig = t
|
||||
|
||||
_, err = d.Write(sending)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// DNS server implementation
|
||||
// DNS server implementation.
|
||||
|
||||
package dns
|
||||
|
||||
|
@ -25,6 +25,7 @@ func HandleUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error {
|
|||
m = m[:n]
|
||||
|
||||
d := new(Conn)
|
||||
// Use the remote addr as we got from ReadFromUDP
|
||||
d.SetUDPConn(l, addr)
|
||||
|
||||
msg := new(Msg)
|
||||
|
@ -66,7 +67,7 @@ func HandleTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error {
|
|||
// connections. The function f may not be nil.
|
||||
func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error {
|
||||
if f == nil {
|
||||
return &Error{Error: "The handle function may not be nil"}
|
||||
return ErrHandle
|
||||
}
|
||||
a, err := net.ResolveTCPAddr(addr)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue