dns package

682 views
Skip to first unread message

Miek Gieben

unread,
Aug 3, 2010, 6:50:50 PM8/3/10
to Go List
Hello,

I've, well, forked the DNS code contained in the net package, because I
wanted to add more functionality to it.

I've created a new namespace 'dns' and added stuff.

o More supported records: AAAA and DNSSEC records
o Created a Resolver structure (instead of DNSConfig)
o More 'dig' like output in the String functions.
o A Query() function (instead of Exchange)
o uint8, hex, base64 unpacking
o started with EDNS0 support

The code is on github: http://github.com/miekg/godns
Project page (which is pretty empty atm): http://miek.nl/projects/godns/

A lot of stuff still needs to be done. One the things would be
validating DNSSEC responses. But I get the feeling I'm on the right
track.

It may be a bit early to ask, but is this a worth while addition to
the standard Go library?

Regards,

--
Miek

signature.asc

Andrew Gerrand

unread,
Aug 3, 2010, 7:45:46 PM8/3/10
to Go List, golang-dev

I haven't had a good look at the code, but at least some of this
functionality is desirable for the standard library. (support for
additional record types, for one)

The best way to approach integrating it is (at some point) to break
your changes down into the smallest parts and submit them as CLs.

You can also start a discussion in golang-dev about specific
implementation details.

Andrew

Russ Cox

unread,
Aug 3, 2010, 7:55:02 PM8/3/10
to Andrew Gerrand, Go List, golang-dev
I don't believe that a major DNS package belongs in the
standard library. Depending on scope it might make
sense for you to just have a separate DNS library, like
there is a separate readline library.

The long term plan is to throw away the DNS code and
replace it with calls to the host C library getaddrinfo and such,
because it's just too complicated to try to recreate ourselves.
We're getting particularly burned on OS X, where the firewall
doesn't even let us receive the UDP responses from the DNS
servers, but there are problems on Linux and FreeBSD too,
especially with not being able to resolve non-DNS names.
Using the host library will solve all of that.

The DNS code was a good bootstrap mechanism that let
us get programs running before it was possible to link with
the standard libraries in any way, but now that we have
the necessary mechanisms in place, it's a fool's errand to
try to keep up with the churn in typical host networking libraries.

We might keep the DNS code around for things
like embedded but networked systems without C libraries,
but it won't be linked in by default.
(I plan to delete it and bring it back if necessary.)

Russ

Stéphane Bortzmeyer

unread,
Oct 6, 2010, 4:43:23 PM10/6/10
to Go List
2010/8/4 Miek Gieben <mi...@miek.nl>:

> I've, well, forked the DNS code contained in the net package, because I
> wanted to add more functionality to it.

Well, anyway, as soon as you want to use the DNS code, you have to
fork it because it does not have its own package and it does not
export the functions.

