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
This commit is contained in:
Miek Gieben 2010-12-22 20:53:18 +01:00
parent 0f05a2f434
commit 4ce23b71cf
8 changed files with 70 additions and 44 deletions

View File

@ -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

2
TODO
View File

@ -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)

17
edns.go
View File

@ -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:

View File

@ -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)
}

38
msg.go
View File

@ -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()

View File

@ -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)
}

View File

@ -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)

View File

@ -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",