Switch setCAA, CAA.String to presentation format, add various encoding helpers

This commit is contained in:
Roland Shoemaker 2015-06-17 16:06:31 -07:00
parent 1995ce2be4
commit 020002b9e0
5 changed files with 132 additions and 57 deletions

45
msg.go
View File

@ -100,7 +100,7 @@ var TypeToString = map[uint16]string{
TypeANY: "ANY", // Meta RR
TypeATMA: "ATMA",
TypeAXFR: "AXFR", // Meta RR
TypeCAA: "TYPE257",
TypeCAA: "CAA",
TypeCDNSKEY: "CDNSKEY",
TypeCDS: "CDS",
TypeCERT: "CERT",
@ -543,6 +543,36 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
return offset, nil
}
func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
if offset >= len(msg) {
return offset, ErrBuf
}
bs := tmp[:len(s)]
copy(bs, s)
for i := 0; i < len(bs); i++ {
if len(msg) <= offset {
return offset, ErrBuf
}
if bs[i] == '\\' {
i++
if i == len(bs) {
break
}
// check for \DDD
if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
msg[offset] = dddToByte(bs[i:])
i += 2
} else {
msg[offset] = bs[i]
}
} else {
msg[offset] = bs[i]
}
offset++
}
return offset, nil
}
func unpackTxt(msg []byte, offset, rdend int) ([]string, int, error) {
var err error
var ss []string
@ -890,6 +920,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
// length of string. String is RAW (not encoded in hex, nor base64)
copy(msg[off:off+len(s)], s)
off += len(s)
case `dns:"octet"`:
var varstrTmp []byte
off, err = packOctetString(fv.String(), msg, off, varstrTmp)
if err != nil {
return lenmsg, err
}
case `dns:"txt"`:
fallthrough
case "":
@ -1254,6 +1290,13 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
switch val.Type().Field(i).Tag {
default:
return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")}
case `dns:"octet"`:
strend := lenrd
if strend > lenmsg {
return lenmsg, &Error{err: "overflow unpacking octet"}
}
s = string(msg[off:strend])
off = strend
case `dns:"hex"`:
hexend := lenrd
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {

View File

@ -1455,3 +1455,25 @@ func TestParseHINFO(t *testing.T) {
}
}
}
func TestParseCAA(t *testing.T) {
lt := map[string]string{
"example.net. CAA 0 issue \"symantec.com\"": "example.net.\t3600\tIN\tCAA\t0 issue \"symantec.com\"",
"example.net. CAA 0 issuewild \"symantec.com; stuff\"": "example.net.\t3600\tIN\tCAA\t0 issuewild \"symantec.com; stuff\"",
"example.net. CAA 128 tbs \"critical\"": "example.net.\t3600\tIN\tCAA\t128 tbs \"critical\"",
"example.net. CAA 2 auth \"0>09\\006\\010+\\006\\001\\004\\001\\214y\\002\\003\\001\\006\\009`\\134H\\001e\\003\\004\\002\\001\\004 y\\209\\012\\221r\\220\\156Q\\218\\150\\150{\\166\\245:\\231\\182%\\157:\\133\\179}\\1923r\\238\\151\\255\\128q\\145\\002\\001\\000\"": "example.net.\t3600\tIN\tCAA\t2 auth \"0>09\\006\\010+\\006\\001\\004\\001\\214y\\002\\003\\001\\006\\009`\\134H\\001e\\003\\004\\002\\001\\004 y\\209\\012\\221r\\220\\156Q\\218\\150\\150{\\166\\245:\\231\\182%\\157:\\133\\179}\\1923r\\238\\151\\255\\128q\\145\\002\\001\\000\"",
"example.net. TYPE257 0 issue \"symantec.com\"": "example.net.\t3600\tIN\tCAA\t0 issue \"symantec.com\"",
}
for i, o := range lt {
rr, err := NewRR(i)
if err != nil {
t.Error("failed to parse RR: ", err)
continue
}
if rr.String() != o {
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String())
} else {
t.Logf("RR is OK: `%s'", rr.String())
}
}
}

View File

