Switch setCAA, CAA.String to presentation format, add various encoding helpers
This commit is contained in:
parent
1995ce2be4
commit
020002b9e0
45
msg.go
45
msg.go
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
64
types.go
64
types.go
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
56
zscan_rr.go
56
zscan_rr.go
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue