commit
65752c4214
|
@ -118,6 +118,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||
* 6605 - ECDSA
|
||||
* 6725 - IANA Registry Update
|
||||
* 6742 - ILNP DNS
|
||||
* 6844 - CAA record
|
||||
* 6891 - EDNS0 update
|
||||
* 6895 - DNS IANA considerations
|
||||
* 6975 - Algorithm Understanding in DNSSEC
|
||||
|
@ -138,6 +139,5 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||
* privatekey.Precompute() when signing?
|
||||
* Last remaining RRs: APL, ATMA, A6 and NXT and IPSECKEY;
|
||||
* Missing in parsing: ISDN, UNSPEC, ATMA;
|
||||
* CAA parsing is broken;
|
||||
* NSEC(3) cover/match/closest enclose;
|
||||
* Replies with TC bit are not parsed to the end;
|
||||
|
|
|
@ -429,9 +429,6 @@ func TestToRFC3597(t *testing.T) {
|
|||
func TestNoRdataPack(t *testing.T) {
|
||||
data := make([]byte, 1024)
|
||||
for typ, fn := range typeToRR {
|
||||
if typ == TypeCAA {
|
||||
continue // TODO(miek): known omission
|
||||
}
|
||||
r := fn()
|
||||
*r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 3600}
|
||||
_, err := PackRR(r, data, 0, nil, false)
|
||||
|
|
43
msg.go
43
msg.go
|
@ -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"`:
|
||||
bytesTmp := make([]byte, 0)
|
||||
off, err = packOctetString(fv.String(), msg, off, bytesTmp)
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
72
types.go
72
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
|
||||
|
@ -1527,8 +1558,6 @@ func (rr *EUI64) copy() RR { return &EUI64{*rr.Hdr.copyHeader(), rr.Ad
|
|||
func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
|
||||
func (rr *EUI64) len() int { return rr.Hdr.len() + 8 }
|
||||
|
||||
// Support in incomplete - just handle it as unknown record
|
||||
/*
|
||||
type CAA struct {
|
||||
Hdr RR_Header
|
||||
Flag uint8
|
||||
|
@ -1538,14 +1567,9 @@ type CAA struct {
|
|||
|
||||
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) + 1 + len(rr.Value) }
|
||||
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() + strconv.FormatInt(int64(rr.Flag), 10) + " " + rr.Tag
|
||||
s += strconv.QuoteToASCII(rr.Value)
|
||||
return s
|
||||
}
|
||||
*/
|
||||
|
||||
type UID struct {
|
||||
Hdr RR_Header
|
||||
|
@ -1668,10 +1692,10 @@ func copyIP(ip net.IP) net.IP {
|
|||
|
||||
// Map of constructors for each RR type.
|
||||
var typeToRR = map[uint16]func() RR{
|
||||
TypeA: func() RR { return new(A) },
|
||||
TypeAAAA: func() RR { return new(AAAA) },
|
||||
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||
// TypeCAA: func() RR { return new(CAA) },
|
||||
TypeA: func() RR { return new(A) },
|
||||
TypeAAAA: func() RR { return new(AAAA) },
|
||||
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||
TypeCAA: func() RR { return new(CAA) },
|
||||
TypeCDS: func() RR { return new(CDS) },
|
||||
TypeCERT: func() RR { return new(CERT) },
|
||||
TypeCNAME: func() RR { return new(CNAME) },
|
||||
|
|
34
zscan_rr.go
34
zscan_rr.go
|
@ -2170,10 +2170,44 @@ func setIPSECKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string)
|
|||
return rr, nil, c1
|
||||
}
|
||||
|
||||
func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||
rr := new(CAA)
|
||||
rr.Hdr = h
|
||||
l := <-c
|
||||
if l.length == 0 {
|
||||
return rr, nil, l.comment
|
||||
}
|
||||
i, err := strconv.Atoi(l.token)
|
||||
if err != nil {
|
||||
return nil, &ParseError{f, "bad CAA Flag", l}, ""
|
||||
}
|
||||
rr.Flag = uint8(i)
|
||||
|
||||
<-c // zBlank
|
||||
l = <-c // zString
|
||||
if l.value != zString {
|
||||
return nil, &ParseError{f, "bad CAA Tag", l}, ""
|
||||
}
|
||||
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 {
|
||||
rr.Value = s[0]
|
||||
}
|
||||
return rr, nil, c1
|
||||
}
|
||||
|
||||
var typeToparserFunc = map[uint16]parserFunc{
|
||||
TypeAAAA: parserFunc{setAAAA, false},
|
||||
TypeAFSDB: parserFunc{setAFSDB, false},
|
||||
TypeA: parserFunc{setA, false},
|
||||
TypeCAA: parserFunc{setCAA, true},
|
||||
TypeCDS: parserFunc{setCDS, true},
|
||||
TypeCDNSKEY: parserFunc{setCDNSKEY, true},
|
||||
TypeCERT: parserFunc{setCERT, true},
|
||||
|
|
Loading…
Reference in New Issue