At least it gives formerr now

This commit is contained in:
Miek Gieben 2010-12-23 11:02:01 +01:00
parent 4668b309e2
commit 8302d19b42
4 changed files with 166 additions and 110 deletions

50
edns.go
View File

@ -2,16 +2,16 @@ package dns
// Implementation of EDNS0, RFC 2671
const (
OptionCodeLLQ = 1
OptionCodeUL = 2
OptionCodeNSID = 3
// EDNS flag bits (put in Z section)
_DO = 1 << 15 // dnssec ok
OptionCodeLLQ = 1
OptionCodeUL = 2
OptionCodeNSID = 3
// EDNS flag bits (put in Z section)
_DO = 1 << 15 // dnssec ok
)
type Option struct {
Code uint16
Data string "hex"
Code uint16
Data string "hex"
}
// EDNS extended RR.
@ -19,31 +19,31 @@ type Option struct {
// the RR_Header over to this type and allow for
// easy access
type EDNS0_Header struct {
Name string "extended-name"
Opt uint16 // was type
UDPSize uint16 // was class
ExtendedRcode uint8 // was TTL
Version uint8 // was TTL
Z uint16 // was TTL (all flags should be put here)
Rdlength uint16 // length of data after the header
Name string "extended-name"
Opt uint16 // was type
UDPSize uint16 // was class
ExtendedRcode uint8 // was TTL
Version uint8 // was TTL
Z uint16 // was TTL (all flags should be put here)
Rdlength uint16 // length of data after the header
}
type RR_OPT struct {
Hdr RR_Header // this must become a EDNS0_Header
Option []Option "OPT" // Tag is used in pack and unpack
Hdr RR_Header // this must become a EDNS0_Header
Option []Option "OPT" // Tag is used in pack and unpack
}
func (rr *RR_OPT) Header() *RR_Header {
return &rr.Hdr
return &rr.Hdr
}
func (rr *RR_OPT) String() string {
s := rr.Hdr.String()
for _, o := range rr.Option {
switch o.Code {
case OptionCodeNSID:
s += "NSID: " + o.Data
}
}
return s
s := rr.Hdr.String()
for _, o := range rr.Option {
switch o.Code {
case OptionCodeNSID:
s += "NSID: " + o.Data
}
}
return s
}

122
msg.go
View File

@ -73,13 +73,13 @@ func packDomainName(s string, msg []byte, off int, edns bool) (off1 int, ok bool
s += "."
}
if edns {
// packing for edns is actually easy
msg[0] = 0x40 // 01 111111
msg[1] = 0x00
off += 2
return off, true
}
if edns {
// packing for edns is actually easy
msg[0] = 0x40 // 01 111111
msg[1] = 0x00
off += 2
return off, true
}
// Each dot ends a segment of the name.
// We trade each dot byte for a length byte.
@ -146,19 +146,19 @@ Loop:
}
s += string(msg[off:off+c]) + "."
off += c
case 0x40:
// Need a check if a RR has this, because
// we need to set RR_Heasder.Edns to true
// edns extended name, does not matter for
// the rest of the RR (which should be OPT)
// but the parsing here (is for now) relatively simple
// The name must be the root label aka 00
// TODO check! MG
println("*** Seeing EDNS")
edns = true
s = ""
off++
break Loop
case 0x40:
// Need a check if a RR has this, because
// we need to set RR_Heasder.Edns to true
// edns extended name, does not matter for
// the rest of the RR (which should be OPT)
// but the parsing here (is for now) relatively simple
// The name must be the root label aka 00
// TODO check! MG
println("*** Seeing EDNS")
edns = true
s = ""
off++
break Loop
case 0xC0:
// pointer to somewhere else in msg.
// remember location after first ptr,
@ -199,33 +199,33 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int, edns bool) (
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v\n", f.Type)
return len(msg), false
case *reflect.BoolValue:
// Used internally for Edns, not present in the DNS
continue;
case *reflect.BoolValue:
// Used internally for Edns, not present in the DNS
continue
case *reflect.SliceValue:
switch f.Tag {
default:
fmt.Fprintf(os.Stderr, "net: dns: unknown IP tag %v\n", f.Tag)
return len(msg), false
case "OPT": // edns
// Set the Hdr.Edns to true
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 "OPT": // edns
// Set the Hdr.Edns to true
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
@ -293,9 +293,9 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int, edns bool) (
if !ok {
return len(msg), false
}
case "hex":
// TODO need this for DS
println("hex packing not implemented")
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) {
@ -332,9 +332,9 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
return len(msg), false, false
case *reflect.BoolValue:
// Used internally for Edns, not present in the DNS
continue;
case *reflect.BoolValue:
// Used internally for Edns, not present in the DNS
continue
case *reflect.SliceValue:
switch f.Tag {
default:
@ -356,8 +356,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 "OPT": // edns
// do it here
}
case *reflect.StructValue:
off, ok, edns = unpackStructValue(fv, msg, off)
@ -400,7 +400,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 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])
@ -415,7 +415,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
consumed = 4 // Flags(2) + Protocol(1) + Algorithm(1)
case "RR_RRSIG":
consumed = 18 // TypeCovered(2) + Algorithm(1) + Labels(1) +
// OrigTTL(4) + SigExpir(4) + SigIncep(4) + KeyTag(2) + len(signername)
// OrigTTL(4) + SigExpir(4) + SigIncep(4) + KeyTag(2) + len(signername)
// Should already be set in the sequence of parsing (comes before)
// Work because of rfc4034, section 3.17
consumed += len(val.FieldByName("SignerName").(*reflect.StringValue).Get()) + 1
@ -490,7 +490,7 @@ func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) {
// a bit inefficient but this doesn't need to be fast.
// off1 is end of header
// off2 is end of rr
edns := rr.Header().Edns
edns := rr.Header().Edns
off1, ok = packStruct(rr.Header(), msg, off, edns)
off2, ok = packStruct(rr, msg, off, edns)
if !ok {
@ -506,25 +506,25 @@ func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) {
// Resource record unpacker.
func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) {
// unpack just the header, to find the rr type and length
// check if we have an edns packet, and set h.Edns to true
// check if we have an edns packet, and set h.Edns to true
var h RR_Header
var edns bool
var edns bool
off0 := off
if off, ok, edns = unpackStruct(&h, msg, off); !ok {
return nil, len(msg), false
}
h.Edns = edns // set Edns if found
h.Edns = edns // set Edns if found
end := off + int(h.Rdlength)
// make an rr of that type and re-unpack.
// again inefficient but doesn't need to be fast.
mk, known := rr_mk[int(h.Rrtype)]
if !known {
return &h, end, true // false, or unknown RR??
return &h, end, true // false, or unknown RR??
}
rr = mk()
off, ok, _ = unpackStruct(rr, msg, off0) // don't care about edns?
off, ok, _ = unpackStruct(rr, msg, off0) // don't care about edns?
if off != end {
// added MG
// println("Hier gaat het dan fout, echt waar en was if off0", off0)
@ -545,7 +545,7 @@ type MsgHdr struct {
Truncated bool
Recursion_desired bool
Recursion_available bool
Z bool // or just zero??
Z bool // or just zero??
Authenticated_data bool
Checking_disabled bool
Rcode int
@ -598,7 +598,7 @@ type Msg struct {
Answer []RR
Ns []RR
// EDNS0 has to be put in this section
Extra []RR
Extra []RR
}
@ -647,7 +647,7 @@ func (dns *Msg) Pack() (msg []byte, ok bool) {
// Could work harder to calculate message size,
// but this is far more than we need and not
// big enough to hurt the allocator.
msg = make([]byte, 4096) // TODO, calculate REAL size
msg = make([]byte, 4096) // TODO, calculate REAL size
// Pack it in: header and then the pieces.
off := 0

51
resolverEdns_test.go Normal file
View File

@ -0,0 +1,51 @@
package dns
import (
"testing"
"time"
"fmt"
)
func TestResolverEdns(t *testing.T) {
res := new(Resolver)
ch := NewQuerier(res)
res.Servers = []string{"127.0.0.1"}
res.Timeout = 2
res.Attempts = 1
m := new(Msg)
m.MsgHdr.Recursion_desired = true //only set this bit
m.Question = make([]Question, 1)
m.Extra = make([]RR, 1)
// Add EDNS rr
edns := new(RR_OPT)
edns.Hdr.Edns = true // must be set for edns
edns.Hdr.Name = "." // must . be for edns
edns.Hdr.Rrtype = TypeOPT
edns.Hdr.Class = ClassINET
edns.Hdr.Ttl = 3600
// no options
// edns.Option = make([]Option, 1)
// edns.Option[0].Code = OptionCodeNSID
// edns.Option[0].Data = "lalalala"
// ask something
m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET}
m.Extra[0] = edns
fmt.Printf("%v\n", m)
ch <- DnsMsg{m, nil}
in := <-ch
if in.Dns.Rcode != RcodeSuccess {
t.Log("Failed to get an valid answer")
t.Fail()
}
fmt.Printf("%v\n", in)
ch <- DnsMsg{nil, nil}
time.Sleep(1.0e9)
}

View File

@ -120,7 +120,7 @@ func (q *Question) String() string {
// There are many types of messages,
// but they all share the same header.
type RR_Header struct {
Edns bool // true is this a edns header
Edns bool // true is this a edns header
Name string "domain-name"
Rrtype uint16
Class uint16
@ -134,14 +134,19 @@ func (h *RR_Header) Header() *RR_Header {
func (h *RR_Header) String() string {
var s string
if len(h.Name) == 0 {
s = ".\t"
} else {
s = h.Name + "\t"
}
s = s + strconv.Itoa(int(h.Ttl)) + "\t"
s = s + class_str[h.Class] + "\t"
s = s + rr_str[h.Rrtype] + "\t"
if h.Edns {
s = ";"
}
if len(h.Name) == 0 {
s += ".\t"
} else {
s += h.Name + "\t"
}
s = s + strconv.Itoa(int(h.Ttl)) + "\t"
s = s + class_str[h.Class] + "\t"
s = s + rr_str[h.Rrtype] + "\t"
return s
}
@ -354,16 +359,16 @@ func (rr *RR_AAAA) String() string {
// DNSSEC types
type RR_RRSIG struct {
Hdr RR_Header
TypeCovered uint16
Algorithm uint8
Labels uint8
OrigTtl uint32
Expiration uint32
Inception uint32
KeyTag uint16
SignerName string "domain-name"
Sig string "base64"
Hdr RR_Header
TypeCovered uint16
Algorithm uint8
Labels uint8
OrigTtl uint32
Expiration uint32
Inception uint32
KeyTag uint16
SignerName string "domain-name"
Sig string "base64"
}
func (rr *RR_RRSIG) Header() *RR_Header {
@ -376,8 +381,8 @@ func (rr *RR_RRSIG) Header() *RR_Header {
// needs serial stuff
// starts when 1970 has been 68 years ago??
func intToDate(t uint32) string {
// als meer dan 68 jaar geleden, dan 68 jaar bij bedrag optellen
// TODO
// als meer dan 68 jaar geleden, dan 68 jaar bij bedrag optellen
// TODO
ti := time.SecondsToUTC(int64(t))
return ti.Format("20060102030405")
}
@ -389,9 +394,9 @@ func (rr *RR_RRSIG) String() string {
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.Labels)) +
" " + strconv.Itoa(int(rr.OrigTtl)) +
// " " + strconv.Itoa(int(rr.Expiration)) + // date calc! TODO
// " " + strconv.Itoa(int(rr.Expiration)) + // date calc! TODO
" " + intToDate(rr.Expiration) +
// " " + strconv.Itoa(int(rr.Inception)) + // date calc! TODO
// " " + strconv.Itoa(int(rr.Inception)) + // date calc! TODO
" " + intToDate(rr.Inception) +
" " + strconv.Itoa(int(rr.KeyTag)) +
" " + rr.SignerName +
@ -515,7 +520,7 @@ var rr_str = map[uint16]string{
TypeSRV: "SRV",
TypeA: "A",
TypeAAAA: "AAAA",
TypeOPT: "OPT",
TypeOPT: "OPT",
TypeDS: "DS",
TypeRRSIG: "RRSIG",
TypeNSEC: "NSEC",