2011-02-09 07:25:01 +11:00
|
|
|
// Copyright 2011 Miek Gieben. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// DNS server implementation
|
|
|
|
|
|
|
|
// Package responder implements a DNS server. Any nameserver needs to implement
|
|
|
|
// the Responder interface to get things going. Each incoming query is handled
|
|
|
|
// in a seperate goroutine.
|
|
|
|
//
|
|
|
|
// Typical usage of the package:
|
|
|
|
//
|
|
|
|
// type myserv Server
|
|
|
|
// func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { /* UDP reply */ }
|
|
|
|
// func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { /* TCP reply */}
|
|
|
|
//
|
|
|
|
// s := new(Server) // create new sever
|
|
|
|
// s.Address = "127.0.0.1" // listen address
|
|
|
|
// s.Port = "8053" // listen port
|
|
|
|
// var m *myserv
|
|
|
|
// ch :=make(chan bool)
|
|
|
|
// go s.NewResponder(m, ch) // start the responder
|
2011-02-09 07:26:40 +11:00
|
|
|
package dns
|
2011-02-09 07:25:01 +11:00
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"net"
|
|
|
|
)
|
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
// Wrap request in this struct
|
|
|
|
type Request struct {
|
|
|
|
Tcp bool // True for tcp, false for udp
|
|
|
|
Buf []byte // The received message
|
|
|
|
Addr net.Addr // Remote site
|
|
|
|
UDPConn *net.UDPConn // Connection for UDP
|
|
|
|
TCPConn *net.TCPConn // Connection for TCP
|
|
|
|
Error os.Error // Any errors that are found
|
2011-02-09 07:49:37 +11:00
|
|
|
}
|
|
|
|
|
2011-02-09 07:25:01 +11:00
|
|
|
// Every nameserver implements the Hander interface. It defines
|
|
|
|
// the kind of nameserver
|
|
|
|
type Handler interface {
|
|
|
|
// Receives the raw message content and writes back
|
|
|
|
// an UDP response. An UDP connection needs a remote
|
|
|
|
// address to write to. ServeUDP() must take care of sending
|
|
|
|
// any response back to the requestor.
|
2011-02-09 08:15:21 +11:00
|
|
|
ReplyUDP(c *net.UDPConn, a net.Addr, in []byte)
|
2011-02-09 07:25:01 +11:00
|
|
|
// Receives the raw message content and writes back
|
|
|
|
// a TCP response. A TCP connection does need to
|
|
|
|
// know explicitly be told the remote address. ServeTCP() must
|
|
|
|
// take care of sending back a response to the requestor.
|
2011-02-10 03:59:06 +11:00
|
|
|
ReplyTCP(c *net.TCPConn, a net.Addr, in []byte)
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
func accepterUDP(l *net.UDPConn, ch chan *Request, quit chan bool) {
|
2011-02-09 07:25:01 +11:00
|
|
|
for {
|
2011-02-10 03:59:06 +11:00
|
|
|
select {
|
|
|
|
case <-quit:
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
r := new(Request)
|
|
|
|
r.Tcp = false
|
|
|
|
m := make([]byte, DefaultMsgSize)
|
|
|
|
n, radd, err := l.ReadFromUDP(m)
|
|
|
|
if err != nil {
|
|
|
|
r.Error = err
|
|
|
|
ch <- r
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m = m[:n]
|
|
|
|
r.Buf = m
|
|
|
|
r.Addr = radd
|
|
|
|
r.UDPConn = l
|
|
|
|
ch <- r
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
|
|
|
}
|
2011-02-10 03:59:06 +11:00
|
|
|
panic("not reached")
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
func accepterTCP(l *net.TCPListener, ch chan *Request, quit chan bool) {
|
|
|
|
b := make([]byte, 2)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-quit:
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
r := new(Request)
|
|
|
|
r.Tcp = true
|
|
|
|
c, err := l.AcceptTCP()
|
|
|
|
if err != nil {
|
|
|
|
r.Error = err
|
|
|
|
ch <- r
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
n, cerr := c.Read(b)
|
|
|
|
if cerr != nil {
|
|
|
|
r.Error = cerr
|
|
|
|
ch <- r
|
|
|
|
continue
|
|
|
|
}
|
2011-02-09 07:25:01 +11:00
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
length := uint16(b[0])<<8 | uint16(b[1])
|
|
|
|
if length == 0 {
|
|
|
|
r.Error = &Error{Error: "received nil msg length"}
|
|
|
|
ch <- r
|
|
|
|
}
|
|
|
|
m := make([]byte, length)
|
2011-02-09 07:25:01 +11:00
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
n, cerr = c.Read(m)
|
|
|
|
if cerr != nil {
|
|
|
|
r.Error = cerr
|
|
|
|
ch <- r
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
i := n
|
|
|
|
if i < int(length) {
|
|
|
|
n, err = c.Read(m[i:])
|
|
|
|
if err != nil {
|
|
|
|
r.Error = err
|
|
|
|
ch <- r
|
|
|
|
}
|
|
|
|
i += n
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
2011-02-10 03:59:06 +11:00
|
|
|
r.Buf = m
|
|
|
|
r.Addr = c.RemoteAddr()
|
|
|
|
r.TCPConn = c
|
|
|
|
ch <- r
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
2011-02-10 03:59:06 +11:00
|
|
|
}
|
|
|
|
panic("not reached")
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
|
|
|
|
2011-02-10 03:59:06 +11:00
|
|
|
func ListenAndServe(addr string, handler Handler, q chan bool) os.Error {
|
|
|
|
ta, err := net.ResolveTCPAddr(addr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
lt, err := net.ListenTCP("tcp", ta)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2011-02-09 07:25:01 +11:00
|
|
|
|
|
|
|
ua, err := net.ResolveUDPAddr(addr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2011-02-10 03:59:06 +11:00
|
|
|
lu, err := net.ListenUDP("udp", ua)
|
2011-02-09 07:25:01 +11:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2011-02-10 03:59:06 +11:00
|
|
|
|
|
|
|
rc := make(chan *Request)
|
|
|
|
qt := make(chan bool)
|
|
|
|
qu := make(chan bool)
|
|
|
|
go accepterTCP(lt, rc, qt)
|
|
|
|
go accepterUDP(lu, rc, qu)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-q:
|
|
|
|
/* quit received, lets stop */
|
|
|
|
lt.Close()
|
|
|
|
lu.Close()
|
|
|
|
qt <- true
|
|
|
|
qu <- true
|
|
|
|
case r:=<-rc:
|
|
|
|
/* request recieved */
|
|
|
|
if r.Tcp {
|
|
|
|
go handler.ReplyTCP(r.TCPConn, r.Addr, r.Buf)
|
|
|
|
} else {
|
|
|
|
go handler.ReplyUDP(r.UDPConn, r.Addr, r.Buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
2011-02-09 07:25:01 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send a buffer on the TCP connection.
|
|
|
|
func SendTCP(m []byte, c *net.TCPConn) os.Error {
|
|
|
|
l := make([]byte, 2)
|
|
|
|
l[0] = byte(len(m) >> 8)
|
|
|
|
l[1] = byte(len(m))
|
|
|
|
// First we send the length
|
|
|
|
_, err := c.Write(l)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// And the the message
|
|
|
|
_, err = c.Write(m)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a buffer to the remove address. Only here because
|
|
|
|
// of the symmetry with SendTCP().
|
|
|
|
func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error {
|
|
|
|
_, err := c.WriteTo(m, a)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|