Generate pack/unpack for all RRs (#360)
Add dns:txt parsing helper to prevent compile errors. This allows us to generate all unpack/pack function. Add pack to the RR interface definition and add this method to PrivateRR. We still use typeToUnpack to select which types don't use reflection.
This commit is contained in:
parent
3f53d75269
commit
907a4aef57
2
dns.go
2
dns.go
|
@ -34,6 +34,8 @@ type RR interface {
|
||||||
copy() RR
|
copy() RR
|
||||||
// len returns the length (in octets) of the uncompressed RR in wire format.
|
// len returns the length (in octets) of the uncompressed RR in wire format.
|
||||||
len() int
|
len() int
|
||||||
|
// pack packs an RR into wire format.
|
||||||
|
pack([]byte, int, map[string]int, bool) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RR_Header is the header all DNS resource records share.
|
// RR_Header is the header all DNS resource records share.
|
||||||
|
|
52
msg.go
52
msg.go
|
@ -1354,56 +1354,8 @@ func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress boo
|
||||||
_, ok := typeToUnpack[rr.Header().Rrtype]
|
_, ok := typeToUnpack[rr.Header().Rrtype]
|
||||||
switch ok {
|
switch ok {
|
||||||
case true:
|
case true:
|
||||||
// Shortcut reflection, `pack' needs to be added to the RR interface so we can just do this:
|
off1, err = rr.pack(msg, off, compression, compress)
|
||||||
// off1, err = t.pack(msg, off, compression, compress)
|
// TODO(miek): revert the logic and make a blacklist for types that still use reflection. Kill typeToUnpack.
|
||||||
// TODO(miek): revert the logic and make a blacklist for types that still use reflection. Kill
|
|
||||||
// typeToUnpack and just generate all the pack and unpack functions even though we don't use
|
|
||||||
// them for all types (yet).
|
|
||||||
switch t := rr.(type) {
|
|
||||||
case *RR_Header:
|
|
||||||
// we can be called with an empty RR, consisting only out of the header, see update_test.go's
|
|
||||||
// TestDynamicUpdateZeroRdataUnpack for an example. This is OK as RR_Header also implements the RR interface.
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *ANY:
|
|
||||||
// Also "weird" setup, see (again) update_test.go's TestRemoveRRset, where the Rrtype is 1 but the type is *ANY.
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *A:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *AAAA:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *CNAME:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *DNAME:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *HINFO:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *L32:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *LOC:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *MB:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *MD:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *MF:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *MG:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *MX:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *NID:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *NS:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *PTR:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *RP:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *SRV:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
case *DNSKEY:
|
|
||||||
off1, err = t.pack(msg, off, compression, compress)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
off1, err = packStructCompress(rr, msg, off, compression, compress)
|
off1, err = packStructCompress(rr, msg, off, compression, compress)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,37 +29,6 @@ import (
|
||||||
// * NINFO
|
// * NINFO
|
||||||
// * PrivateRR
|
// * PrivateRR
|
||||||
|
|
||||||
// What types are we generating, should be kept in sync with typeToUnpack in msg.go
|
|
||||||
var generate = map[string]bool{
|
|
||||||
"AAAA": true,
|
|
||||||
"ANY": true,
|
|
||||||
"A": true,
|
|
||||||
"CNAME": true,
|
|
||||||
"DNAME": true,
|
|
||||||
"DNSKEY": true,
|
|
||||||
"HINFO": true,
|
|
||||||
"L32": true,
|
|
||||||
"LOC": true,
|
|
||||||
"MB": true,
|
|
||||||
"MD": true,
|
|
||||||
"MF": true,
|
|
||||||
"MG": true,
|
|
||||||
"MR": true,
|
|
||||||
"MX": true,
|
|
||||||
"NID": true,
|
|
||||||
"NS": true,
|
|
||||||
"PTR": true,
|
|
||||||
"RP": true,
|
|
||||||
"SRV": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldGenerate(name string) bool {
|
|
||||||
_, ok := generate[name]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// For later: IPSECKEY is weird.
|
|
||||||
|
|
||||||
var packageHdr = `
|
var packageHdr = `
|
||||||
// *** DO NOT MODIFY ***
|
// *** DO NOT MODIFY ***
|
||||||
// AUTOGENERATED BY go generate from msg_generate.go
|
// AUTOGENERATED BY go generate from msg_generate.go
|
||||||
|
@ -123,7 +92,7 @@ func main() {
|
||||||
for _, name := range namedTypes {
|
for _, name := range namedTypes {
|
||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
if isEmbedded || !shouldGenerate(name) {
|
if isEmbedded {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,17 +112,17 @@ return off, err
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
//switch st.Tag(i) {
|
switch st.Tag(i) {
|
||||||
//case `dns:"-"`:
|
case `dns:"-"`:
|
||||||
//// ignored
|
// ignored
|
||||||
//case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
case `dns:"txt"`:
|
||||||
//o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
o("off, err = packStringTxt(rr.%s, msg, off)\n")
|
||||||
//default:
|
default:
|
||||||
//log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
//log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
//}
|
}
|
||||||
//continue
|
continue
|
||||||
//}
|
}
|
||||||
|
|
||||||
switch st.Tag(i) {
|
switch st.Tag(i) {
|
||||||
case `dns:"-"`:
|
case `dns:"-"`:
|
||||||
|
@ -202,7 +171,7 @@ return off, err
|
||||||
for _, name := range namedTypes {
|
for _, name := range namedTypes {
|
||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
if isEmbedded || !shouldGenerate(name) {
|
if isEmbedded {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,17 +195,17 @@ return rr, off, err
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
//switch st.Tag(i) {
|
switch st.Tag(i) {
|
||||||
//case `dns:"-"`:
|
case `dns:"-"`:
|
||||||
//// ignored
|
// ignored
|
||||||
//case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
case `dns:"txt"`:
|
||||||
//o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
|
||||||
//default:
|
default:
|
||||||
//log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
//log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
//}
|
}
|
||||||
//continue
|
continue
|
||||||
//}
|
}
|
||||||
|
|
||||||
switch st.Tag(i) {
|
switch st.Tag(i) {
|
||||||
case `dns:"-"`:
|
case `dns:"-"`:
|
||||||
|
|
|
@ -397,3 +397,20 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
|
||||||
off += len(h)
|
off += len(h)
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
|
||||||
|
txt, off, err := unpackTxt(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return nil, len(msg), err
|
||||||
|
}
|
||||||
|
return txt, off, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func packStringTxt(s []string, msg []byte, off int) (int, error) {
|
||||||
|
txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
|
||||||
|
off, err := packTxt(s, msg, off, txtTmp)
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
|
@ -65,6 +65,14 @@ func (r *PrivateRR) copy() RR {
|
||||||
}
|
}
|
||||||
return rr
|
return rr
|
||||||
}
|
}
|
||||||
|
func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
|
n, err := r.Data.Pack(msg[off:])
|
||||||
|
if err != nil {
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
off += n
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrivateHandle registers a private resource record type. It requires
|
// PrivateHandle registers a private resource record type. It requires
|
||||||
// string and numeric representation of private RR type and generator function as argument.
|
// string and numeric representation of private RR type and generator function as argument.
|
||||||
|
|
Loading…
Reference in New Issue