[My personal fork: http://www.bortzmeyer.org/tmp/dnslib.go ]

> It may be a bit early to ask, but is this a worth while addition to
> the standard Go library?

IMHO, a good DNS library would be really nice, whether in the standard
library or not. Today, we have to do a lot of work even for a simple
DNS client. So, I encourage you to go on and I volunteer as a beta
tester.

At the present time, there is something strange in your library. When
the resolution fails, for instance because the name server does not
exist, Query returns something which is apparently not a normal "nil"
since printing it crashes Go:

% ./restest
. 0 192.168.1.2
. 0 2003::53
panic: runtime error: invalid memory address or nil pointer dereference

panic PC=0xaf6f50
runtime.panic+0xa9 /usr/local/go/src/pkg/runtime/proc.c:1020
runtime.panic(0x0, 0x80cc1b0)
panicstring+0x61 /usr/local/go/src/pkg/runtime/runtime.c:83
panicstring(0x80cc1b0, 0xa7c938)
sigpanic+0x11b /usr/local/go/src/pkg/runtime/linux/thread.c:286
sigpanic()
dns.*MsgHdr·String+0x3a /home/stephane/src/Go/dns/godns/dnsmsg.go:483
dns.*MsgHdr·String(0xa9d320, 0x0, 0x0)
dns.*Msg·String+0x36 /home/stephane/src/Go/dns/godns/dnsmsg.go:618
dns.*Msg·String(0x0, 0x0, 0x0)
fmt.*pp·printField+0x29f7 /usr/local/go/src/pkg/fmt/print.go:551
fmt.*pp·printField(0x0, 0x80e8b18, 0x0, 0xa95dc0, 0x0, ...)
fmt.*pp·doPrintf+0x693 /usr/local/go/src/pkg/fmt/print.go:876
fmt.*pp·doPrintf(0xaa7e70, 0x80e8b18, 0x0, 0x76, 0x0, ...)
fmt.Fprintf+0x52 /usr/local/go/src/pkg/fmt/print.go:140
fmt.Fprintf(0xaa7e70, 0x80f5340, 0x3, 0xa7c930, 0x1, ...)
fmt.Printf+0x6d /usr/local/go/src/pkg/fmt/print.go:149
fmt.Printf(0xa95ba0, 0xa95480, 0x80f5340, 0x3, 0xa7c930, ...)
main.main+0x2d9 /home/stephane/src/Go/dns/godns/restest.go:30
main.main()
mainstart+0xf /usr/local/go/src/pkg/runtime/386/asm.s:83
mainstart()
goexit /usr/local/go/src/pkg/runtime/proc.c:145
goexit()

goroutine 2 [3]:
runtime.entersyscall+0x25 /usr/local/go/src/pkg/runtime/proc.c:565
runtime.entersyscall()
syscall.Syscall6+0x5 /usr/local/go/src/pkg/syscall/asm_linux_386.s:40
syscall.Syscall6()
syscall.EpollWait+0x74 /usr/local/go/src/pkg/syscall/zsyscall_linux_386.go:188
syscall.EpollWait(0x100, 0x6, 0xa90490, 0x1, 0xffffffff, ...)
net.*pollster·WaitFD+0x134 /usr/local/go/src/pkg/net/fd_linux.go:116
net.*pollster·WaitFD(0x6, 0xa90490, 0x1, 0x1, 0xffffffff, ...)
net.*pollServer·Run+0xcb /usr/local/go/src/pkg/net/fd.go:207
net.*pollServer·Run(0xa7c8b8, 0x0)
goexit /usr/local/go/src/pkg/runtime/proc.c:145
goexit()

Rob 'Commander' Pike

unread,
Oct 6, 2010, 4:47:31 PM10/6/10
to Stéphane Bortzmeyer, Go List

The bug is right there in the trace. The String method of dns.MsgHdr doesn't protect against a nil pointer. (Printf doesn't do that for you because for some types nil is a perfectly printable value.)

-rob


Stéphane Bortzmeyer

unread,
Oct 6, 2010, 4:54:15 PM10/6/10
to Rob 'Commander' Pike, Go List
Le 6 octobre 2010 22:47, Rob 'Commander' Pike <r...@google.com> a écrit :

> The String method of dns.MsgHdr doesn't protect against a nil pointer.

Yes, of course. Miek, if you want, here is a diff which does protect
against errors.

--- a/dnsmsg.go
+++ b/dnsmsg.go
@@ -480,6 +480,9 @@ type MsgHdr struct {
//;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48404
//;; flags: qr aa rd ra;
func (h *MsgHdr) String() string {
+ if h == nil {
+ return "<nil> MsgHdr"
+ }
s := ";; ->>HEADER<<- opcode: " + opcode_str[h.opcode]
s += ", status: " + rcode_str[h.rcode]
s += ", id: " + strconv.Itoa(int(h.id)) + "\n"
@@ -615,6 +618,9 @@ func (dns *Msg) Unpack(msg []byte) bool {
}

func (dns *Msg) String() string {
+ if dns == nil {
+ return "<nil> Msg"
+ }
s := dns.MsgHdr.String() + " "
s += "QUERY: " + strconv.Itoa(len(dns.Question)) + ", "
s += "ANSWER: " + strconv.Itoa(len(dns.Answer)) + ", "

Miek Gieben

unread,
Oct 7, 2010, 2:49:13 AM10/7/10
to Go List
[ Quoting Stéphane Bortzmeyer in "Re: [go-nuts] dns package"... ]

> > The String method of dns.MsgHdr doesn't protect against a nil pointer.
>
> Yes, of course. Miek, if you want, here is a diff which does protect
> against errors.

Thanks. I've applied it.

grtz Miek

signature.asc
Reply all
Reply to author
Forward
0 new messages