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
|
TypeANY: "ANY", // Meta RR
|
||||||
TypeATMA: "ATMA",
|
TypeATMA: "ATMA",
|
||||||
TypeAXFR: "AXFR", // Meta RR
|
TypeAXFR: "AXFR", // Meta RR
|
||||||
TypeCAA: "TYPE257",
|
TypeCAA: "CAA",
|
||||||
TypeCDNSKEY: "CDNSKEY",
|
TypeCDNSKEY: "CDNSKEY",
|
||||||
TypeCDS: "CDS",
|
TypeCDS: "CDS",
|
||||||
TypeCERT: "CERT",
|
TypeCERT: "CERT",
|
||||||
|
@ -543,6 +543,36 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
|
||||||
return offset, nil
|
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) {
|
func unpackTxt(msg []byte, offset, rdend int) ([]string, int, error) {
|
||||||
var err error
|
var err error
|
||||||
var ss []string
|
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)
|
// length of string. String is RAW (not encoded in hex, nor base64)
|
||||||
copy(msg[off:off+len(s)], s)
|
copy(msg[off:off+len(s)], s)
|
||||||
off += len(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"`:
|
case `dns:"txt"`:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "":
|
case "":
|
||||||
|
@ -1254,6 +1290,13 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
||||||
switch val.Type().Field(i).Tag {
|
switch val.Type().Field(i).Tag {
|
||||||
default:
|
default:
|
||||||
return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")}
|
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"`:
|
case `dns:"hex"`:
|
||||||
hexend := lenrd
|
hexend := lenrd
|
||||||
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
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)
|
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 {
|
func sprintTxt(txt []string) string {
|
||||||
var out []byte
|
var out []byte
|
||||||
for i, s := range txt {
|
for i, s := range txt {
|
||||||
|
@ -543,21 +571,24 @@ func appendTXTStringByte(s []byte, b byte) []byte {
|
||||||
return append(s, '\\', b)
|
return append(s, '\\', b)
|
||||||
}
|
}
|
||||||
if b < ' ' || b > '~' {
|
if b < ' ' || b > '~' {
|
||||||
var buf [3]byte
|
return appendByte(s, b)
|
||||||
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 append(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) {
|
func nextByte(b []byte, offset int) (byte, int) {
|
||||||
if offset >= len(b) {
|
if offset >= len(b) {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
@ -1531,20 +1562,13 @@ type CAA struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Flag uint8
|
Flag uint8
|
||||||
Tag string
|
Tag string
|
||||||
Value string `dns:"hex"`
|
Value string `dns:"octet"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
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) 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) len() int { return rr.Hdr.len() + 1 + len(rr.Tag) + len(rr.Value)/2 }
|
||||||
|
func (rr *CAA) String() string { return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintCAAValue(rr.Value) }
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type UID struct {
|
type UID struct {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
func TestDynamicUpdateParsing(t *testing.T) {
|
func TestDynamicUpdateParsing(t *testing.T) {
|
||||||
prefix := "example.com. IN "
|
prefix := "example.com. IN "
|
||||||
for _, typ := range TypeToString {
|
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" {
|
typ == "TSIG" || typ == "ISDN" || typ == "UNSPEC" || typ == "NULL" || typ == "ATMA" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
56
zscan_rr.go
56
zscan_rr.go
|
@ -2,7 +2,6 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -2175,47 +2174,34 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
rr := new(CAA)
|
rr := new(CAA)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
l := <-c
|
l := <-c
|
||||||
if l.token != "\\#" {
|
if l.length == 0 {
|
||||||
return nil, &ParseError{f, "bad CAA Rdata", l}, ""
|
return rr, nil, l.comment
|
||||||
}
|
}
|
||||||
<-c // zBlank
|
i, err := strconv.Atoi(l.token)
|
||||||
l = <-c
|
if err != nil {
|
||||||
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 {
|
|
||||||
return nil, &ParseError{f, "bad CAA Flag", l}, ""
|
return nil, &ParseError{f, "bad CAA Flag", l}, ""
|
||||||
}
|
}
|
||||||
rr.Flag = uint8(flagbyte[0])
|
rr.Flag = uint8(i)
|
||||||
|
|
||||||
tagbyte, e := hex.DecodeString(s[2:4])
|
<-c // zBlank
|
||||||
if e != nil {
|
l = <-c // zString
|
||||||
return nil, &ParseError{f, "bad CAA Tag length", l}, ""
|
if l.value != zString {
|
||||||
}
|
|
||||||
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 {
|
|
||||||
return nil, &ParseError{f, "bad CAA Tag", l}, ""
|
return nil, &ParseError{f, "bad CAA Tag", l}, ""
|
||||||
}
|
}
|
||||||
rr.Tag = string(tag)
|
rr.Tag = l.token
|
||||||
|
|
||||||
rr.Value = s[4+(taglength*2):]
|
|
||||||
|
|
||||||
|
<-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
|
return rr, nil, c1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue