Use an interface method for parsing zone file records (#886)

* Eliminate Variable bool from parserFunc

Instead we now check whether the last token read from the zlexer was
a zNewline or zEOF. The error check above should be tripped for any
record that ends prematurely.

* Use an interface method for parsing zone file records

* Prevent panic in TestOmittedTTL if no regexp match

* Move slurpRemainder into fixed length parse functions

This is consistent with the original logic in setRR and avoids potential
edge cases.

* Parse synthetic records according to RFC 3597

These records lack a presentation format and cannot be parsed otherwise.
This behaviour is consistent with how this previously operated.
This commit is contained in:
Tom Thorogood 2019-01-06 14:36:16 +10:30 committed by GitHub
parent 44a8c5f8ba
commit db3d0ce13b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 452 additions and 702 deletions

9
dns.go
View File

@ -50,6 +50,11 @@ type RR interface {
// This will only be called on a new and empty RR type with only the header populated. It
// will only be called if the record's RDATA is non-empty.
unpack(msg []byte, off int) (off1 int, err error)
// parse parses an RR from zone file format.
//
// This will only be called on a new and empty RR type with only the header populated.
parse(c *zlexer, origin, file string) *ParseError
}
// RR_Header is the header all DNS resource records share.
@ -97,6 +102,10 @@ func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
panic("dns: internal error: unpack should never be called on RR_Header")
}
func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on RR_Header")
}
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
func (rr *RFC3597) ToRFC3597(r RR) error {
buf := make([]byte, Len(r)*2)

View File

@ -88,6 +88,10 @@ func (rr *OPT) len(off int, compression map[string]struct{}) int {
return l
}
func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on OPT")
}
// return the old value -> delete SetVersion?
// Version returns the EDNS version used. Only zero is defined.

View File

@ -543,6 +543,10 @@ example.com. DNAME 10 ; TTL=314 after second $TTL
continue
}
expected := reCaseFromComment.FindStringSubmatch(record.Comment)
if len(expected) != 3 {
t.Errorf("regexp didn't match for record %d", i)
continue
}
expectedTTL, _ := strconv.ParseUint(expected[1], 10, 32)
ttl := record.RR.Header().Ttl
if ttl != uint32(expectedTTL) {

View File

@ -86,22 +86,10 @@ func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
return off, err
}
// PrivateHandle registers a private resource record type. It requires
// string and numeric representation of private RR type and generator function as argument.
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
rtypestr = strings.ToUpper(rtypestr)
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
TypeToString[rtype] = rtypestr
StringToType[rtypestr] = rtype
setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) {
rr := mkPrivateRR(h.Rrtype)
rr.Hdr = h
func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError {
var l lex
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
Fetch:
Fetch:
for {
// TODO(miek): we could also be returning _QUOTE, this might or might not
// be an issue (basically parsing TXT becomes hard)
@ -113,15 +101,22 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
}
}
err := rr.Data.Parse(text)
err := r.Data.Parse(text)
if err != nil {
return nil, &ParseError{f, err.Error(), l}
return &ParseError{file, err.Error(), l}
}
return rr, nil
}
return nil
}
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
// PrivateHandle registers a private resource record type. It requires
// string and numeric representation of private RR type and generator function as argument.
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
rtypestr = strings.ToUpper(rtypestr)
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
TypeToString[rtype] = rtypestr
StringToType[rtypestr] = rtype
}
// PrivateHandleRemove removes definitions required to support private RR type.
@ -130,7 +125,6 @@ func PrivateHandleRemove(rtype uint16) {
if ok {
delete(TypeToRR, rtype)
delete(TypeToString, rtype)
delete(typeToparserFunc, rtype)
delete(StringToType, rtypestr)
}
}

1047
scan_rr.go

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,10 @@ func (rr *TSIG) String() string {
return s
}
func (rr *TSIG) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on TSIG")
}
// The following values must be put in wireformat, so that the MAC can be calculated.
// RFC 2845, section 3.4.2. TSIG Variables.
type tsigWireFmt struct {

View File

@ -238,6 +238,10 @@ type ANY struct {
func (rr *ANY) String() string { return rr.Hdr.String() }
func (rr *ANY) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on ANY")
}
// NULL RR. See RFC 1035.
type NULL struct {
Hdr RR_Header
@ -249,6 +253,10 @@ func (rr *NULL) String() string {
return ";" + rr.Hdr.String() + rr.Data
}
func (rr *NULL) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on NULL")
}
// CNAME RR. See RFC 1034.
type CNAME struct {
Hdr RR_Header