From 4ce23b71cf0cb988b7080e0015f33370b76e873e Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 22 Dec 2010 20:53:18 +0100 Subject: [PATCH] Fix the encoding a EDNS RR Still need to handle the domain name packer, so that we can detect we have an OPT RR, with the different encoding --- Makefile | 5 ++++- TODO | 2 ++ edns.go | 17 +++++++---------- edns_test.go | 8 ++++---- msg.go | 38 +++++++++++++++++++++++++++++--------- pack_test.go | 31 +++++++++++++++++-------------- resolver_test.go | 7 +++---- types.go | 6 ++++-- 8 files changed, 70 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index db7ae207..9fac694d 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,15 @@ GOFILES=\ include $(GOROOT)/src/Make.pkg -p: restest manglertest packtest dnssectest +p: restest manglertest ednstest dnssectest # too lazy to lookup how this works again in Makefiles restest: restest.go $(GOFILES) 6g -I _obj restest.go && 6l -L _obj -o restest restest.6 +ednstest: ednstest.go $(GOFILES) + 6g -I _obj ednstest.go && 6l -L _obj -o ednstest ednstest.6 + manglertest: manglertest.go $(GOFILES) 6g -I _obj manglertest.go && 6l -L _obj -o manglertest manglertest.6 diff --git a/TODO b/TODO index dd201224..ac80b48b 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,8 @@ EDNS -- add EDNS0 support DNSSEC - validation and the remaining records DS, RRSIG, NSEC, etc. NSEC/NSEC3/NSEC3PARAM stuff +unknown RRs + Generic version of TryOneName quotes in quotes in txt records fix os.Erros usage (extend or whatever) diff --git a/edns.go b/edns.go index 8db4add6..fb57ce6a 100644 --- a/edns.go +++ b/edns.go @@ -1,8 +1,6 @@ package dns -// This is the base layer for ENDS, in practise -// You'll only need to set updsize, do bit, and?? - +// Implementation of EDNS0, RFC 2671 const ( OptionCodeLLQ = 1 OptionCodeUL = 2 @@ -14,8 +12,7 @@ const ( // Need PackOption I guess?? TODO type Option struct { Code uint16 -// Length uint16 - Data string "hex" // len(data) is must be encode in packet + Data string "hex" } // EDNS extended RR. @@ -29,17 +26,17 @@ type EDNS0_Header struct { Rdlength uint16 // length of data after the header } -type RR_EDNS0 struct { +type RR_OPT struct { Hdr RR_Header // this must become a EDNS0_Header - Option []Option + Option []Option "OPT" // Tag is used in pack and unpack } -func (rr *RR_EDNS0) Header() *RR_Header { +func (rr *RR_OPT) Header() *RR_Header { return &rr.Hdr } -func (rr *RR_EDNS0) String() string { - var s string +func (rr *RR_OPT) String() string { + s := rr.Hdr.String() for _, o := range rr.Option { switch o.Code { case OptionCodeNSID: diff --git a/edns_test.go b/edns_test.go index bf5317d8..19cac42d 100644 --- a/edns_test.go +++ b/edns_test.go @@ -1,19 +1,19 @@ package dns // Test EDNS RR records - import ( "testing" + "fmt" ) func TestEDNS_RR(t *testing.T) { - edns := new(RR_EDNS0) - edns.Hdr.Name = "miek.nl." // must . be for edns + edns := new(RR_OPT) + edns.Hdr.Name = "." // must . be for edns edns.Hdr.Rrtype = TypeOPT edns.Hdr.Class = ClassINET edns.Hdr.Ttl = 3600 edns.Option = make([]Option, 1) edns.Option[0].Code = OptionCodeNSID edns.Option[0].Data = "lalalala" - //fmt.Printf("%s\n", edns) + fmt.Printf("%v\n", edns) } diff --git a/msg.go b/msg.go index 35293102..08dc3a93 100644 --- a/msg.go +++ b/msg.go @@ -183,9 +183,25 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o default: fmt.Fprintf(os.Stderr, "net: dns: unknown IP tag %v", f.Tag) return len(msg), false - case "edns": // ends - - case "ipv4": + case "OPT": // edns + for j := 0; j < val.Field(i).(*reflect.SliceValue).Len(); j++ { + println(j) // TODO MG + element := val.Field(i).(*reflect.SliceValue).Elem(j) + code := uint16(element.(*reflect.StructValue).Field(0).(*reflect.UintValue).Get()) + data := string(element.(*reflect.StructValue).Field(1).(*reflect.StringValue).Get()) + // Option Code + msg[off] = byte(code >> 8) + msg[off+1] = byte(code) + // Length + msg[off+2] = byte(len(data) >> 8) + msg[off+3] = byte(len(data)) + off += 4 + copy(msg[off:off+len(data)], []byte(data)) + off += len(data) // +1?? + println("data", data) + println("off", off) + } + case "A": if fv.Len() > net.IPv4len || off+fv.Len() > len(msg) { return len(msg), false } @@ -194,7 +210,7 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o msg[off+2] = byte(fv.Elem(2).(*reflect.UintValue).Get()) msg[off+3] = byte(fv.Elem(3).(*reflect.UintValue).Get()) off += net.IPv4len - case "ipv6": + case "AAAA": if fv.Len() > net.IPv6len || off+fv.Len() > len(msg) { return len(msg), false } @@ -252,6 +268,9 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o if !ok { return len(msg), false } + case "hex": + // TODO need this for DS + println("hex packing not implemented") case "": // Counted string: 1 byte length. if len(s) > 255 || off+1+len(s) > len(msg) { @@ -293,14 +312,14 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, default: fmt.Fprintf(os.Stderr, "net: dns: unknown IP tag %v", f.Tag) return len(msg), false - case "ipv4": + case "A": if off+net.IPv4len > len(msg) { return len(msg), false } b := net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3]) fv.Set(reflect.NewValue(b).(*reflect.SliceValue)) off += net.IPv4len - case "ipv6": + case "AAAA": if off+net.IPv6len > len(msg) { return len(msg), false } @@ -309,6 +328,8 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, b := net.IP(p) fv.Set(reflect.NewValue(b).(*reflect.SliceValue)) off += net.IPv6len + case "OPT": // edns + // do it here } case *reflect.StructValue: off, ok = unpackStructValue(fv, msg, off) @@ -347,12 +368,11 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, case "hex": // Rest of the RR is hex encoded rdlength := int(val.FieldByName("Hdr").(*reflect.StructValue).FieldByName("Rdlength").(*reflect.UintValue).Get()) - // hoeft hier ook niet var consumed int switch val.Type().Name() { case "RR_DS": consumed = 4 // KeyTag(2) + Algorithm(1) + DigestType(1) - default: + default: consumed = 0 // TODO } s = hex.EncodeToString(msg[off : off+rdlength-consumed]) @@ -468,7 +488,7 @@ func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) { // again inefficient but doesn't need to be fast. mk, known := rr_mk[int(h.Rrtype)] if !known { - return &h, end, true + return &h, end, true // false, or unknown RR?? } rr = mk() diff --git a/pack_test.go b/pack_test.go index 19592aff..b21162c8 100644 --- a/pack_test.go +++ b/pack_test.go @@ -2,7 +2,6 @@ package dns import ( "testing" - "fmt" "net" ) @@ -28,7 +27,6 @@ func TestPackUnpack(t *testing.T) { t.Log("Failed to unpack msg with AAAA") t.Fail() } - fmt.Printf("%v\n", in) key := new(RR_DNSKEY) key.Hdr.Name = "miek.nl." @@ -42,7 +40,6 @@ func TestPackUnpack(t *testing.T) { out.Answer[0] = key msg, ok = out.Pack() -// fmt.Printf("%v\n", msg) if ! ok { t.Log("Failed to pack msg with DNSKEY") t.Fail() @@ -52,8 +49,6 @@ func TestPackUnpack(t *testing.T) { t.Log("Failed to unpack msg with DNSKEY") t.Fail() } - fmt.Printf("%v\n", in) - sig := new(RR_RRSIG) sig.Hdr.Name = "miek.nl." @@ -70,9 +65,20 @@ func TestPackUnpack(t *testing.T) { sig.SignerName = "miek.nl." sig.Sig = "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ" + out.Answer[0] = sig + msg, ok = out.Pack() + if ! ok { + t.Log("Failed to pack msg with RRSIG") + t.Fail() + } - edns := new(RR_EDNS0) - edns.Hdr.Name = "miek.nl." // must . be for edns + if ! in.Unpack(msg) { + t.Log("Failed to unpack msg with RRSIG") + t.Fail() + } + + edns := new(RR_OPT) + edns.Hdr.Name = "." edns.Hdr.Rrtype = TypeOPT edns.Hdr.Class = ClassINET edns.Hdr.Ttl = 3600 @@ -80,19 +86,16 @@ func TestPackUnpack(t *testing.T) { edns.Option[0].Code = OptionCodeNSID edns.Option[0].Data = "lalalala" - out.Answer[0] = sig - out.Extra = make([]RR, 1) - out.Extra[0] = edns + out.Answer[0] = edns msg, ok = out.Pack() -// fmt.Printf("%v\n", msg) if ! ok { - t.Log("Failed to pack msg with RRSIG and EDNS") + t.Log("Failed to pack msg with OPT (EDNS)") t.Fail() } if ! in.Unpack(msg) { - t.Log("Failed to unpack msg with RRSIG and EDNS") + t.Log("Failed to unpack msg with OPT (EDNS)") t.Fail() } - fmt.Printf("%v\n", in) + } diff --git a/resolver_test.go b/resolver_test.go index 1133fd54..562b5db4 100644 --- a/resolver_test.go +++ b/resolver_test.go @@ -12,7 +12,7 @@ func TestResolver(t *testing.T) { ch := NewQuerier(res) res.Servers = []string{"127.0.0.1"} -// res.Timeout = 2 + res.Timeout = 2 res.Attempts = 1 m := new(Msg) @@ -27,8 +27,8 @@ func TestResolver(t *testing.T) { if in.Dns.Rcode != RcodeSuccess { t.Log("Failed to get an valid answer") t.Fail() + fmt.Printf("%v\n", in) } - fmt.Printf("%v\n", in) // ask something m.Question[0] = Question{"www.nlnetlabs.nl", TypeRRSIG, ClassINET} @@ -38,9 +38,8 @@ func TestResolver(t *testing.T) { if in.Dns.Rcode != RcodeSuccess { t.Log("Failed to get an valid answer") t.Fail() + fmt.Printf("%v\n", in) } - fmt.Printf("%v\n", in) - ch <- DnsMsg{nil, nil} time.Sleep(1.0e9) diff --git a/types.go b/types.go index efc464c5..6899a3e4 100644 --- a/types.go +++ b/types.go @@ -327,7 +327,7 @@ func (rr *RR_SRV) String() string { type RR_A struct { Hdr RR_Header - A net.IP "ipv4" + A net.IP "A" } func (rr *RR_A) Header() *RR_Header { @@ -340,7 +340,7 @@ func (rr *RR_A) String() string { type RR_AAAA struct { Hdr RR_Header - AAAA net.IP "ipv6" + AAAA net.IP "AAAA" } func (rr *RR_AAAA) Header() *RR_Header { @@ -489,6 +489,7 @@ var rr_mk = map[int]func() RR{ TypeSRV: func() RR { return new(RR_SRV) }, TypeA: func() RR { return new(RR_A) }, TypeAAAA: func() RR { return new(RR_AAAA) }, + TypeOPT: func() RR { return new(RR_OPT) }, TypeDS: func() RR { return new(RR_DS) }, TypeRRSIG: func() RR { return new(RR_RRSIG) }, TypeNSEC: func() RR { return new(RR_NSEC) }, @@ -513,6 +514,7 @@ var rr_str = map[uint16]string{ TypeSRV: "SRV", TypeA: "A", TypeAAAA: "AAAA", + TypeOPT: "OPT", TypeDS: "DS", TypeRRSIG: "RRSIG", TypeNSEC: "NSEC",