Fixes for the new presentation of txt records

This commit is contained in:
Miek Gieben 2012-02-13 15:59:40 +01:00
parent 2f64868d3c
commit 2c44133163
4 changed files with 63 additions and 33 deletions

View File

@ -42,7 +42,7 @@ type Option struct {
// m.Extra[0] = opt // add OPT RR to the message // m.Extra[0] = opt // add OPT RR to the message
type RR_OPT struct { type RR_OPT struct {
Hdr RR_Header Hdr RR_Header
Option []Option "OPT" // tag is used in Pack and Unpack Option []Option "opt" // tag is used in Pack and Unpack
} }
func (rr *RR_OPT) Header() *RR_Header { func (rr *RR_OPT) Header() *RR_Header {

View File

@ -64,7 +64,7 @@ func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
t := new(dns.RR_TXT) t := new(dns.RR_TXT)
t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0} t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
t.Txt = str t.Txt = []string{str}
switch r.Question[0].Qtype { switch r.Question[0].Qtype {
case dns.TypeTXT: case dns.TypeTXT:

84
msg.go
View File

@ -367,8 +367,24 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
case reflect.Slice: case reflect.Slice:
switch val.Type().Field(i).Tag { switch val.Type().Field(i).Tag {
default: default:
println("dns: unknown tag packing slice", val.Type().Field(i).Tag)
return lenmsg, false return lenmsg, false
case "OPT": // edns case "txt":
for j := 0; j < val.Field(i).Len(); j++ {
element := val.Field(i).Index(j).String()
// Counted string: 1 byte length.
if len(element) > 255 || off+1+len(element) > lenmsg {
println("dns: overflow packing TXT string")
return len(msg), false
}
msg[off] = byte(len(element))
off++
for i := 0; i < len(element); i++ {
msg[off+i] = element[i]
}
off += len(element)
}
case "opt": // edns
// Length of the entire option section // Length of the entire option section
for j := 0; j < val.Field(i).Len(); j++ { for j := 0; j < val.Field(i).Len(); j++ {
element := val.Field(i).Index(j) element := val.Field(i).Index(j)
@ -387,7 +403,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
copy(msg[off:off+len(string(h))], h) copy(msg[off:off+len(string(h))], h)
off += len(string(h)) off += len(string(h))
} }
case "A": case "a":
// It must be a slice of 4, even if it is 16, we encode // It must be a slice of 4, even if it is 16, we encode
// only the first 4 // only the first 4
switch fv.Len() { switch fv.Len() {
@ -417,7 +433,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
println("dns: overflow packing A") println("dns: overflow packing A")
return lenmsg, false return lenmsg, false
} }
case "AAAA": case "aaaa":
if fv.Len() > net.IPv6len || off+fv.Len() > lenmsg { if fv.Len() > net.IPv6len || off+fv.Len() > lenmsg {
println("dns: overflow packing AAAA") println("dns: overflow packing AAAA")
return lenmsg, false return lenmsg, false
@ -426,7 +442,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
msg[off] = byte(fv.Index(j).Uint()) msg[off] = byte(fv.Index(j).Uint())
off++ off++
} }
case "NSEC": // NSEC/NSEC3 case "nsec": // NSEC/NSEC3
// This is the uint16 type bitmap // This is the uint16 type bitmap
if val.Field(i).Len() == 0 { if val.Field(i).Len() == 0 {
// Do absolutely nothing // Do absolutely nothing
@ -577,8 +593,6 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
copy(msg[off:off+len(s)], s) copy(msg[off:off+len(s)], s)
off += len(s) off += len(s)
case "txt": case "txt":
// Counted string: 1 byte length, but the string may be longer
// than 255, in that case it should be multiple strings, for now:
fallthrough fallthrough
case "": case "":
// Counted string: 1 byte length. // Counted string: 1 byte length.
@ -625,25 +639,25 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
case reflect.Slice: case reflect.Slice:
switch val.Type().Field(i).Tag { switch val.Type().Field(i).Tag {
default: default:
println("dns: unknown tag unpacking struct") println("dns: unknown tag unpacking slice", val.Type().Field(i).Tag)
return lenmsg, false return lenmsg, false
case "A": case "txt":
if off+net.IPv4len > len(msg) { txt := make([]string,0)
println("dns: overflow unpacking A") rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
return lenmsg, false Txts:
} l := int(msg[off])
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3]))) if off + l + 1 > lenmsg {
off += net.IPv4len println("dns: failure unpacking txt strings")
case "AAAA": return lenmsg, false
if off+net.IPv6len > lenmsg { }
println("dns: overflow unpacking AAAA") txt = append(txt, string(msg[off+1:off+l]))
return lenmsg, false off += l
} if off < rdlength {
fv.Set(reflect.ValueOf(net.IP{msg[off], msg[off+1], msg[off+2], msg[off+3], msg[off+4], // More
msg[off+5], msg[off+6], msg[off+7], msg[off+8], msg[off+9], msg[off+10], goto Txts
msg[off+11], msg[off+12], msg[off+13], msg[off+14], msg[off+15]})) }
off += net.IPv6len fv.Set(reflect.ValueOf(txt))
case "OPT": // EDNS case "opt": // EDNS
if off+2 > lenmsg { if off+2 > lenmsg {
// This is an ENDNS0 (OPT Record) with no rdata // This is an ENDNS0 (OPT Record) with no rdata
// We can savely return here. // We can savely return here.
@ -659,7 +673,23 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
opt[0].Data = hex.EncodeToString(msg[off1 : off1+int(optlen)]) opt[0].Data = hex.EncodeToString(msg[off1 : off1+int(optlen)])
fv.Set(reflect.ValueOf(opt)) fv.Set(reflect.ValueOf(opt))
off = off1 + int(optlen) off = off1 + int(optlen)
case "NSEC": // NSEC/NSEC3 case "a":
if off+net.IPv4len > len(msg) {
println("dns: overflow unpacking A")
return lenmsg, false
}
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
off += net.IPv4len
case "aaaa":
if off+net.IPv6len > lenmsg {
println("dns: overflow unpacking AAAA")
return lenmsg, false
}
fv.Set(reflect.ValueOf(net.IP{msg[off], msg[off+1], msg[off+2], msg[off+3], msg[off+4],
msg[off+5], msg[off+6], msg[off+7], msg[off+8], msg[off+9], msg[off+10],
msg[off+11], msg[off+12], msg[off+13], msg[off+14], msg[off+15]}))
off += net.IPv6len
case "nsec": // NSEC/NSEC3
// Rest of the Record is the type bitmap // Rest of the Record is the type bitmap
rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
var endrr int var endrr int
@ -868,7 +898,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
s = hex.EncodeToString(msg[off : off+size]) s = hex.EncodeToString(msg[off : off+size])
off += size off += size
case "txt": case "txt":
// 1 or multiple txt pieces // 1 txt piece
rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
Txt: Txt:
if off >= lenmsg || off+1+int(msg[off]) > lenmsg { if off >= lenmsg || off+1+int(msg[off]) > lenmsg {
@ -882,7 +912,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
} }
off += n off += n
if off < rdlength { if off < rdlength {
// More to come // More to
goto Txt goto Txt
} }
case "": case "":

View File

@ -491,7 +491,7 @@ func (rr *RR_DNAME) Len() int {
type RR_A struct { type RR_A struct {
Hdr RR_Header Hdr RR_Header
A net.IP "A" A net.IP "a"
} }
func (rr *RR_A) Header() *RR_Header { func (rr *RR_A) Header() *RR_Header {
@ -508,7 +508,7 @@ func (rr *RR_A) Len() int {
type RR_AAAA struct { type RR_AAAA struct {
Hdr RR_Header Hdr RR_Header
AAAA net.IP "AAAA" AAAA net.IP "aaaa"
} }
func (rr *RR_AAAA) Header() *RR_Header { func (rr *RR_AAAA) Header() *RR_Header {
@ -584,7 +584,7 @@ func (rr *RR_RRSIG) Len() int {
type RR_NSEC struct { type RR_NSEC struct {
Hdr RR_Header Hdr RR_Header
NextDomain string "domain-name" NextDomain string "domain-name"
TypeBitMap []uint16 "NSEC" TypeBitMap []uint16 "nsec"
} }
func (rr *RR_NSEC) Header() *RR_Header { func (rr *RR_NSEC) Header() *RR_Header {
@ -769,7 +769,7 @@ type RR_NSEC3 struct {
Salt string "size-hex" Salt string "size-hex"
HashLength uint8 HashLength uint8
NextDomain string "size-base32" NextDomain string "size-base32"
TypeBitMap []uint16 "NSEC" TypeBitMap []uint16 "nsec"
} }
func (rr *RR_NSEC3) Header() *RR_Header { func (rr *RR_NSEC3) Header() *RR_Header {