@ -501,6 +501,34 @@ func sprintName(s string) string {
return string(dst)
}
func sprintCAAValue(s string) string {
src := []byte(s)
dst := make([]byte, 0, len(src))
dst = append(dst, '"')
for i := 0; i < len(src); {
if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
dst = append(dst, src[i:i+2]...)
i += 2
} else {
b, n := nextByte(src, i)
if n == 0 {
i++ // dangling back slash
} else if b == '.' {
dst = append(dst, b)
} else {
if b < ' ' || b > '~' {
dst = appendByte(dst, b)
} else {
dst = append(dst, b)
}
}
i += n
}
}
dst = append(dst, '"')
return string(dst)
}
func sprintTxt(txt []string) string {
var out []byte
for i, s := range txt {
@ -543,21 +571,24 @@ func appendTXTStringByte(s []byte, b byte) []byte {
return append(s, '\\', b)
}
if b < ' ' || b > '~' {
var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\')
for i := 0; i < 3-len(bufs); i++ {
s = append(s, '0')
}
for _, r := range bufs {
s = append(s, r)
}
return s
return appendByte(s, b)
}
return append(s, b)
}
func appendByte(s []byte, b byte) []byte {
var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\')
for i := 0; i < 3-len(bufs); i++ {
s = append(s, '0')
}
for _, r := range bufs {
s = append(s, r)
}
return s
}
func nextByte(b []byte, offset int) (byte, int) {
if offset >= len(b) {
return 0, 0
@ -1531,20 +1562,13 @@ type CAA struct {
Hdr RR_Header
Flag uint8
Tag string
Value string `dns:"hex"`
Value string `dns:"octet"`
}
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
func (rr *CAA) copy() RR { return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value} }
func (rr *CAA) len() int { return rr.Hdr.len() + 1 + len(rr.Tag) + len(rr.Value)/2 }
func (rr *CAA) String() string {
s := rr.Hdr.String()
s += "\\# " + strconv.Itoa(2 + len(rr.Tag) + len(rr.Value)/2) + " "
s += fmt.Sprintf("%02X%02X%X%s", rr.Flag, len(rr.Tag), rr.Tag, strings.ToUpper(rr.Value))
return s
}
func (rr *CAA) String() string { return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintCAAValue(rr.Value) }
type UID struct {

View File

@ -8,7 +8,7 @@ import (
func TestDynamicUpdateParsing(t *testing.T) {
prefix := "example.com. IN "
for _, typ := range TypeToString {
if typ == "TYPE257" || typ == "OPT" || typ == "AXFR" || typ == "IXFR" || typ == "ANY" || typ == "TKEY" ||
if typ == "CAA" || typ == "OPT" || typ == "AXFR" || typ == "IXFR" || typ == "ANY" || typ == "TKEY" ||
typ == "TSIG" || typ == "ISDN" || typ == "UNSPEC" || typ == "NULL" || typ == "ATMA" {
continue
}

View File

@ -2,7 +2,6 @@ package dns
import (
"encoding/base64"
"encoding/hex"
"net"
"strconv"
"strings"
@ -2175,47 +2174,34 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(CAA)
rr.Hdr = h
l := <-c
if l.token != "\\#" {
return nil, &ParseError{f, "bad CAA Rdata", l}, ""
if l.length == 0 {
return rr, nil, l.comment
}
<-c // zBlank
l = <-c
rdlength, e := strconv.Atoi(l.token)
if e != nil {
return nil, &ParseError{f, "bad CAA Rdata", l}, ""
}
s, e1, c1 := endingToString(c, "bad CAA Rdata", f)
if e1 != nil {
return nil, e1, c1
}
if rdlength*2 != len(s) || len(s) < 4 {
return nil, &ParseError{f, "bad CAA Rdata", l}, ""
}
flagbyte, e := hex.DecodeString(s[0:2])
if e != nil {
i, err := strconv.Atoi(l.token)
if err != nil {
return nil, &ParseError{f, "bad CAA Flag", l}, ""
}
rr.Flag = uint8(flagbyte[0])
rr.Flag = uint8(i)
tagbyte, e := hex.DecodeString(s[2:4])
if e != nil {
return nil, &ParseError{f, "bad CAA Tag length", l}, ""
}
taglength := int(tagbyte[0])
if rdlength*2 < (4 + taglength) {
return nil, &ParseError{f, "bad CAA Tag length", l}, ""
}
tag, e := hex.DecodeString(s[4:4+(taglength*2)])
if e != nil {
<-c // zBlank
l = <-c // zString
if l.value != zString {
return nil, &ParseError{f, "bad CAA Tag", l}, ""
}
rr.Tag = string(tag)
rr.Value = s[4+(taglength*2):]
rr.Tag = l.token
<-c // zBlank
s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f)
if e != nil {
return nil, e, ""
}
if len(s) > 1 {
return nil, &ParseError{f, "bad CAA Value", l}, ""
} else if len(s) == 0 {
rr.Value = ""
} else {
rr.Value = s[0]
}
return rr, nil, c1
}