Bring funkensturm up to date for the new api
This commit is contained in:
parent
dd6d245488
commit
61925e2002
|
@ -5,8 +5,8 @@ supported. DNSSEC types too.
|
||||||
EDNS0 is (see edns.go), UDP/TCP queries, TSIG, AXFR (and IXFR probably)
|
EDNS0 is (see edns.go), UDP/TCP queries, TSIG, AXFR (and IXFR probably)
|
||||||
too. Both client and server side programming is supported.
|
too. Both client and server side programming is supported.
|
||||||
|
|
||||||
Sample programs can be found in the _examples directory. They can
|
Sample programs can be found in the `_examples` directory. They can
|
||||||
be build with: make examples (after the dns package has been installed)
|
be build with: `make examples` (after the dns package has been installed)
|
||||||
|
|
||||||
The major omission at the moment is parsing Resource Records from
|
The major omission at the moment is parsing Resource Records from
|
||||||
strings. (i.e. supporting the RFC 1035 zone file format).
|
strings. (i.e. supporting the RFC 1035 zone file format).
|
||||||
|
@ -15,9 +15,10 @@ Also the IPv6 support needs to be tested
|
||||||
Everything else should be present and working. If not, drop me an email.
|
Everything else should be present and working. If not, drop me an email.
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
|
|
||||||
Miek Gieben - 2010, 2011 - miek@miek.nl
|
Miek Gieben - 2010, 2011 - miek@miek.nl
|
||||||
|
|
||||||
Supported RFCs and features include:
|
## Supported RFCs and features include:
|
||||||
|
|
||||||
* 1034/1035 - DNS standard
|
* 1034/1035 - DNS standard
|
||||||
* 1982 - Serial Arithmetic
|
* 1982 - Serial Arithmetic
|
||||||
|
@ -37,11 +38,12 @@ Supported RFCs and features include:
|
||||||
* 4255 - SSHFP
|
* 4255 - SSHFP
|
||||||
* 4408 - SPF
|
* 4408 - SPF
|
||||||
* 5001 - NSID
|
* 5001 - NSID
|
||||||
* 5155 - NSEC -- todo
|
* 5155 - NSEC
|
||||||
* 5936 - AXFR
|
* 5936 - AXFR
|
||||||
|
|
||||||
Loosely based upon:
|
## Loosely based upon:
|
||||||
* ldns
|
|
||||||
* NSD
|
* `ldns`
|
||||||
* Net::DNS
|
* `NSD`
|
||||||
* GRONG
|
* `Net::DNS`
|
||||||
|
* `GRONG`
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dns"
|
"dns"
|
||||||
"dns/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
|
@ -26,17 +25,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(m *dns.Msg, ok bool) *dns.Msg {
|
func send(m *dns.Msg, ok bool) (out *dns.Msg) {
|
||||||
switch ok {
|
switch ok {
|
||||||
case true, false:
|
case true, false:
|
||||||
var in resolver.Msg
|
|
||||||
for _, r := range qr {
|
for _, r := range qr {
|
||||||
r <- resolver.Msg{m, nil, nil}
|
out, _ = r.Query(m)
|
||||||
in = <-r
|
|
||||||
}
|
}
|
||||||
return in.Dns // return the last
|
return
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the configration
|
// Return the configration
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"dns"
|
"dns"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
"dns/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const NSECDELAY = 1 * 1e9 // 1 second, meaning 1 qps (smaller means higher qps)
|
const NSECDELAY = 1 * 1e9 // 1 second, meaning 1 qps (smaller means higher qps)
|
||||||
|
@ -47,7 +46,7 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
return m, ok
|
return m, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func delay(m *dns.Msg, ok bool) *dns.Msg {
|
func delay(m *dns.Msg, ok bool) (out *dns.Msg) {
|
||||||
var ok1 bool
|
var ok1 bool
|
||||||
switch ok {
|
switch ok {
|
||||||
case true:
|
case true:
|
||||||
|
@ -55,26 +54,21 @@ func delay(m *dns.Msg, ok bool) *dns.Msg {
|
||||||
if !ok1 {
|
if !ok1 {
|
||||||
fmt.Fprintf(os.Stderr, "Info: Dropping: too often\n")
|
fmt.Fprintf(os.Stderr, "Info: Dropping: too often\n")
|
||||||
time.Sleep(NSECDELAY)
|
time.Sleep(NSECDELAY)
|
||||||
return nil
|
return
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stderr, "Info: Ok: let it through\n")
|
fmt.Fprintf(os.Stderr, "Info: Ok: let it through\n")
|
||||||
var in resolver.Msg
|
|
||||||
for _, r := range qr {
|
for _, r := range qr {
|
||||||
r <- resolver.Msg{m, nil, nil}
|
out, _ = r.Query(m)
|
||||||
in = <-r
|
|
||||||
}
|
}
|
||||||
return in.Dns
|
return
|
||||||
}
|
}
|
||||||
case false:
|
case false:
|
||||||
var in resolver.Msg
|
|
||||||
for _, r := range qr {
|
for _, r := range qr {
|
||||||
r <- resolver.Msg{m, nil, nil}
|
out, _ = r.Query(m)
|
||||||
in = <-r
|
|
||||||
}
|
}
|
||||||
return in.Dns
|
return
|
||||||
return in.Dns
|
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the configration
|
// Return the configration
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"dns"
|
"dns"
|
||||||
"dns/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
|
@ -26,17 +25,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(m *dns.Msg, ok bool) *dns.Msg {
|
func send(m *dns.Msg, ok bool) (out *dns.Msg) {
|
||||||
switch ok {
|
switch ok {
|
||||||
case true, false:
|
case true, false:
|
||||||
var in resolver.Msg
|
|
||||||
for _, r := range qr {
|
for _, r := range qr {
|
||||||
r <- resolver.Msg{m, nil, nil}
|
out, _ = r.Query(m)
|
||||||
in = <-r
|
|
||||||
}
|
}
|
||||||
return in.Dns
|
return
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the configration
|
// Return the configration
|
||||||
|
|
|
@ -7,7 +7,6 @@ package main
|
||||||
// We could also use one 1 key for multiple domains.
|
// We could also use one 1 key for multiple domains.
|
||||||
import (
|
import (
|
||||||
"dns"
|
"dns"
|
||||||
"dns/resolver"
|
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -59,17 +58,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(m *dns.Msg, ok bool) *dns.Msg {
|
func send(m *dns.Msg, ok bool) (out *dns.Msg) {
|
||||||
switch ok {
|
switch ok {
|
||||||
case true, false:
|
case true, false:
|
||||||
var in resolver.Msg
|
|
||||||
for _, r := range qr {
|
for _, r := range qr {
|
||||||
r <- resolver.Msg{m, nil, nil}
|
out, _ = r.Query(m)
|
||||||
in = <-r
|
|
||||||
}
|
}
|
||||||
return in.Dns // return the last
|
return
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var pubkey *dns.RR_DNSKEY
|
var pubkey *dns.RR_DNSKEY
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
type server dns.Server
|
type server dns.Server
|
||||||
|
|
||||||
// Define a slice of channels for the resolver for sending the queries somewhere else.
|
// Define a slice of channels for the resolver for sending the queries somewhere else.
|
||||||
var qr []chan resolver.Msg
|
var qr []*dns.Resolver
|
||||||
|
|
||||||
// The configuration of Funkensturm
|
// The configuration of Funkensturm
|
||||||
var f *Funkensturm
|
var f *Funkensturm
|
||||||
|
@ -151,7 +151,7 @@ func doFunkensturm(i []byte) ([]byte, os.Error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
func (s *server) ReplyUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
||||||
out, err := doFunkensturm(i)
|
out, err := doFunkensturm(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
|
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
|
||||||
|
@ -159,12 +159,12 @@ func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if out != nil {
|
if out != nil {
|
||||||
responder.SendUDP(out, c, a)
|
dns.SendUDP(out, c, a)
|
||||||
}
|
}
|
||||||
// nothing is send back
|
// nothing is send back
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ResponderTCP(c *net.TCPConn, i []byte) {
|
func (s *server) ReplyTCP(c *net.TCPConn, a net.Addr, i []byte) {
|
||||||
out, err := doFunkensturm(i)
|
out, err := doFunkensturm(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
|
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
|
||||||
|
@ -172,7 +172,7 @@ func (s *server) ResponderTCP(c *net.TCPConn, i []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if out != nil {
|
if out != nil {
|
||||||
responder.SendTCP(out, c)
|
dns.SendTCP(out, c, a)
|
||||||
}
|
}
|
||||||
// nothing is send back
|
// nothing is send back
|
||||||
}
|
}
|
||||||
|
@ -180,10 +180,10 @@ func (s *server) ResponderTCP(c *net.TCPConn, i []byte) {
|
||||||
// split 127.0.0.1:53 into components
|
// split 127.0.0.1:53 into components
|
||||||
// TODO IPv6
|
// TODO IPv6
|
||||||
func splitAddrPort(s string) (a, p string) {
|
func splitAddrPort(s string) (a, p string) {
|
||||||
items := strings.Split(s, ":", 2)
|
items := strings.Split(s, ":", 2)
|
||||||
a = items[0]
|
a = items[0]
|
||||||
p = items[1]
|
p = items[1]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -197,15 +197,13 @@ func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
resolvers := strings.Split(*rserver, ",", -1)
|
resolvers := strings.Split(*rserver, ",", -1)
|
||||||
qr = make([]chan resolver.Msg, len(resolvers))
|
qr = make([]*dns.Resolver, len(resolvers))
|
||||||
for i, ra := range resolvers {
|
for i, ra := range resolvers {
|
||||||
addr, port := splitAddrPort(ra)
|
addr, port := splitAddrPort(ra)
|
||||||
// TODO error checking
|
r := new(dns.Resolver)
|
||||||
// The resolver(s)
|
|
||||||
r := new(resolver.Resolver)
|
|
||||||
r.Servers = []string{addr}
|
r.Servers = []string{addr}
|
||||||
r.Port = port
|
r.Port = port
|
||||||
qr[i] = r.NewQuerier() // connect to global qr[i
|
qr[i] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
f = funkensturm()
|
f = funkensturm()
|
||||||
|
@ -215,14 +213,10 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The responder
|
// The server
|
||||||
addr, port := splitAddrPort(*sserver)
|
|
||||||
s := new(responder.Server)
|
|
||||||
s.Address = addr
|
|
||||||
s.Port = port
|
|
||||||
var srv *server
|
var srv *server
|
||||||
rs := make(chan os.Error)
|
quit := make(chan bool)
|
||||||
go s.NewResponder(srv, rs)
|
go dns.ListenAndServe(*sserver, srv, quit)
|
||||||
|
|
||||||
forever:
|
forever:
|
||||||
for {
|
for {
|
||||||
|
@ -230,15 +224,9 @@ forever:
|
||||||
select {
|
select {
|
||||||
case <-signal.Incoming:
|
case <-signal.Incoming:
|
||||||
println("Signal received, stopping")
|
println("Signal received, stopping")
|
||||||
rs <- nil // shutdown responder
|
quit <- true
|
||||||
break forever
|
break forever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(rs)
|
close(quit)
|
||||||
|
|
||||||
// And the resolvers
|
|
||||||
for _, q := range qr {
|
|
||||||
q <- resolver.Msg{}
|
|
||||||
<-q
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
308
resolver.go
308
resolver.go
|
@ -42,7 +42,7 @@ type Resolver struct {
|
||||||
Rotate bool // round robin among servers -- TODO
|
Rotate bool // round robin among servers -- TODO
|
||||||
Tcp bool // use TCP
|
Tcp bool // use TCP
|
||||||
Mangle func([]byte) []byte // mangle the packet
|
Mangle func([]byte) []byte // mangle the packet
|
||||||
// rtt map[string]int server->int, smaller is faster 0, -1 is unreacheble
|
// rtt map[string]int server->int, smaller is faster 0, -1 is unreacheble
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a query using *res, q holds the question to be asked.
|
// Send a query using *res, q holds the question to be asked.
|
||||||
|
@ -50,136 +50,136 @@ type Resolver struct {
|
||||||
func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
|
func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
|
||||||
var (
|
var (
|
||||||
c net.Conn
|
c net.Conn
|
||||||
in *Msg
|
in *Msg
|
||||||
port string
|
port string
|
||||||
)
|
)
|
||||||
if len(res.Servers) == 0 {
|
if len(res.Servers) == 0 {
|
||||||
return nil, &Error{Error: "No servers defined"}
|
return nil, &Error{Error: "No servers defined"}
|
||||||
}
|
}
|
||||||
// len(res.Server) == 0 can be perfectly valid, when setting up the resolver
|
// len(res.Server) == 0 can be perfectly valid, when setting up the resolver
|
||||||
// It is now
|
// It is now
|
||||||
if res.Port == "" {
|
if res.Port == "" {
|
||||||
port = "53"
|
port = "53"
|
||||||
} else {
|
} else {
|
||||||
port = res.Port
|
port = res.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
if q.Id == 0 {
|
if q.Id == 0 {
|
||||||
// No Id sed, set it
|
// No Id sed, set it
|
||||||
q.SetId()
|
q.SetId()
|
||||||
}
|
}
|
||||||
sending, ok := q.Pack()
|
sending, ok := q.Pack()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &Error{Error: packErr}
|
return nil, &Error{Error: packErr}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(res.Servers); i++ {
|
for i := 0; i < len(res.Servers); i++ {
|
||||||
server := res.Servers[i] + ":" + port
|
server := res.Servers[i] + ":" + port
|
||||||
if res.Tcp {
|
if res.Tcp {
|
||||||
c, err = net.Dial("tcp", "", server)
|
c, err = net.Dial("tcp", "", server)
|
||||||
} else {
|
} else {
|
||||||
c, err = net.Dial("udp", "", server)
|
c, err = net.Dial("udp", "", server)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if res.Tcp {
|
if res.Tcp {
|
||||||
in, err = exchangeTCP(c, sending, res, true)
|
in, err = exchangeTCP(c, sending, res, true)
|
||||||
} else {
|
} else {
|
||||||
in, err = exchangeUDP(c, sending, res, true)
|
in, err = exchangeUDP(c, sending, res, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check id in.id != out.id, should be checked in the client!
|
// Check id in.id != out.id, should be checked in the client!
|
||||||
c.Close()
|
c.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// q holds the inital query
|
// q holds the inital query
|
||||||
// channel is closed by AXfr
|
// channel is closed by AXfr
|
||||||
func (res *Resolver) Axfr(q *Msg, m chan *Msg) {
|
func (res *Resolver) Axfr(q *Msg, m chan *Msg) {
|
||||||
var port string
|
var port string
|
||||||
var err os.Error
|
var err os.Error
|
||||||
var in *Msg
|
var in *Msg
|
||||||
if res.Port == "" {
|
if res.Port == "" {
|
||||||
port = "53"
|
port = "53"
|
||||||
} else {
|
} else {
|
||||||
port = res.Port
|
port = res.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = err // TODO(mg)
|
var _ = err // TODO(mg)
|
||||||
|
|
||||||
if q.Id == 0 {
|
if q.Id == 0 {
|
||||||
q.SetId()
|
q.SetId()
|
||||||
}
|
|
||||||
|
|
||||||
sending, ok := q.Pack()
|
|
||||||
if !ok {
|
|
||||||
m <- nil
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SERVER:
|
sending, ok := q.Pack()
|
||||||
for i := 0; i < len(res.Servers); i++ {
|
if !ok {
|
||||||
server := res.Servers[i] + ":" + port
|
m <- nil
|
||||||
c, cerr := net.Dial("tcp", "", server)
|
return
|
||||||
if cerr != nil {
|
}
|
||||||
err = cerr
|
|
||||||
continue SERVER
|
|
||||||
}
|
|
||||||
first := true
|
|
||||||
// Start the AXFR
|
|
||||||
for {
|
|
||||||
if first {
|
|
||||||
in, cerr = exchangeTCP(c, sending, res, true)
|
|
||||||
} else {
|
|
||||||
in, err = exchangeTCP(c, sending, res, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cerr != nil {
|
SERVER:
|
||||||
// Failed to send, try the next
|
for i := 0; i < len(res.Servers); i++ {
|
||||||
err = cerr
|
server := res.Servers[i] + ":" + port
|
||||||
c.Close()
|
c, cerr := net.Dial("tcp", "", server)
|
||||||
continue SERVER
|
if cerr != nil {
|
||||||
}
|
err = cerr
|
||||||
if in.Id != q.Id {
|
continue SERVER
|
||||||
m <- nil
|
}
|
||||||
return
|
first := true
|
||||||
}
|
// Start the AXFR
|
||||||
|
for {
|
||||||
|
if first {
|
||||||
|
in, cerr = exchangeTCP(c, sending, res, true)
|
||||||
|
} else {
|
||||||
|
in, err = exchangeTCP(c, sending, res, false)
|
||||||
|
}
|
||||||
|
|
||||||
if first {
|
if cerr != nil {
|
||||||
if !checkSOA(in, true) {
|
// Failed to send, try the next
|
||||||
c.Close()
|
err = cerr
|
||||||
continue SERVER
|
c.Close()
|
||||||
}
|
continue SERVER
|
||||||
m <- in
|
}
|
||||||
first = !first
|
if in.Id != q.Id {
|
||||||
}
|
m <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !first {
|
if first {
|
||||||
if !checkSOA(in, false) {
|
if !checkSOA(in, true) {
|
||||||
// Soa record not the last one
|
c.Close()
|
||||||
m <- in
|
continue SERVER
|
||||||
continue
|
}
|
||||||
} else {
|
m <- in
|
||||||
c.Close()
|
first = !first
|
||||||
m <- in
|
}
|
||||||
close(m)
|
|
||||||
return
|
if !first {
|
||||||
}
|
if !checkSOA(in, false) {
|
||||||
}
|
// Soa record not the last one
|
||||||
}
|
m <- in
|
||||||
println("Should never be reached")
|
continue
|
||||||
return
|
} else {
|
||||||
}
|
c.Close()
|
||||||
close(m)
|
m <- in
|
||||||
|
close(m)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println("Should never be reached")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
close(m)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
|
||||||
for a := 0; a < attempts; a++ {
|
for a := 0; a < attempts; a++ {
|
||||||
// only send something when told so
|
// only send something when told so
|
||||||
if send {
|
if send {
|
||||||
err := sendTCP(m,c)
|
err := sendTCP(m, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if e, ok := err.(net.Error); ok && e.Timeout() {
|
if e, ok := err.(net.Error); ok && e.Timeout() {
|
||||||
continue
|
continue
|
||||||
|
@ -278,66 +278,66 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
|
||||||
return nil, &Error{Error: servErr}
|
return nil, &Error{Error: servErr}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendUDP(m []byte,c net.Conn) os.Error {
|
func sendUDP(m []byte, c net.Conn) os.Error {
|
||||||
_, err := c.Write(m)
|
_, err := c.Write(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func recvUDP(c net.Conn) ([]byte, os.Error) {
|
func recvUDP(c net.Conn) ([]byte, os.Error) {
|
||||||
m := make([]byte, DefaultMsgSize) // More than enough???
|
m := make([]byte, DefaultMsgSize) // More than enough???
|
||||||
n, err := c.Read(m)
|
n, err := c.Read(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m = m[:n]
|
m = m[:n]
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTCP(m []byte, c net.Conn) os.Error {
|
func sendTCP(m []byte, c net.Conn) os.Error {
|
||||||
l := make([]byte, 2)
|
l := make([]byte, 2)
|
||||||
l[0] = byte(len(m) >> 8)
|
l[0] = byte(len(m) >> 8)
|
||||||
l[1] = byte(len(m))
|
l[1] = byte(len(m))
|
||||||
// First we send the length
|
// First we send the length
|
||||||
_, err := c.Write(l)
|
_, err := c.Write(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// And the the message
|
// And the the message
|
||||||
_, err = c.Write(m)
|
_, err = c.Write(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func recvTCP(c net.Conn) ([]byte, os.Error) {
|
func recvTCP(c net.Conn) ([]byte, os.Error) {
|
||||||
l := make([]byte, 2) // receiver length
|
l := make([]byte, 2) // receiver length
|
||||||
// The server replies with two bytes length
|
// The server replies with two bytes length
|
||||||
_, err := c.Read(l)
|
_, err := c.Read(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,err
|
return nil, err
|
||||||
}
|
}
|
||||||
length := uint16(l[0])<<8 | uint16(l[1])
|
length := uint16(l[0])<<8 | uint16(l[1])
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return nil, &Error{Error: "received nil msg length", Server: c.RemoteAddr().String()}
|
return nil, &Error{Error: "received nil msg length", Server: c.RemoteAddr().String()}
|
||||||
}
|
}
|
||||||
m := make([]byte, length)
|
m := make([]byte, length)
|
||||||
n, cerr := c.Read(m)
|
n, cerr := c.Read(m)
|
||||||
if cerr != nil {
|
if cerr != nil {
|
||||||
return nil, cerr
|
return nil, cerr
|
||||||
}
|
}
|
||||||
i := n
|
i := n
|
||||||
if i < int(length) {
|
if i < int(length) {
|
||||||
n, err = c.Read(m[i:])
|
n, err = c.Read(m[i:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
i += n
|
i += n
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if he SOA record exists in the Answer section of
|
// Check if he SOA record exists in the Answer section of
|
||||||
|
|
Loading…
Reference in New Issue