miekg / dns Goto Github PK
View Code? Open in Web Editor NEWDNS library in Go
Home Page: https://miek.nl/2014/august/16/go-dns-package
License: BSD 3-Clause "New" or "Revised" License
DNS library in Go
Home Page: https://miek.nl/2014/august/16/go-dns-package
License: BSD 3-Clause "New" or "Revised" License
Yes, the result is not standards-compliant. But no, it shouldn't result in a panic.
func NewSOA(answeringServer string, hostmaster string) dns.RR {
return &dns.SOA{Hdr: dns.RR_Header{Name: answeringServer, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 12345},
Ns: answeringServer,
Mbox: hostmaster,
Serial: uint32(time.Now().Truncate(time.Hour).Unix()),
Refresh: 28800,
Retry: 7200,
Expire: 604800,
Minttl: 60,
}
}
func NameError(m, req *dns.Msg) {
//m.SetRcode(req, dns.RcodeNameError)
m.Ns = []dns.RR{NewSOA("local.dns.skydns.local.", "")} // <-------------- "" is the Hostmaster
m.Ns[0].Header().Ttl = 60 // s.config.MinTtl
// StatsNameErrorCount.Inc(1)
}
func main() {
m := new(dns.Msg)
// START header
m.Id = 33074
m.Response = true
m.Opcode = 0
m.Authoritative = true
m.Truncated = false // about to be set
m.RecursionDesired = true
m.RecursionAvailable = true
m.Zero = false
m.AuthenticatedData = false
m.CheckingDisabled = false
m.Rcode = 3
// END header
m.Compress = true // <-----------------
// question
m.Question = make([]dns.Question, 1)
m.Question[0] = dns.Question{"skydns.test.", dns.TypeNS, dns.ClassINET}
// EMPTY answer
// ns
NameError(m, nil)
// EMPTY extra
fmt.Println(m.Len())
}
I've run into this while testing SkyDNS. The corresponding entries in etcd went away resulting in an empty "Hostmaster" field.
Trying to compile godns with today's tip, I get many:
zscan.go:8: can't find import: text/scanner
It seems several packages moved to the toplevel. The attached patch addresses this. https://gist.github.com/1584838
I noticed that my server wasn't returning the 'aa' bit for NXDOMAIN replies. I use msg.SetRcode to setup that reply and that code sets Authoritative to false. Shouldn't it leave that bit alone?
// SetRcode creates an error packet suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
dns.MsgHdr.Rcode = rcode
dns.MsgHdr.Opcode = OpcodeQuery
dns.MsgHdr.Response = true
dns.MsgHdr.Authoritative = false
dns.MsgHdr.Id = request.MsgHdr.Id
dns.Question = make([]Question, 1)
dns.Question[0] = request.Question[0]
return dns
}
Or am I just doing it wrong? abh/geodns@45c00a7
[cookiemonster:] owens% uname -a1/RELEASE_X86_64 x86_64
Darwin cookiemonster.nysernet.org 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23
[cookiemonster:~] owens% go version
go version weekly.2012-03-13
Test case:
[cookiemonster:~] owens% chaos a.root-servers.net
panic: runtime error: index out of range
goroutine 1 [running]:
main.main()
/Users/owens/Projects/gocode/src/dns/ex/chaos/chaos.go:32 +0x3b3
goroutine 2 [syscall]:
created by runtime.main
/Users/owens/Projects/go/src/pkg/runtime/proc.c:221
goroutine 3 [chan receive]:
dns.(_Query).Query(0xf84004c620, 0x0)
/Users/owens/Projects/gocode/src/dns/client.go:176 +0xa4
dns.(_Query).ListenAndQuery(0xf84004c620, 0xf84004c620, 0x2571, 0x0)
/Users/owens/Projects/gocode/src/dns/client.go:191 +0x3b
created by dns.ListenAndQuery
/Users/owens/Projects/gocode/src/dns/client.go:199 +0x5c
goroutine 6 [syscall]:
syscall.Syscall6()
/Users/owens/Projects/go/src/pkg/syscall/asm_darwin_amd64.s:38 +0x5
syscall.kevent(0x7, 0x0, 0x0, 0xf84006d188, 0x10000000a, ...)
/Users/owens/Projects/go/src/pkg/syscall/zsyscall_darwin_amd64.go:199 +0x88
syscall.Kevent(0xf800000007, 0x0, 0x0, 0xf84006d188, 0xa0000000a, ...)
/Users/owens/Projects/go/src/pkg/syscall/syscall_bsd.go:538 +0xa4
net.(_pollster).WaitFD(0xf84006d180, 0xf840088000, 0x68189710, 0x0, 0x0, ...)
/Users/owens/Projects/go/src/pkg/net/fd_darwin.go:96 +0x185
net.(_pollServer).Run(0xf840088000, 0x0)
/Users/owens/Projects/go/src/pkg/net/fd.go:236 +0xe4
created by net.newPollServer
/Users/owens/Projects/go/src/pkg/net/newpollserver.go:35 +0x382
it would be nice to have wrappers for the TypeToString and ClassToString maps that return the mnemonic if known, or RFC 3597 compliant generic representations otherwise. something like this:
import "strconv"
type RRType uint16
type RRClass uint16
func (t RRType) String() string {
if s, ok := dns.TypeToString[uint16(t)]; ok {
return s
} else {
return "TYPE" + strconv.Itoa(int(t))
}
}
func (c RRClass) String() string {
if s, ok := dns.ClassToString[uint16(c)]; ok {
return s
} else {
return "CLASS" + strconv.Itoa(int(c))
}
}
so that one could simply format integer class and type values with e.g.
fmt.Println("the rrclass is", dns.RRClass(rrclass))
fmt.Println("the rrtype is", dns.RRType(rrtype))
instead of the ten or so lines it would take otherwise.
Should I be concerned about these?
2012-08-31 06:53:52.161312500 dns: overflow packing domain-name 91
2012-08-31 06:54:00.627255500 dns: overflow packing domain-name 91
2012-08-31 06:54:07.093995500 dns: overflow packing domain-name 91
2012-08-31 06:54:11.751124500 dns: overflow packing domain-name 91
2012-08-31 06:54:32.695499500 dns: overflow packing domain-name 205
2012-08-31 06:54:32.695597500 dns: overflow packing domain-name 205
2012-08-31 06:54:32.695598500 dns: overflow packing domain-name 205
I have code here to demonstrate how tests might be implemented to avoid timeouts.
asergeyev/dns@miekg:master...master
It uses PacketConn-based server and along the way I found that Shutdown should be changed as you predicted.
https://github.com/miekg/dns/blob/master/server.go#L359
code suggests that after you got your server to activate, you cannot change handler. Is it intentional? (trips race condition in TestServingLargeResponses that I've touched)
Could be worked around either way but just want to know your standing on it.
In the following program, m.Pack returns dns.ErrBuf instead of dns.ErrFqdn
package main
import (
"fmt"
"github.com/miekg/dns"
"net"
"os"
"time"
)
func main() {
c := new(dns.Client)
c.TsigSecret = map[string]string{
"example-key.": "aHVudGVyMg==",
}
m := new(dns.Msg)
m.SetUpdate("example.")
u1 := dns.A{dns.RR_Header{"example.", dns.TypeA, dns.ClassANY, 300, 0}, net.IPv4(1,2,3,4)}
m.Ns = []dns.RR{&u1}
// the key name isn't fully qualified
m.SetTsig("example-key", dns.HmacMD5, 300, time.Now().Unix())
_, err := m.Pack()
if(err != nil) {
fmt.Println("pack:", err)
os.Exit(1)
}
}
So.. when you use Dynamic Update queries, you sometimes use no RDATA rrs, like this:
RData length will be 0 and there would be text representation like this:
example.org. 0 ANY A
This library correctly represents such text representation from something like this:
&dns.A{
Hdr: dns.RR_Header{
Name: "example.org.",
Rrtype: dns.TypeA,
Class: dns.ClassANY,
Ttl: 0,
Rdlength: 0,
},
A: nil,
}.String()
but fails to parse it back into RR, this one will panic regardless of whitespace after A:
_, err := dns.NewRR("example.org. ANY A")
if err != nil { panic("got error") }
This would not affect much real world operations! I don't know where the need of parsing such records in text format would arise but IMO it worth discussion if this behavior should be considered a bug.
I did not check much but Net::DNS is installed and seem to read those properly:
$ perl -Mv5.16 -MNet::DNS -e "say Net::DNS::RR->new('example.org. ANY A')->string();"
example.org. 0 ANY A ; no data
hi,
i see there is a call to println() in the Unpack() function:
if off != len(msg) {
// TODO(mg) remove eventually
// Err: extra bytes in packet
println("dns: extra bytes in dns packet", off, "<", len(msg))
}
i ran into this today when decoding response messages from a broken authority server. my program was printing out the following:
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 59 < 67
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 59 < 67
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 42 < 48
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 43 < 49
dns: extra bytes in dns packet 59 < 67
etc. etc. i would prefer the message parser to be completely silent on my stdio streams :)
somewhat fortunately it seems this output goes to stderr rather than stdout, which would have been even worse. (coincidentally i'm generating YAML and the warning message that Unpack() prints happens to be valid YAML.)
i guess there is a related issue of how strict the message parser should be... perhaps there should be an UnpackStrict() function that treats DNS format errors like this as full-fledged errors, or perhaps there could be a Warning string (or []string) field in the Msg type that gets formatted into the result of String(), similar to what dig does, e.g.:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28301
;; flags: qr ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: Messages has 19 extra bytes at end
but i think the issue of whether/how to return "warnings" is distinct from the issue of "library" code writing to stderr.
I realize this is more of a Go language problem (my problem not understanding, not the language itself), but:
It'd be helpful - to me at least - with some more documentation on the types and how to work with them.
As the first question: In server_test.go
I was trying to add a test to check that the appropriate response was returned, but r.Extra[0]
is just an RR
, but the content really is an RR_TXT
. How do I cast it so I can access the .Txt
?
m.SetQuestion("miek.nl.", TypeTXT)
r, _ = c.Exchange(m, "127.0.0.1:8053")
fmt.Println("Miek.nl:", r.Extra[0]) // not useful, but .Txt or .(RR_TXT).Txt doesn't work
The demo mx program crashes:
Programmation/Go/godns % _examples/mx/mx
_examples/mx/mx DOMAIN
Programmation/Go/godns % _examples/mx/mx nic.fr
panic: runtime error: invalid memory address or nil pointer dereference
panic PC=0xb7656e90
runtime.panic+0x9f /usr/local/go/src/pkg/runtime/proc.c:1032
runtime.panic(0x80b8bb8, 0xb7652938)
runtime.panicstring+0x61 /usr/local/go/src/pkg/runtime/runtime.c:83
runtime.panicstring(0x81a6977, 0x44)
runtime.sigpanic+0x11b /usr/local/go/src/pkg/runtime/linux/thread.c:286
runtime.sigpanic()
main.main+0x27a /home/bortzmeyer/Programmation/Go/godns/_examples/mx/mx.go:32
main.main()
runtime.mainstart+0xf /usr/local/go/src/pkg/runtime/386/asm.s:84
runtime.mainstart()
runtime.goexit /usr/local/go/src/pkg/runtime/proc.c:148
runtime.goexit()
goroutine 3 [3]:
runtime.entersyscall+0x25 /usr/local/go/src/pkg/runtime/proc.c:572
runtime.entersyscall()
syscall.Syscall6+0x5 /usr/local/go/src/pkg/syscall/asm_linux_386.s:39
syscall.Syscall6()
syscall.EpollWait+0x74 /usr/local/go/src/pkg/syscall/zsyscall_linux_386.go:188
syscall.EpollWait(0x6, 0xb76536d0, 0x1, 0x1, 0xffffffff, ...)
net._pollster·WaitFD+0x134 /usr/local/go/src/pkg/net/fd_linux.go:116
net._pollster·WaitFD(0xb76528d8, 0x0, 0x0, 0x0, 0x0, ...)
net._pollServer·Run+0xcb /usr/local/go/src/pkg/net/fd.go:207
net._pollServer·Run(0xb767dd60, 0x0)
runtime.goexit /usr/local/go/src/pkg/runtime/proc.c:148
runtime.goexit()
goroutine 2 [4]:
runtime.gosched+0x75 /usr/local/go/src/pkg/runtime/proc.c:553
runtime.gosched()
runtime.selectgo+0x2c0 /usr/local/go/src/pkg/runtime/chan.c:768
runtime.selectgo(0xb76536f0, 0xb76717c0)
dns/resolver.query+0x549 /home/bortzmeyer/Programmation/Go/godns/resolver/resolver.go:130
dns/resolver.query(0xb7671540, 0xb76717c0, 0x0)
runtime.goexit /usr/local/go/src/pkg/runtime/proc.c:148
runtime.goexit()
go at its tip:
% hg summary
parent: 7016:4380423c630f tip
Fix documentation typo.
branch: default
commit: 6 unknown (clean)
update: (current)
godns at its tip:
% git log|head
commit 4592aba
Author: Miek Gieben [email protected]
Date: Mon Jan 3 11:34:54 2011 +0100
fix TODO
Debian squeeze:
% uname -a
Linux batilda 2.6.26-2-686 #1 SMP Thu Sep 16 19:35:51 UTC 2010 i686 GNU/Linux
I'll enable some logging and see what I find tomorrow.
dns: overflow packing domain-name 185
panic: runtime error: index out of range
goroutine 75236 [running]:
github.com/miekg/dns.PackDomainName(0x18b25830, 0xd, 0x18859600, 0xb9, 0xb9, ...)
/opt/go/src/github.com/miekg/dns/msg.go:238 +0x2bc
github.com/miekg/dns.packStructValue(0x818d8b8, 0x18b45800, 0x196, 0x18859600, 0xb9, ...)
/opt/go/src/github.com/miekg/dns/msg.go:590 +0x323a
----- stack segment boundary -----
github.com/miekg/dns.packStructValue(0x819131c, 0x18b45800, 0x196, 0x18859600, 0xb9, ...)
/opt/go/src/github.com/miekg/dns/msg.go:527 +0x39ed
github.com/miekg/dns.packStructCompress(0x818c728, 0x18b45800, 0x18859600, 0xb9, 0xb9, ...)
/opt/go/src/github.com/miekg/dns/msg.go:658 +0x71
github.com/miekg/dns.PackRR(0x18838c90, 0x18b45800, 0x18859600, 0xb9, 0xb9, ...)
/opt/go/src/github.com/miekg/dns/msg.go:1064 +0x7e
github.com/miekg/dns.(*Msg).Pack(0x18ea0d20, 0x18859600, 0xb9, 0xb9, 0x1894c110, ...)
/opt/go/src/github.com/miekg/dns/msg.go:1225 +0x43c
github.com/miekg/dns.(*response).Write(0x18c52400, 0x18ea0d20, 0x0, 0x0)
/opt/go/src/github.com/miekg/dns/server.go:369 +0x17b
main.serve(0x188896c0, 0x18c52400, 0x18cfc640, 0x18949a00, 0x189499b4, ...)
/opt/geodns/serve.go:71 +0x70f
main._func_003(0x188d5068, 0x80864f1, 0x188896c0, 0x18c52400, 0x18cfc640, ...)
/opt/geodns/serve.go:129 +0x3e
github.com/miekg/dns.HandlerFunc.ServeDNS(0x189499a0, 0x188896c0, 0x18c52400, 0x18cfc640, 0x1887306
0, ...)
/opt/go/src/github.com/miekg/dns/server.go:75 +0x35
github.com/miekg/dns.(*ServeMux).ServeDNS(0x188471c8, 0x188896c0, 0x18c52400, 0x18cfc640, 0x18c5240
0, ...)
/opt/go/src/github.com/miekg/dns/server.go:147 +0xf0
github.com/miekg/dns.(*conn).serve(0x189da090, 0x1)
/opt/go/src/github.com/miekg/dns/server.go:343 +0x251
created by github.com/miekg/dns.(*Server).ServeUDP
/opt/go/src/github.com/miekg/dns/server.go:288 +0x318
Putting production traffic on my server made it panic with an "index out of range" error from msg.go (see below). The error was that my NS records weren't fqdn's (no dot at the end). Not sure if crashing is appropriate (if so just close the ticket) or if it should have been caught in some other way.
;; opcode: QUERY, status: NOERROR, id: 32885
;; flags: qr aa; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;pool.ntp.org. IN NS
;; ANSWER SECTION:
pool.ntp.org. 390 IN NS a.ntpns.org
pool.ntp.org. 390 IN NS b.ntpns.org
pool.ntp.org. 390 IN NS c.ntpns.org
panic: runtime error: index out of range
goroutine 2446 [running]:
github.com/miekg/dns.PackDomainName(0x18e7a200, 0xc, 0x1919e870, 0x8b, 0x8b, ...)
/opt/go/src/github.com/miekg/dns/msg.go:245 +0x33c
github.com/miekg/dns.packStructValue(0x81861fc, 0x18c9a4e0, 0x196, 0x1919e870, 0x8b, ...)
/opt/go/src/github.com/miekg/dns/msg.go:590 +0x323a
github.com/miekg/dns.packStructCompress(0x818c380, 0x18c9a4e0, 0x1919e870, 0x8b, 0x8b, ...)
/opt/go/src/github.com/miekg/dns/msg.go:658 +0x71
github.com/miekg/dns.PackRR(0x1892d900, 0x18c9a4e0, 0x1919e870, 0x8b, 0x8b, ...)
/opt/go/src/github.com/miekg/dns/msg.go:1064 +0x7e
github.com/miekg/dns.(*Msg).Pack(0x18dc6500, 0x1919e870, 0x8b, 0x8b, 0x18848090, ...)
/opt/go/src/github.com/miekg/dns/msg.go:1222 +0x3c8
github.com/miekg/dns.(*response).Write(0x18e53640, 0x18dc6500, 0x0, 0x0)
/opt/go/src/github.com/miekg/dns/server.go:369 +0x17b
main.serve(0x188da360, 0x18e53640, 0x1919f3c0, 0x188d9a00, 0x188d99b4, ...)
/opt/geodns/serve.go:98 +0xe3f
main._func_003(0x188e38c0, 0x8086488, 0x188da360, 0x18e53640, 0x1919f3c0, ...)
/opt/geodns/serve.go:129 +0x3e
github.com/miekg/dns.HandlerFunc.ServeDNS(0x188d99a0, 0x188da360, 0x18e53640, 0x1919f3c0, 0x18873040, ...)
/opt/go/src/github.com/miekg/dns/server.go:75 +0x35
github.com/miekg/dns.(*ServeMux).ServeDNS(0x188481c8, 0x188da360, 0x18e53640, 0x1919f3c0, 0x18e53640, ...)
/opt/go/src/github.com/miekg/dns/server.go:147 +0xf0
github.com/miekg/dns.(*conn).serve(0x18dc7480, 0x0)
/opt/go/src/github.com/miekg/dns/server.go:343 +0x251
created by github.com/miekg/dns.(*Server).ServeUDP
/opt/go/src/github.com/miekg/dns/server.go:288 +0x318
Running 'go test -race' will reveal them
The makefile requires a config.go this file isn't in the repository and I don't see a way to generate it.
Removing the listing from the Makefile allows the software to build without error.
if t, ok := in.Answer[len(in.Answer)-1].(*TXT); ok {
fmt.Printf(t.Txt)
// do something with t.Txt
}
I got undefined: TXT
There is issue I'm observing while trying to create fast moving tool with your library (which is great).
On high levels of concurrency, when I let goroutines run wild I'm getting "dial udp a.b.c.d:53: too many open files" error.
IMO that's due to client's exchange logic that only has single way of doing things ritght now, "Exchange() -> dial()/send()->write()/receive()->read()"
That will essentially create socket in OS for every operation and send/receive on it via "send and recv". Sendto and recvfrom in my situation would be most efficient but syscall lib is very hard to deal with, I'm trying to find simpler solutions...
IMO other version of Exchange could have additional net.Conn parameter for clients who send bunch of requests to same address... As coder I'd expect it this way:
dnsconn := c.Dial(addr)
for _, msg := range queries {
resp, rtt, err := c.ExchangeWith(dnsconn)
if err {
...
}
...
}
Should not be hard to implement... You might suggest different way of handling that. I understand that retrying logic might require to keep more than one net.Conn inside of that "dnsconn" structure.
I've got a scenario where I need to run multiple tests against different server configs. I really need the ability to end a ListenAndServe call from another goroutine. It's a bit weird that the feature doesn't already exist.
I'm willing to help implement this feature, by the way.
I think a broken packet caused this (I didn't have logging turned on, sadly, but it looks like it crashed before it even called my handler so maybe it wouldn't have helped)
extra bytes in dns packet 12 < 23
panic: runtime error: index out of range
goroutine 47788 [running]:
github.com/miekg/dns.(*ServeMux).ServeDNS(0x188471c8, 0x1893c510, 0x18d538a0, 0x18a1eb90, 0x18d
538a0, ...)
/opt/go/src/github.com/miekg/dns/server.go:143 +0x38
github.com/miekg/dns.(*conn).serve(0x18eb9f30, 0x0)
/opt/go/src/github.com/miekg/dns/server.go:343 +0x251
created by github.com/miekg/dns.(*Server).ServeUDP
/opt/go/src/github.com/miekg/dns/server.go:288 +0x318
Even after patching for issue #9, godns does not compile with today's tip:
% make
8g -o go.8 clientconfig.go client.go defaults.go dns.go dnssec.go edns.go keygen.go kscan.go msg.go nsec3.go rawmsg.go server.go tsig.go types.go update.go xfr.go zscan.go zscan_rr.go
clientconfig.go:30: undefined: error
client.go:24: undefined: error
client.go:25: undefined: error
client.go:26: undefined: error
client.go:27: undefined: error
client.go:156: undefined: error
client.go:175: undefined: error
client.go:204: undefined: error
client.go:228: undefined: error
dns.go:168: undefined: error
client.go:228: too many errors
make: *** [go.8] Error 1
Something apparently changed recently in error types.
"RRsetDelete" update comes back with "FORMERR". I haven't been able to track down why this is quite yet. The server is not providing enough log information for this. A soon as I can get more info, I'll pass it along or a patch (or a nevermind if I'm the bad one).
The most simple test I could do came back with this as well, so it seems likely to be a real bug somewhere. I don't think this is a meta-RR problem, though. I'll report back soon when I have something to add.
.
$ go test -race .
complains on dns.HelloServerLargeResponse()
. It shouldn't :)
Hi,
it tries to support it but seems to fail:
go run q.go SRV foo.example.com.
;; Truncated
;; opcode: QUERY, status: NOERROR, id: 50875
;; flags: qr tc rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;foo.example.com. IN SRV
;; query time: 31221 µs, server: 10.20.30.40:53(udp), size: 56 bytes
vs
dig SRV foo.example.com.
; <<>> DiG 9.9.2-P1 <<>> SRV foo.example.com.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9662
;; flags: qr rd ra; QUERY: 1, ANSWER: 14, AUTHORITY: 2, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;foo.example.com. IN SRV
;; ANSWER SECTION:
foo.example.com. 60 IN SRV 0 0 6566 app121.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app122.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app123.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app126.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app132.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app018.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app031.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app035.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app036.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app091.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app102.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app107.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app110.servers.example.com.
foo.example.com. 60 IN SRV 0 0 6566 app116.servers.example.com.
;; AUTHORITY SECTION:
example.com. 0 IN NS ns1.servers.example.com.
example.com. 0 IN NS ns2.servers.example.com.
;; Query time: 30 msec
;; SERVER: 10.20.30.40#53(10.20.30.40)
;; WHEN: Tue Jun 25 19:45:10 2013
;; MSG SIZE rcvd: 775
On a side note: Is it planned to have some higher level functions for resolving names? Because golang's net package doesn't handle truncated SRV records either: https://code.google.com/p/go/issues/detail?id=5686
I'm running Go 1.0.1.
When run the "reflect" example and then run a nmap UDP port scan (nmap -sU localhost
), the following error occurs (complete output log):
panic: runtime error: index out of range
goroutine 15 [running]:
dns.(*ServeMux).ServeDNS(0xf840066068, 0xf8400a4840, 0xf8400a4bc0, 0xf84006f480, 0xf8400a4bc0, ...)
/opt/go/src/pkg/dns/server.go:138 +0x34
dns.(*conn).serve(0xf840098b40, 0x0)
/opt/go/src/pkg/dns/server.go:339 +0x326
created by dns.(*Server).ServeUDP
/opt/go/src/pkg/dns/server.go:285 +0x3c7
goroutine 1 [chan receive]:
main.main()
/opt/go/dns/ex/reflect/reflect.go:148 +0x425
goroutine 2 [syscall]:
created by runtime.main
/tmp/bindist510773444/go/src/pkg/runtime/proc.c:221
goroutine 3 [syscall]:
os/signal.loop()
/usr/local/go/src/pkg/os/signal/signal_unix.go:20 +0x1c
created by os/signal.init·1
/usr/local/go/src/pkg/os/signal/signal_unix.go:26 +0x2f
goroutine 4 [chan receive]:
net.(*pollServer).WaitRead(0xf84008a840, 0xf840089120, 0xf84004e7b0, 0xb, 0x1, ...)
/usr/local/go/src/pkg/net/fd.go:268 +0x73
net.(*netFD).accept(0xf840089120, 0x46dfa1, 0x0, 0xf84004dc60, 0xf840066040, ...)
/usr/local/go/src/pkg/net/fd.go:622 +0x20d
net.(*TCPListener).AcceptTCP(0xf840066240, 0x528188, 0x0, 0x0, 0xf840066068, ...)
/usr/local/go/src/pkg/net/tcpsock_posix.go:320 +0x71
dns.(*Server).ServeTCP(0xf840001730, 0xf840066240, 0x0, 0x0, 0x0, ...)
/opt/go/src/pkg/dns/server.go:213 +0xd3
dns.(*Server).ListenAndServe(0xf840001730, 0xf840001730, 0x0, 0x401aec)
/opt/go/src/pkg/dns/server.go:187 +0x1c2
dns.ListenAndServe(0x572e8c, 0x33353a00000003, 0x5743ec, 0x3, 0x0, ...)
/opt/go/src/pkg/dns/server.go:90 +0x84
main.serve(0x5743ec, 0x70637400000003, 0x0, 0x0, 0x0, ...)
/opt/go/dns/ex/reflect/reflect.go:105 +0x72
created by main.main
/opt/go/dns/ex/reflect/reflect.go:141 +0x376
goroutine 5 [runnable]:
syscall.Syscall6()
/tmp/bindist510773444/go/src/pkg/syscall/asm_linux_amd64.s:55 +0x51
syscall.recvfrom(0x4, 0xf8400a5a00, 0x20000000200, 0x7f5f00000000, 0xf8400a3620, ...)
/usr/local/go/src/pkg/syscall/zerrors_linux_amd64.go:3007 +0xa6
syscall.Recvfrom(0xf800000004, 0xf8400a5a00, 0x20000000200, 0x0, 0x201, ...)
/usr/local/go/src/pkg/syscall/syscall_linux.go:512 +0xbb
net.(*netFD).ReadFrom(0xf8400a2000, 0xf8400a5a00, 0x20000000200, 0x100000000, 0x0, ...)
/usr/local/go/src/pkg/net/fd.go:454 +0x150
net.(*UDPConn).ReadFromUDP(0xf840066230, 0xf8400a5a00, 0x20000000200, 0xf8400a5a00, 0x0, ...)
/usr/local/go/src/pkg/net/udpsock_posix.go:164 +0x104
dns.(*Server).ServeUDP(0xf840098000, 0xf840066230, 0x0, 0x0, 0x0, ...)
/opt/go/src/pkg/dns/server.go:269 +0x13a
dns.(*Server).ListenAndServe(0xf840098000, 0xf840098000, 0x0, 0x401aec)
/opt/go/src/pkg/dns/server.go:197 +0x3e8
dns.ListenAndServe(0x572e8c, 0x33353a00000003, 0x57447c, 0x3, 0x0, ...)
/opt/go/src/pkg/dns/server.go:90 +0x84
main.serve(0x57447c, 0x70647500000003, 0x0, 0x0, 0x0, ...)
/opt/go/dns/ex/reflect/reflect.go:105 +0x72
created by main.main
/opt/go/dns/ex/reflect/reflect.go:142 +0x3bc
goroutine 6 [syscall]:
syscall.Syscall6()
/tmp/bindist510773444/go/src/pkg/syscall/asm_linux_amd64.s:40 +0x5
syscall.EpollWait(0xf800000007, 0xf84008e0c0, 0xa0000000a, 0xffffffff, 0xc, ...)
/usr/local/go/src/pkg/syscall/zerrors_linux_amd64.go:1781 +0xa1
net.(*pollster).WaitFD(0xf84008e0b0, 0xf84008a840, 0x0, 0x0, 0x0, ...)
/usr/local/go/src/pkg/net/fd_linux.go:146 +0x110
net.(*pollServer).Run(0xf84008a840, 0x0)
/usr/local/go/src/pkg/net/fd.go:236 +0xe4
created by net.newPollServer
/usr/local/go/src/pkg/net/newpollserver.go:35 +0x382
Thanks in advanced!
One of the servers crashed with this last night:
2012-09-02 02:46:54.288897500 panic: runtime error: index out of range
2012-09-02 02:46:54.288902500
2012-09-02 02:46:54.288905500 goroutine 1146879 [running]:
2012-09-02 02:46:54.288908500 github.com/miekg/dns.(*Msg).SetRcode(0x1d215dc0, 0x1d215d70, 0x2, 0x269f48, 0x1d215dc0, ...)
2012-09-02 02:46:54.288912500 /opt/go/src/github.com/miekg/dns/defaults.go:51 +0x9a
2012-09-02 02:46:54.288916500 github.com/miekg/dns.Failed(0x18801a80, 0x1b3ac220, 0x1d215d70, 0x8087b07)
2012-09-02 02:46:54.288919500 /opt/go/src/github.com/miekg/dns/server.go:88 +0x49
2012-09-02 02:46:54.288981500 github.com/miekg/dns.HandlerFunc.ServeDNS(0x808768e, 0x18801a80, 0x1b3ac220, 0x1d215d70, 0x808768e, ...)
2012-09-02 02:46:54.288986500 /opt/go/src/github.com/miekg/dns/server.go:81 +0x35
2012-09-02 02:46:54.288989500 github.com/miekg/dns.(*ServeMux).ServeDNS(0x188491c8, 0x18801a80, 0x1b3ac220, 0x1d215d70, 0x1b3ac220, ...)
2012-09-02 02:46:54.288993500 /opt/go/src/github.com/miekg/dns/server.go:156 +0xa2
2012-09-02 02:46:54.288997500 github.com/miekg/dns.(*conn).serve(0x1a0b6930, 0x1)
2012-09-02 02:46:54.296310500 /opt/go/src/github.com/miekg/dns/server.go:341 +0x28e
2012-09-02 02:46:54.296314500 created by github.com/miekg/dns.(*Server).serveUDP
2012-09-02 02:46:54.296318500 /opt/go/src/github.com/miekg/dns/server.go:299 +0x314
2012-09-02 02:46:54.296321500
This is similar to issue #67 I filed, but instead of resolving for apple.com, if you choose google.com, I always get "dns: bad rdlength" when sending the response back to the client.
I'm getting lots of EOF errors when trying to get the NS of some domains in random DNS servers, including Google's.
I'm using your lib in here:
https://github.com/hgfischer/domainerator/blob/develop/domain/query/query.go
Ex.: binary.ac, binary.by, etc
Any idea?
This is a follow-up to the remark I made about that in #25:
Just thinking out loud here:
It'd be nice if there was some way to have my build break when the dns API changes in maybe-incompatible ways. Because I use cgo I build my server on 3-4 different boxes, so my process for "keeping in sync" has just been to go get -u -v
, but then it's hard to know exactly which version of dns I got.
For geodns itself I build it with
REVISION=`git rev-parse --short=8 HEAD`
go build -ldflags "-X main.gitVersion $REVISION" -v
... maybe I should just add another version like that for the dnsGitVersion
.
As for you making a subdirectory for "v2", that sounds like a huge hassle. I think just do it on a branch, and if you need to keep v1 around when v2 is ready to be merged setup a separate git repository that people can import and alias to dns
if they need the old version.
I have a problem with a server that has multiple IP address and is bound to 0.0.0.0.
I expect the DNS queries to be responded from the source IP address it was received on, but because of the way a UDP socket works when it's bound to 0.0.0.0, the OS is choosing the source IP when calling WriteTo().
For example, host(1)
won't handle the response properly if it wasn't received from the destination address the query was sent to.
See this stackoverflow message for more information about this UDP problem:
http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket
So:
Thanks.
See skynetservices/skydns#67, this needs some building blocks here.
Can you add an example of how to use the EDNS subnet option (in the server)?
I was playing here and converted whole RR into lower case for some reason. That triggered inability of parser to read that RR back.
IMO needs to be corrected. I can work on it if needed with your recommendations. Case-insensitive support is somewhat implemented in parsing RRSIG but not in parsing RRs themselves, not sure why. maybe whole piece for reading type or class from buffer should be separated into function...
Since upgrading to the latest version some of my boxes are crashing with this error. Looking at the code it seems impossible, so not sure what's going on. I wish there was an easy way to know exactly which version of the dns package is included or otherwise a better way to manage the package dependencies. :-/
geodns 00:33:23.263167 serve.go:139: Opening on 64.142.112.226:53 udp
geodns 00:33:23.263202 serve.go:139: Opening on 207.171.17.42:53 udp
geodns 00:33:23.263187 serve.go:139: Opening on 64.142.112.226:53 tcp
geodns 00:33:23.263215 serve.go:139: Opening on 207.171.17.42:53 tcp
geodns 00:33:23.268425 config.go:47: Updated file, going to read pool.ntp.org.json
panic: dns: not reached
goroutine 17 [running]:
github.com/miekg/dns.(*ServeMux).match(0x188571c8, 0x18bb6340, 0xc, 0x6f0001, 0x29, ...)
/home/ask/go/src/github.com/miekg/dns/server.go:196 +0x10c
github.com/miekg/dns.(*ServeMux).ServeDNS(0x188571c8, 0x18bb7690, 0x18bb9000, 0x18bba000, 0x18bb9000, ...)
/home/ask/go/src/github.com/miekg/dns/server.go:230 +0xe8
github.com/miekg/dns.(*conn).serve(0x18bb7000, 0x0)
/home/ask/go/src/github.com/miekg/dns/server.go:419 +0x28e
created by github.com/miekg/dns.(*Server).serveUDP
/home/ask/go/src/github.com/miekg/dns/server.go:377 +0x310
goroutine 1 [chan receive]:
...
I'm cross-posting this issue (inhies/cjdcmd#39), because it actually belongs here.
I was building a packages that apparently depends on github.com/miekg/dns and stumbled upon an error in miekg/dns/labels.go, as follows:
$ go get github.com/inhies/cjdcmd
github.com/miekg/dns
projects/go/src/github.com/miekg/dns/labels.go:108: function ends without a return statement
projects/go/src/github.com/miekg/dns/labels.go:132: function ends without a return statement
System: Ubuntu 12.04 (amd64), go version go1.0.3b
I managed to solve this issue by adding something like "return CountLabes(s)" and "return Split(s)" to the end of the respective functions. Now it builds successfully. As I am a no good programmer and have never coded in golang, I did not dare to fork, edit and submit a pull request.
Thank you.
I have a NAPTR I am querying from a private DNS server. I am able to query and retrieve the msg in msg.Answer, but the library appears to provide a maximum of 9 entries in that msg.Answer. In this case, I actually have 10 in that NAPTR.
Since there is no guaranteed order, it is usually one of two fields that ends up always missing. If I use 'dig', I am able to get all 10 records each time.
I applied the automated migrations with
for i in */.go; do gofix $i; done
but it still doesn't compile:
6g -o go.6 clientconfig.go client.go defaults.go dns.go dnssec.go edns.go keygen.go msg.go nsec3.go server.go tsig.go types.go xfr.go
client.go:152: label forever defined and not used
keygen.go:61: t.P undefined (type rsa.PrivateKey has no field or method P)
keygen.go:62: t.Q undefined (type *rsa.PrivateKey has no field or method Q)
keygen.go:67: t.P undefined (type *rsa.PrivateKey has no field or method P)
keygen.go:68: t.Q undefined (type *rsa.PrivateKey has no field or method Q)
keygen.go:71: t.Q undefined (type *rsa.PrivateKey has no field or method Q)
keygen.go:71: t.P undefined (type *rsa.PrivateKey has no field or method P)
keygen.go:131: p.P undefined (type *rsa.PrivateKey has no field or method P)
keygen.go:132: p.P undefined (type *rsa.PrivateKey has no field or method P)
keygen.go:135: p.Q undefined (type *rsa.PrivateKey has no field or method Q)
keygen.go:135: too many errors
make: ** [go.6] Error 1
OSX:dns-master littlesuper$ go get github.com/miekg/dns
OSX:dns-master littlesuper$ go build dns
can't load package: package dns: import "dns": cannot find package
When running latest master i get:
github.com/miekg/dns../src/github.com/miekg/dns/defaults.go:290: function ends without a return statement
../src/github.com/miekg/dns/defaults.go:299: function ends without a return statement
gopath/src/github.com/miekg/dns/edns.go:230: function ends without a return statement
Our continuous integration server just picked this up.
I'd expect the following to work unless I'm doing something wrong.
package dns
import (
"net"
"strconv"
"testing"
)
func TestSRVPacking(t *testing.T) {
msg := Msg{}
things := []string{"1.2.3.4:8484",
"45.45.45.45:8484",
"84.84.84.84:8484",
}
for i, n := range things {
h, p, err := net.SplitHostPort(n)
if err != nil {
continue
}
port := 8484
tmp, err := strconv.Atoi(p)
if err == nil {
port = tmp
}
rr := &RR_SRV{
Hdr: RR_Header{Name: "somename",
Rrtype: TypeSRV,
Class: ClassINET,
Ttl: 5},
Priority: uint16(i),
Weight: 5,
Port: uint16(port),
Target: h,
}
msg.Answer = append(msg.Answer, rr)
}
_, ok := msg.Pack()
if !ok {
t.Fatalf("Couldn't pack %v\n", msg)
}
}
I noticed double-quotes were escaped in TXT records I received over the network. After a bit of digging I suspected it had something to do with unpackTxtString() not working correctly. Here's a test I case I hastily wrote up to verify this behavior:
package dns
import (
"testing"
)
func TestTxtPackUnpack(t *testing.T) {
var original string
original = `{"Name": "alex", "Age": 22}`
var (
err error
msg []byte
buf []byte
check string
)
msg = make([]byte, 128)
buf = make([]byte, 128)
_, err = packTxtString(original, msg, 0, buf)
if err != nil {
t.Fatal(err)
}
check, _, err = unpackTxtString(msg, 0)
if err != nil {
t.Fatal(err)
}
if original != check {
t.Fatalf("%s != %s\n", original, check)
}
}
As expected it fails. At this point I don't know enough about this library to say if it should pass or not. So I have a few questions. Is this the desired behavior? If yes, why is this the case and how are we supposed to work around it (i.e. I don't want double-quotes escaped)? If no, then how should it be fixed? I would be willing to attempt fixing this in a pull request if I knew how these functions were supposed to actually run.
When creating RRs via the NewRR function, I've found that rr.Header().Rdlength is not set to the length of the rdata. I'm still not sure the scope of real-world implications, here - it became a thorn in my side when testing my project, where I was using reflect.DeepEqual to compare a produced *Msg against an expected *Msg value.
I'm getting an error decoding a response with the client "dns: overflow unpacking uint32". The response is being generated with the same library, and contains a combination of SRV and A records. Nothing crazy as far as I can tell. Below is the binary buffer after packing that is being sent:
[130 137 133 0 0 1 0 10 0 1 0 5 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 255 0 1 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 11 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 5 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 1 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 3 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 7 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 33 0 1 0 0 0 0 0 29 0 1 0 1 31 64 5 102 111 111 49 48 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 33 0 1 0 0 0 0 0 28 0 1 0 1 31 64 4 102 111 111 52 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 33 0 1 0 0 0 0 0 28 0 1 0 1 31 64 4 102 111 111 48 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 33 0 1 0 0 0 0 0 28 0 1 0 1 31 64 4 102 111 111 50 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 3 119 101 98 7 115 101 114 118 105 99 101 6 99 111 110 115 117 108 0 0 33 0 1 0 0 0 0 0 28 0 1 0 1 31 64 4 102 111 111 54 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 6 99 111 110 115 117 108 0 0 6 0 1 0 0 0 0 0 50 2 110 115 6 99 111 110 115 117 108 0 10 112 111 115 116 109 97 115 116 101 114 6 99 111 110 115 117 108 0 82 254 117 230 0 0 14 16 0 0 2 88 0 1 81 128 0 0 0 0 5 102 111 111 49 48 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 11 4 102 111 111 52 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 5 4 102 111 111 48 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 1 4 102 111 111 50 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 3 4 102 111 111 54 4 110 111 100 101 3 100 99 49 6 99 111 110 115 117 108 0 0 1 0 1 0 0 0 0 0 4 127 0 0 7]
In some cases, I'm using the client to act like a recursive DNS server. However, with some queries, I get the following:
dns: overflow packing uint32
It seems to have to do with something in the response body. I have a minimal test case here: https://gist.github.com/armon/8248769
Once you run that server, use the following dig command:
time dig @127.0.0.1 -p 8600 +qr apple.com ANY
Inside the test case, there is a line with a comment to toggle the value. The compression flag on the response seems to change if this works. With compression enabled, the response goes through fine. Without compression, the packing error happens.
This is from a downstream issue: hashicorp/consul#284
Looks like there is an issue in dns.unpackStructValue that can cause a panic. That ticket has all the information I know about this currently.
From the documentation for the Client
type:
A nil Client is usable for sending queries.
This is not true. A pointer to the zero value is usable, nil is not.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.