From db3d0ce13bdc1a6b8c7f6bdf75448e9a4306951b Mon Sep 17 00:00:00 2001 From: Tom Thorogood Date: Sun, 6 Jan 2019 14:36:16 +1030 Subject: [PATCH] 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. --- dns.go | 9 + edns.go | 4 + parse_test.go | 26 +- privaterr.go | 52 ++- scan_rr.go | 1051 ++++++++++++++++++------------------------------- tsig.go | 4 + types.go | 8 + 7 files changed, 452 insertions(+), 702 deletions(-) diff --git a/dns.go b/dns.go index ee7474de..25f3c457 100644 --- a/dns.go +++ b/dns.go @@ -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) diff --git a/edns.go b/edns.go index 77111338..f366bdb1 100644 --- a/edns.go +++ b/edns.go @@ -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. diff --git a/parse_test.go b/parse_test.go index b5af01f4..9adb6484 100644 --- a/parse_test.go +++ b/parse_test.go @@ -341,7 +341,7 @@ func TestParseDirectiveMisc(t *testing.T) { func TestNSEC(t *testing.T) { nsectests := map[string]string{ - "nl. IN NSEC3PARAM 1 0 5 30923C44C6CBBB8F": "nl.\t3600\tIN\tNSEC3PARAM\t1 0 5 30923C44C6CBBB8F", + "nl. IN NSEC3PARAM 1 0 5 30923C44C6CBBB8F": "nl.\t3600\tIN\tNSEC3PARAM\t1 0 5 30923C44C6CBBB8F", "p2209hipbpnm681knjnu0m1febshlv4e.nl. IN NSEC3 1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM": "p2209hipbpnm681knjnu0m1febshlv4e.nl.\t3600\tIN\tNSEC3\t1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM", "localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC": "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC", "localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC TYPE65534": "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC TYPE65534", @@ -398,16 +398,16 @@ func TestQuotes(t *testing.T) { `t.example.com. IN TXT "a bc"`: "t.example.com.\t3600\tIN\tTXT\t\"a bc\"", `t.example.com. IN TXT "a bc"`: "t.example.com.\t3600\tIN\tTXT\t\"a\\010 bc\"", - `t.example.com. IN TXT ""`: "t.example.com.\t3600\tIN\tTXT\t\"\"", - `t.example.com. IN TXT "a"`: "t.example.com.\t3600\tIN\tTXT\t\"a\"", - `t.example.com. IN TXT "aa"`: "t.example.com.\t3600\tIN\tTXT\t\"aa\"", - `t.example.com. IN TXT "aaa" ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", - `t.example.com. IN TXT "abc" "DEF"`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", - `t.example.com. IN TXT "abc" ( "DEF" )`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", - `t.example.com. IN TXT aaa ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", - `t.example.com. IN TXT aaa aaa;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", - `t.example.com. IN TXT aaa aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", - `t.example.com. IN TXT aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", + `t.example.com. IN TXT ""`: "t.example.com.\t3600\tIN\tTXT\t\"\"", + `t.example.com. IN TXT "a"`: "t.example.com.\t3600\tIN\tTXT\t\"a\"", + `t.example.com. IN TXT "aa"`: "t.example.com.\t3600\tIN\tTXT\t\"aa\"", + `t.example.com. IN TXT "aaa" ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", + `t.example.com. IN TXT "abc" "DEF"`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", + `t.example.com. IN TXT "abc" ( "DEF" )`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", + `t.example.com. IN TXT aaa ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", + `t.example.com. IN TXT aaa aaa;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", + `t.example.com. IN TXT aaa aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", + `t.example.com. IN TXT aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", "cid.urn.arpa. NAPTR 100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu.", "cid.urn.arpa. NAPTR 100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu.", "cid.urn.arpa. NAPTR 100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu.", @@ -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) { diff --git a/privaterr.go b/privaterr.go index e84af220..98da17d1 100644 --- a/privaterr.go +++ b/privaterr.go @@ -86,6 +86,29 @@ func (r *PrivateRR) unpack(msg []byte, off int) (int, error) { return off, err } +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: + for { + // TODO(miek): we could also be returning _QUOTE, this might or might not + // be an issue (basically parsing TXT becomes hard) + switch l, _ = c.Next(); l.value { + case zNewline, zEOF: + break Fetch + case zString: + text = append(text, l.token) + } + } + + err := r.Data.Parse(text) + if err != nil { + return &ParseError{file, err.Error(), l} + } + + return nil +} + // 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) { @@ -94,34 +117,6 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) 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 - - var l lex - text := make([]string, 0, 2) // could be 0..N elements, median is probably 1 - Fetch: - for { - // TODO(miek): we could also be returning _QUOTE, this might or might not - // be an issue (basically parsing TXT becomes hard) - switch l, _ = c.Next(); l.value { - case zNewline, zEOF: - break Fetch - case zString: - text = append(text, l.token) - } - } - - err := rr.Data.Parse(text) - if err != nil { - return nil, &ParseError{f, err.Error(), l} - } - - return rr, nil - } - - typeToparserFunc[rtype] = parserFunc{setPrivateRR, true} } // 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) } } diff --git a/scan_rr.go b/scan_rr.go index 11b33abb..f48ff789 100644 --- a/scan_rr.go +++ b/scan_rr.go @@ -7,39 +7,38 @@ import ( "strings" ) -type parserFunc struct { - // Func defines the function that parses the tokens and returns the RR - // or an error. - Func func(h RR_Header, c *zlexer, origin string, file string) (RR, *ParseError) - // Signals if the RR ending is of variable length, like TXT or records - // that have Hexadecimal or Base64 as their last element in the Rdata. Records - // that have a fixed ending or for instance A, AAAA, SOA and etc. - Variable bool -} - // Parse the rdata of each rrtype. // All data from the channel c is either zString or zBlank. // After the rdata there may come a zBlank and then a zNewline // or immediately a zNewline. If this is not the case we flag // an *ParseError: garbage after rdata. func setRR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - parserfunc, ok := typeToparserFunc[h.Rrtype] - if ok { - r, e := parserfunc.Func(h, c, o, f) - if parserfunc.Variable { - return r, e - } - if e != nil { - return nil, e - } - e = slurpRemainder(c, f) - if e != nil { - return nil, e - } - return r, nil + var rr RR + if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) { + rr = newFn() + *rr.Header() = h + } else { + rr = &RFC3597{Hdr: h} + } + + err := rr.parse(c, o, f) + if err != nil { + return nil, err + } + + return rr, nil +} + +// canParseAsRR returns true if the record type can be parsed as a +// concrete RR. It blacklists certain record types that must be parsed +// according to RFC 3597 because they lack a presentation format. +func canParseAsRR(rrtype uint16) bool { + switch rrtype { + case TypeANY, TypeNULL, TypeOPT, TypeTSIG: + return false + default: + return true } - // RFC3957 RR (Unknown RR handling) - return setRFC3597(h, c, o, f) } // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces) @@ -127,105 +126,87 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError) { return s, nil } -func setA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(A) - rr.Hdr = h - +func (rr *A) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } rr.A = net.ParseIP(l.token) if rr.A == nil || l.err { - return nil, &ParseError{f, "bad A A", l} + return &ParseError{f, "bad A A", l} } - return rr, nil + return slurpRemainder(c, f) } -func setAAAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(AAAA) - rr.Hdr = h - +func (rr *AAAA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } rr.AAAA = net.ParseIP(l.token) if rr.AAAA == nil || l.err { - return nil, &ParseError{f, "bad AAAA AAAA", l} + return &ParseError{f, "bad AAAA AAAA", l} } - return rr, nil + return slurpRemainder(c, f) } -func setNS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NS) - rr.Hdr = h - +func (rr *NS) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Ns = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad NS Ns", l} + return &ParseError{f, "bad NS Ns", l} } rr.Ns = name - return rr, nil + return slurpRemainder(c, f) } -func setPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(PTR) - rr.Hdr = h - +func (rr *PTR) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Ptr = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad PTR Ptr", l} + return &ParseError{f, "bad PTR Ptr", l} } rr.Ptr = name - return rr, nil + return slurpRemainder(c, f) } -func setNSAPPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NSAPPTR) - rr.Hdr = h - +func (rr *NSAPPTR) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Ptr = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad NSAP-PTR Ptr", l} + return &ParseError{f, "bad NSAP-PTR Ptr", l} } rr.Ptr = name - return rr, nil + return slurpRemainder(c, f) } -func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(RP) - rr.Hdr = h - +func (rr *RP) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Mbox = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } mbox, mboxOk := toAbsoluteName(l.token, o) if l.err || !mboxOk { - return nil, &ParseError{f, "bad RP Mbox", l} + return &ParseError{f, "bad RP Mbox", l} } rr.Mbox = mbox @@ -235,78 +216,66 @@ func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { txt, txtOk := toAbsoluteName(l.token, o) if l.err || !txtOk { - return nil, &ParseError{f, "bad RP Txt", l} + return &ParseError{f, "bad RP Txt", l} } rr.Txt = txt - return rr, nil + return slurpRemainder(c, f) } -func setMR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MR) - rr.Hdr = h - +func (rr *MR) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Mr = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MR Mr", l} + return &ParseError{f, "bad MR Mr", l} } rr.Mr = name - return rr, nil + return slurpRemainder(c, f) } -func setMB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MB) - rr.Hdr = h - +func (rr *MB) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Mb = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MB Mb", l} + return &ParseError{f, "bad MB Mb", l} } rr.Mb = name - return rr, nil + return slurpRemainder(c, f) } -func setMG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MG) - rr.Hdr = h - +func (rr *MG) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Mg = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MG Mg", l} + return &ParseError{f, "bad MG Mg", l} } rr.Mg = name - return rr, nil + return slurpRemainder(c, f) } -func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(HINFO) - rr.Hdr = h - +func (rr *HINFO) parse(c *zlexer, o, f string) *ParseError { chunks, e := endingToTxtSlice(c, "bad HINFO Fields", f) if e != nil { - return nil, e + return e } if ln := len(chunks); ln == 0 { - return rr, nil + return nil } else if ln == 1 { // Can we split it? if out := strings.Fields(chunks[0]); len(out) > 1 { @@ -319,22 +288,19 @@ func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.Cpu = chunks[0] rr.Os = strings.Join(chunks[1:], " ") - return rr, nil + return nil } -func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MINFO) - rr.Hdr = h - +func (rr *MINFO) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Rmail = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } rmail, rmailOk := toAbsoluteName(l.token, o) if l.err || !rmailOk { - return nil, &ParseError{f, "bad MINFO Rmail", l} + return &ParseError{f, "bad MINFO Rmail", l} } rr.Rmail = rmail @@ -344,61 +310,52 @@ func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { email, emailOk := toAbsoluteName(l.token, o) if l.err || !emailOk { - return nil, &ParseError{f, "bad MINFO Email", l} + return &ParseError{f, "bad MINFO Email", l} } rr.Email = email - return rr, nil + return slurpRemainder(c, f) } -func setMF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MF) - rr.Hdr = h - +func (rr *MF) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Mf = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MF Mf", l} + return &ParseError{f, "bad MF Mf", l} } rr.Mf = name - return rr, nil + return slurpRemainder(c, f) } -func setMD(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MD) - rr.Hdr = h - +func (rr *MD) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Md = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MD Md", l} + return &ParseError{f, "bad MD Md", l} } rr.Md = name - return rr, nil + return slurpRemainder(c, f) } -func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(MX) - rr.Hdr = h - +func (rr *MX) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad MX Pref", l} + return &ParseError{f, "bad MX Pref", l} } rr.Preference = uint16(i) @@ -408,25 +365,22 @@ func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad MX Mx", l} + return &ParseError{f, "bad MX Mx", l} } rr.Mx = name - return rr, nil + return slurpRemainder(c, f) } -func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(RT) - rr.Hdr = h - +func (rr *RT) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil { - return nil, &ParseError{f, "bad RT Preference", l} + return &ParseError{f, "bad RT Preference", l} } rr.Preference = uint16(i) @@ -436,25 +390,22 @@ func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad RT Host", l} + return &ParseError{f, "bad RT Host", l} } rr.Host = name - return rr, nil + return slurpRemainder(c, f) } -func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(AFSDB) - rr.Hdr = h - +func (rr *AFSDB) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad AFSDB Subtype", l} + return &ParseError{f, "bad AFSDB Subtype", l} } rr.Subtype = uint16(i) @@ -464,40 +415,34 @@ func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad AFSDB Hostname", l} + return &ParseError{f, "bad AFSDB Hostname", l} } rr.Hostname = name - return rr, nil + return slurpRemainder(c, f) } -func setX25(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(X25) - rr.Hdr = h - +func (rr *X25) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } if l.err { - return nil, &ParseError{f, "bad X25 PSDNAddress", l} + return &ParseError{f, "bad X25 PSDNAddress", l} } rr.PSDNAddress = l.token - return rr, nil + return slurpRemainder(c, f) } -func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(KX) - rr.Hdr = h - +func (rr *KX) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad KX Pref", l} + return &ParseError{f, "bad KX Pref", l} } rr.Preference = uint16(i) @@ -507,61 +452,52 @@ func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad KX Exchanger", l} + return &ParseError{f, "bad KX Exchanger", l} } rr.Exchanger = name - return rr, nil + return slurpRemainder(c, f) } -func setCNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(CNAME) - rr.Hdr = h - +func (rr *CNAME) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Target = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad CNAME Target", l} + return &ParseError{f, "bad CNAME Target", l} } rr.Target = name - return rr, nil + return slurpRemainder(c, f) } -func setDNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(DNAME) - rr.Hdr = h - +func (rr *DNAME) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Target = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad DNAME Target", l} + return &ParseError{f, "bad DNAME Target", l} } rr.Target = name - return rr, nil + return slurpRemainder(c, f) } -func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(SOA) - rr.Hdr = h - +func (rr *SOA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.Ns = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } ns, nsOk := toAbsoluteName(l.token, o) if l.err || !nsOk { - return nil, &ParseError{f, "bad SOA Ns", l} + return &ParseError{f, "bad SOA Ns", l} } rr.Ns = ns @@ -571,7 +507,7 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { mbox, mboxOk := toAbsoluteName(l.token, o) if l.err || !mboxOk { - return nil, &ParseError{f, "bad SOA Mbox", l} + return &ParseError{f, "bad SOA Mbox", l} } rr.Mbox = mbox @@ -584,16 +520,16 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { for i := 0; i < 5; i++ { l, _ = c.Next() if l.err { - return nil, &ParseError{f, "bad SOA zone parameter", l} + return &ParseError{f, "bad SOA zone parameter", l} } if j, e := strconv.ParseUint(l.token, 10, 32); e != nil { if i == 0 { // Serial must be a number - return nil, &ParseError{f, "bad SOA zone parameter", l} + return &ParseError{f, "bad SOA zone parameter", l} } // We allow other fields to be unitful duration strings if v, ok = stringToTTL(l.token); !ok { - return nil, &ParseError{f, "bad SOA zone parameter", l} + return &ParseError{f, "bad SOA zone parameter", l} } } else { @@ -616,21 +552,18 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.Minttl = v } } - return rr, nil + return slurpRemainder(c, f) } -func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(SRV) - rr.Hdr = h - +func (rr *SRV) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad SRV Priority", l} + return &ParseError{f, "bad SRV Priority", l} } rr.Priority = uint16(i) @@ -638,7 +571,7 @@ func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad SRV Weight", l} + return &ParseError{f, "bad SRV Weight", l} } rr.Weight = uint16(i) @@ -646,7 +579,7 @@ func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad SRV Port", l} + return &ParseError{f, "bad SRV Port", l} } rr.Port = uint16(i) @@ -656,24 +589,21 @@ func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad SRV Target", l} + return &ParseError{f, "bad SRV Target", l} } rr.Target = name - return rr, nil + return slurpRemainder(c, f) } -func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NAPTR) - rr.Hdr = h - +func (rr *NAPTR) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad NAPTR Order", l} + return &ParseError{f, "bad NAPTR Order", l} } rr.Order = uint16(i) @@ -681,7 +611,7 @@ func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad NAPTR Preference", l} + return &ParseError{f, "bad NAPTR Preference", l} } rr.Preference = uint16(i) @@ -689,57 +619,57 @@ func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { c.Next() // zBlank l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Flags", l} + return &ParseError{f, "bad NAPTR Flags", l} } l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Flags = l.token l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Flags", l} + return &ParseError{f, "bad NAPTR Flags", l} } } else if l.value == zQuote { rr.Flags = "" } else { - return nil, &ParseError{f, "bad NAPTR Flags", l} + return &ParseError{f, "bad NAPTR Flags", l} } // Service c.Next() // zBlank l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Service", l} + return &ParseError{f, "bad NAPTR Service", l} } l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Service = l.token l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Service", l} + return &ParseError{f, "bad NAPTR Service", l} } } else if l.value == zQuote { rr.Service = "" } else { - return nil, &ParseError{f, "bad NAPTR Service", l} + return &ParseError{f, "bad NAPTR Service", l} } // Regexp c.Next() // zBlank l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Regexp", l} + return &ParseError{f, "bad NAPTR Regexp", l} } l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Regexp = l.token l, _ = c.Next() // _QUOTE if l.value != zQuote { - return nil, &ParseError{f, "bad NAPTR Regexp", l} + return &ParseError{f, "bad NAPTR Regexp", l} } } else if l.value == zQuote { rr.Regexp = "" } else { - return nil, &ParseError{f, "bad NAPTR Regexp", l} + return &ParseError{f, "bad NAPTR Regexp", l} } // After quote no space?? @@ -749,25 +679,22 @@ func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad NAPTR Replacement", l} + return &ParseError{f, "bad NAPTR Replacement", l} } rr.Replacement = name - return rr, nil + return slurpRemainder(c, f) } -func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(TALINK) - rr.Hdr = h - +func (rr *TALINK) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.PreviousName = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } previousName, previousNameOk := toAbsoluteName(l.token, o) if l.err || !previousNameOk { - return nil, &ParseError{f, "bad TALINK PreviousName", l} + return &ParseError{f, "bad TALINK PreviousName", l} } rr.PreviousName = previousName @@ -777,16 +704,14 @@ func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { nextName, nextNameOk := toAbsoluteName(l.token, o) if l.err || !nextNameOk { - return nil, &ParseError{f, "bad TALINK NextName", l} + return &ParseError{f, "bad TALINK NextName", l} } rr.NextName = nextName - return rr, nil + return slurpRemainder(c, f) } -func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(LOC) - rr.Hdr = h +func (rr *LOC) parse(c *zlexer, o, f string) *ParseError { // Non zero defaults for LOC record, see RFC 1876, Section 3. rr.HorizPre = 165 // 10000 rr.VertPre = 162 // 10 @@ -796,11 +721,11 @@ func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { // North l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 32) if e != nil || l.err { - return nil, &ParseError{f, "bad LOC Latitude", l} + return &ParseError{f, "bad LOC Latitude", l} } rr.Latitude = 1000 * 60 * 60 * uint32(i) @@ -812,14 +737,14 @@ func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { } i, e = strconv.ParseUint(l.token, 10, 32) if e != nil || l.err { - return nil, &ParseError{f, "bad LOC Latitude minutes", l} + return &ParseError{f, "bad LOC Latitude minutes", l} } rr.Latitude += 1000 * 60 * uint32(i) c.Next() // zBlank l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { - return nil, &ParseError{f, "bad LOC Latitude seconds", l} + return &ParseError{f, "bad LOC Latitude seconds", l} } else { rr.Latitude += uint32(1000 * i) } @@ -830,14 +755,14 @@ func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { goto East } // If still alive, flag an error - return nil, &ParseError{f, "bad LOC Latitude North/South", l} + return &ParseError{f, "bad LOC Latitude North/South", l} East: // East c.Next() // zBlank l, _ = c.Next() if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { - return nil, &ParseError{f, "bad LOC Longitude", l} + return &ParseError{f, "bad LOC Longitude", l} } else { rr.Longitude = 1000 * 60 * 60 * uint32(i) } @@ -848,14 +773,14 @@ East: goto Altitude } if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { - return nil, &ParseError{f, "bad LOC Longitude minutes", l} + return &ParseError{f, "bad LOC Longitude minutes", l} } else { rr.Longitude += 1000 * 60 * uint32(i) } c.Next() // zBlank l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { - return nil, &ParseError{f, "bad LOC Longitude seconds", l} + return &ParseError{f, "bad LOC Longitude seconds", l} } else { rr.Longitude += uint32(1000 * i) } @@ -866,19 +791,19 @@ East: goto Altitude } // If still alive, flag an error - return nil, &ParseError{f, "bad LOC Longitude East/West", l} + return &ParseError{f, "bad LOC Longitude East/West", l} Altitude: c.Next() // zBlank l, _ = c.Next() if len(l.token) == 0 || l.err { - return nil, &ParseError{f, "bad LOC Altitude", l} + return &ParseError{f, "bad LOC Altitude", l} } if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' { l.token = l.token[0 : len(l.token)-1] } if i, e := strconv.ParseFloat(l.token, 32); e != nil { - return nil, &ParseError{f, "bad LOC Altitude", l} + return &ParseError{f, "bad LOC Altitude", l} } else { rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5) } @@ -893,19 +818,19 @@ Altitude: case 0: // Size e, m, ok := stringToCm(l.token) if !ok { - return nil, &ParseError{f, "bad LOC Size", l} + return &ParseError{f, "bad LOC Size", l} } rr.Size = e&0x0f | m<<4&0xf0 case 1: // HorizPre e, m, ok := stringToCm(l.token) if !ok { - return nil, &ParseError{f, "bad LOC HorizPre", l} + return &ParseError{f, "bad LOC HorizPre", l} } rr.HorizPre = e&0x0f | m<<4&0xf0 case 2: // VertPre e, m, ok := stringToCm(l.token) if !ok { - return nil, &ParseError{f, "bad LOC VertPre", l} + return &ParseError{f, "bad LOC VertPre", l} } rr.VertPre = e&0x0f | m<<4&0xf0 } @@ -913,33 +838,30 @@ Altitude: case zBlank: // Ok default: - return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l} + return &ParseError{f, "bad LOC Size, HorizPre or VertPre", l} } l, _ = c.Next() } - return rr, nil + return nil } -func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(HIP) - rr.Hdr = h - +func (rr *HIP) parse(c *zlexer, o, f string) *ParseError { // HitLength is not represented l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l} + return &ParseError{f, "bad HIP PublicKeyAlgorithm", l} } rr.PublicKeyAlgorithm = uint8(i) c.Next() // zBlank l, _ = c.Next() // zString if len(l.token) == 0 || l.err { - return nil, &ParseError{f, "bad HIP Hit", l} + return &ParseError{f, "bad HIP Hit", l} } rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6. rr.HitLength = uint8(len(rr.Hit)) / 2 @@ -947,7 +869,7 @@ func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { c.Next() // zBlank l, _ = c.Next() // zString if len(l.token) == 0 || l.err { - return nil, &ParseError{f, "bad HIP PublicKey", l} + return &ParseError{f, "bad HIP PublicKey", l} } rr.PublicKey = l.token // This cannot contain spaces rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey))) @@ -960,34 +882,31 @@ func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { case zString: name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad HIP RendezvousServers", l} + return &ParseError{f, "bad HIP RendezvousServers", l} } xs = append(xs, name) case zBlank: // Ok default: - return nil, &ParseError{f, "bad HIP RendezvousServers", l} + return &ParseError{f, "bad HIP RendezvousServers", l} } l, _ = c.Next() } rr.RendezvousServers = xs - return rr, nil + return nil } -func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(CERT) - rr.Hdr = h - +func (rr *CERT) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } if v, ok := StringToCertType[l.token]; ok { rr.Type = v } else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil { - return nil, &ParseError{f, "bad CERT Type", l} + return &ParseError{f, "bad CERT Type", l} } else { rr.Type = uint16(i) } @@ -995,7 +914,7 @@ func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() // zString i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad CERT KeyTag", l} + return &ParseError{f, "bad CERT KeyTag", l} } rr.KeyTag = uint16(i) c.Next() // zBlank @@ -1003,42 +922,36 @@ func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { if v, ok := StringToAlgorithm[l.token]; ok { rr.Algorithm = v } else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { - return nil, &ParseError{f, "bad CERT Algorithm", l} + return &ParseError{f, "bad CERT Algorithm", l} } else { rr.Algorithm = uint8(i) } s, e1 := endingToString(c, "bad CERT Certificate", f) if e1 != nil { - return nil, e1 + return e1 } rr.Certificate = s - return rr, nil + return nil } -func setOPENPGPKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(OPENPGPKEY) - rr.Hdr = h - +func (rr *OPENPGPKEY) parse(c *zlexer, o, f string) *ParseError { s, e := endingToString(c, "bad OPENPGPKEY PublicKey", f) if e != nil { - return nil, e + return e } rr.PublicKey = s - return rr, nil + return nil } -func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(CSYNC) - rr.Hdr = h - +func (rr *CSYNC) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } j, e := strconv.ParseUint(l.token, 10, 32) if e != nil { // Serial must be a number - return nil, &ParseError{f, "bad CSYNC serial", l} + return &ParseError{f, "bad CSYNC serial", l} } rr.Serial = uint32(j) @@ -1048,7 +961,7 @@ func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { j, e = strconv.ParseUint(l.token, 10, 16) if e != nil { // Serial must be a number - return nil, &ParseError{f, "bad CSYNC flags", l} + return &ParseError{f, "bad CSYNC flags", l} } rr.Flags = uint16(j) @@ -1066,33 +979,26 @@ func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { tokenUpper := strings.ToUpper(l.token) if k, ok = StringToType[tokenUpper]; !ok { if k, ok = typeToInt(l.token); !ok { - return nil, &ParseError{f, "bad CSYNC TypeBitMap", l} + return &ParseError{f, "bad CSYNC TypeBitMap", l} } } rr.TypeBitMap = append(rr.TypeBitMap, k) default: - return nil, &ParseError{f, "bad CSYNC TypeBitMap", l} + return &ParseError{f, "bad CSYNC TypeBitMap", l} } l, _ = c.Next() } - return rr, nil + return nil } -func setSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - r, e := setRRSIG(h, c, o, f) - if r != nil { - return &SIG{*r.(*RRSIG)}, e - } - return nil, e +func (rr *SIG) parse(c *zlexer, o, f string) *ParseError { + return rr.RRSIG.parse(c, o, f) } -func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(RRSIG) - rr.Hdr = h - +func (rr *RRSIG) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } tokenUpper := strings.ToUpper(l.token) @@ -1100,11 +1006,11 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { if strings.HasPrefix(tokenUpper, "TYPE") { t, ok = typeToInt(l.token) if !ok { - return nil, &ParseError{f, "bad RRSIG Typecovered", l} + return &ParseError{f, "bad RRSIG Typecovered", l} } rr.TypeCovered = t } else { - return nil, &ParseError{f, "bad RRSIG Typecovered", l} + return &ParseError{f, "bad RRSIG Typecovered", l} } } else { rr.TypeCovered = t @@ -1114,7 +1020,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { - return nil, &ParseError{f, "bad RRSIG Algorithm", l} + return &ParseError{f, "bad RRSIG Algorithm", l} } rr.Algorithm = uint8(i) @@ -1122,7 +1028,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { - return nil, &ParseError{f, "bad RRSIG Labels", l} + return &ParseError{f, "bad RRSIG Labels", l} } rr.Labels = uint8(i) @@ -1130,7 +1036,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 32) if err != nil || l.err { - return nil, &ParseError{f, "bad RRSIG OrigTtl", l} + return &ParseError{f, "bad RRSIG OrigTtl", l} } rr.OrigTtl = uint32(i) @@ -1142,7 +1048,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { // TODO(miek): error out on > MAX_UINT32, same below rr.Expiration = uint32(i) } else { - return nil, &ParseError{f, "bad RRSIG Expiration", l} + return &ParseError{f, "bad RRSIG Expiration", l} } } else { rr.Expiration = i @@ -1154,7 +1060,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { rr.Inception = uint32(i) } else { - return nil, &ParseError{f, "bad RRSIG Inception", l} + return &ParseError{f, "bad RRSIG Inception", l} } } else { rr.Inception = i @@ -1164,7 +1070,7 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 16) if err != nil || l.err { - return nil, &ParseError{f, "bad RRSIG KeyTag", l} + return &ParseError{f, "bad RRSIG KeyTag", l} } rr.KeyTag = uint16(i) @@ -1173,32 +1079,29 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.SignerName = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad RRSIG SignerName", l} + return &ParseError{f, "bad RRSIG SignerName", l} } rr.SignerName = name s, e := endingToString(c, "bad RRSIG Signature", f) if e != nil { - return nil, e + return e } rr.Signature = s - return rr, nil + return nil } -func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NSEC) - rr.Hdr = h - +func (rr *NSEC) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() rr.NextDomain = l.token if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad NSEC NextDomain", l} + return &ParseError{f, "bad NSEC NextDomain", l} } rr.NextDomain = name @@ -1216,50 +1119,47 @@ func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { tokenUpper := strings.ToUpper(l.token) if k, ok = StringToType[tokenUpper]; !ok { if k, ok = typeToInt(l.token); !ok { - return nil, &ParseError{f, "bad NSEC TypeBitMap", l} + return &ParseError{f, "bad NSEC TypeBitMap", l} } } rr.TypeBitMap = append(rr.TypeBitMap, k) default: - return nil, &ParseError{f, "bad NSEC TypeBitMap", l} + return &ParseError{f, "bad NSEC TypeBitMap", l} } l, _ = c.Next() } - return rr, nil + return nil } -func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NSEC3) - rr.Hdr = h - +func (rr *NSEC3) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3 Hash", l} + return &ParseError{f, "bad NSEC3 Hash", l} } rr.Hash = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3 Flags", l} + return &ParseError{f, "bad NSEC3 Flags", l} } rr.Flags = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3 Iterations", l} + return &ParseError{f, "bad NSEC3 Iterations", l} } rr.Iterations = uint16(i) c.Next() l, _ = c.Next() if len(l.token) == 0 || l.err { - return nil, &ParseError{f, "bad NSEC3 Salt", l} + return &ParseError{f, "bad NSEC3 Salt", l} } if l.token != "-" { rr.SaltLength = uint8(len(l.token)) / 2 @@ -1269,7 +1169,7 @@ func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { c.Next() l, _ = c.Next() if len(l.token) == 0 || l.err { - return nil, &ParseError{f, "bad NSEC3 NextDomain", l} + return &ParseError{f, "bad NSEC3 NextDomain", l} } rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits) rr.NextDomain = l.token @@ -1288,44 +1188,41 @@ func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { tokenUpper := strings.ToUpper(l.token) if k, ok = StringToType[tokenUpper]; !ok { if k, ok = typeToInt(l.token); !ok { - return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l} + return &ParseError{f, "bad NSEC3 TypeBitMap", l} } } rr.TypeBitMap = append(rr.TypeBitMap, k) default: - return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l} + return &ParseError{f, "bad NSEC3 TypeBitMap", l} } l, _ = c.Next() } - return rr, nil + return nil } -func setNSEC3PARAM(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NSEC3PARAM) - rr.Hdr = h - +func (rr *NSEC3PARAM) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3PARAM Hash", l} + return &ParseError{f, "bad NSEC3PARAM Hash", l} } rr.Hash = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3PARAM Flags", l} + return &ParseError{f, "bad NSEC3PARAM Flags", l} } rr.Flags = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l} + return &ParseError{f, "bad NSEC3PARAM Iterations", l} } rr.Iterations = uint16(i) c.Next() @@ -1334,20 +1231,17 @@ func setNSEC3PARAM(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.SaltLength = uint8(len(l.token)) rr.Salt = l.token } - return rr, nil + return slurpRemainder(c, f) } -func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(EUI48) - rr.Hdr = h - +func (rr *EUI48) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } if len(l.token) != 17 || l.err { - return nil, &ParseError{f, "bad EUI48 Address", l} + return &ParseError{f, "bad EUI48 Address", l} } addr := make([]byte, 12) dash := 0 @@ -1356,7 +1250,7 @@ func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { addr[i+1] = l.token[i+1+dash] dash++ if l.token[i+1+dash] != '-' { - return nil, &ParseError{f, "bad EUI48 Address", l} + return &ParseError{f, "bad EUI48 Address", l} } } addr[10] = l.token[15] @@ -1364,23 +1258,20 @@ func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { i, e := strconv.ParseUint(string(addr), 16, 48) if e != nil { - return nil, &ParseError{f, "bad EUI48 Address", l} + return &ParseError{f, "bad EUI48 Address", l} } rr.Address = i - return rr, nil + return slurpRemainder(c, f) } -func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(EUI64) - rr.Hdr = h - +func (rr *EUI64) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } if len(l.token) != 23 || l.err { - return nil, &ParseError{f, "bad EUI64 Address", l} + return &ParseError{f, "bad EUI64 Address", l} } addr := make([]byte, 16) dash := 0 @@ -1389,7 +1280,7 @@ func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { addr[i+1] = l.token[i+1+dash] dash++ if l.token[i+1+dash] != '-' { - return nil, &ParseError{f, "bad EUI64 Address", l} + return &ParseError{f, "bad EUI64 Address", l} } } addr[14] = l.token[21] @@ -1397,199 +1288,172 @@ func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { i, e := strconv.ParseUint(string(addr), 16, 64) if e != nil { - return nil, &ParseError{f, "bad EUI68 Address", l} + return &ParseError{f, "bad EUI68 Address", l} } rr.Address = i - return rr, nil + return slurpRemainder(c, f) } -func setSSHFP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(SSHFP) - rr.Hdr = h - +func (rr *SSHFP) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad SSHFP Algorithm", l} + return &ParseError{f, "bad SSHFP Algorithm", l} } rr.Algorithm = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad SSHFP Type", l} + return &ParseError{f, "bad SSHFP Type", l} } rr.Type = uint8(i) c.Next() // zBlank s, e1 := endingToString(c, "bad SSHFP Fingerprint", f) if e1 != nil { - return nil, e1 + return e1 } rr.FingerPrint = s - return rr, nil + return nil } -func setDNSKEYs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError) { - rr := new(DNSKEY) - rr.Hdr = h - +func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, f, typ string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad " + typ + " Flags", l} + return &ParseError{f, "bad " + typ + " Flags", l} } rr.Flags = uint16(i) c.Next() // zBlank l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad " + typ + " Protocol", l} + return &ParseError{f, "bad " + typ + " Protocol", l} } rr.Protocol = uint8(i) c.Next() // zBlank l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad " + typ + " Algorithm", l} + return &ParseError{f, "bad " + typ + " Algorithm", l} } rr.Algorithm = uint8(i) s, e1 := endingToString(c, "bad "+typ+" PublicKey", f) if e1 != nil { - return nil, e1 + return e1 } rr.PublicKey = s - return rr, nil + return nil } -func setKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - r, e := setDNSKEYs(h, c, o, f, "KEY") - if r != nil { - return &KEY{*r.(*DNSKEY)}, e - } - return nil, e +func (rr *DNSKEY) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDNSKEY(c, o, f, "DNSKEY") } -func setDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - return setDNSKEYs(h, c, o, f, "DNSKEY") +func (rr *KEY) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDNSKEY(c, o, f, "KEY") } -func setCDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - r, e := setDNSKEYs(h, c, o, f, "CDNSKEY") - if r != nil { - return &CDNSKEY{*r.(*DNSKEY)}, e - } - return nil, e +func (rr *CDNSKEY) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDNSKEY(c, o, f, "CDNSKEY") } -func setRKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(RKEY) - rr.Hdr = h - +func (rr *RKEY) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad RKEY Flags", l} + return &ParseError{f, "bad RKEY Flags", l} } rr.Flags = uint16(i) c.Next() // zBlank l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad RKEY Protocol", l} + return &ParseError{f, "bad RKEY Protocol", l} } rr.Protocol = uint8(i) c.Next() // zBlank l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad RKEY Algorithm", l} + return &ParseError{f, "bad RKEY Algorithm", l} } rr.Algorithm = uint8(i) s, e1 := endingToString(c, "bad RKEY PublicKey", f) if e1 != nil { - return nil, e1 + return e1 } rr.PublicKey = s - return rr, nil + return nil } -func setEID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(EID) - rr.Hdr = h +func (rr *EID) parse(c *zlexer, o, f string) *ParseError { s, e := endingToString(c, "bad EID Endpoint", f) if e != nil { - return nil, e + return e } rr.Endpoint = s - return rr, nil + return nil } -func setNIMLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NIMLOC) - rr.Hdr = h +func (rr *NIMLOC) parse(c *zlexer, o, f string) *ParseError { s, e := endingToString(c, "bad NIMLOC Locator", f) if e != nil { - return nil, e + return e } rr.Locator = s - return rr, nil + return nil } -func setGPOS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(GPOS) - rr.Hdr = h - +func (rr *GPOS) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } _, e := strconv.ParseFloat(l.token, 64) if e != nil || l.err { - return nil, &ParseError{f, "bad GPOS Longitude", l} + return &ParseError{f, "bad GPOS Longitude", l} } rr.Longitude = l.token c.Next() // zBlank l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { - return nil, &ParseError{f, "bad GPOS Latitude", l} + return &ParseError{f, "bad GPOS Latitude", l} } rr.Latitude = l.token c.Next() // zBlank l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { - return nil, &ParseError{f, "bad GPOS Altitude", l} + return &ParseError{f, "bad GPOS Altitude", l} } rr.Altitude = l.token - return rr, nil + return slurpRemainder(c, f) } -func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError) { - rr := new(DS) - rr.Hdr = h - +func (rr *DS) parseDS(c *zlexer, o, f, typ string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad " + typ + " KeyTag", l} + return &ParseError{f, "bad " + typ + " KeyTag", l} } rr.KeyTag = uint16(i) c.Next() // zBlank @@ -1598,7 +1462,7 @@ func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError) { tokenUpper := strings.ToUpper(l.token) i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { - return nil, &ParseError{f, "bad " + typ + " Algorithm", l} + return &ParseError{f, "bad " + typ + " Algorithm", l} } rr.Algorithm = i } else { @@ -1608,49 +1472,38 @@ func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError) { l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad " + typ + " DigestType", l} + return &ParseError{f, "bad " + typ + " DigestType", l} } rr.DigestType = uint8(i) s, e1 := endingToString(c, "bad "+typ+" Digest", f) if e1 != nil { - return nil, e1 + return e1 } rr.Digest = s - return rr, nil + return nil } -func setDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - return setDSs(h, c, o, f, "DS") +func (rr *DS) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDS(c, o, f, "DS") } -func setDLV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - r, e := setDSs(h, c, o, f, "DLV") - if r != nil { - return &DLV{*r.(*DS)}, e - } - return nil, e +func (rr *DLV) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDS(c, o, f, "DLV") } -func setCDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - r, e := setDSs(h, c, o, f, "CDS") - if r != nil { - return &CDS{*r.(*DS)}, e - } - return nil, e +func (rr *CDS) parse(c *zlexer, o, f string) *ParseError { + return rr.parseDS(c, o, f, "CDS") } -func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(TA) - rr.Hdr = h - +func (rr *TA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad TA KeyTag", l} + return &ParseError{f, "bad TA KeyTag", l} } rr.KeyTag = uint16(i) c.Next() // zBlank @@ -1659,7 +1512,7 @@ func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { tokenUpper := strings.ToUpper(l.token) i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { - return nil, &ParseError{f, "bad TA Algorithm", l} + return &ParseError{f, "bad TA Algorithm", l} } rr.Algorithm = i } else { @@ -1669,274 +1522,238 @@ func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad TA DigestType", l} + return &ParseError{f, "bad TA DigestType", l} } rr.DigestType = uint8(i) s, err := endingToString(c, "bad TA Digest", f) if err != nil { - return nil, err + return err } rr.Digest = s - return rr, nil + return nil } -func setTLSA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(TLSA) - rr.Hdr = h - +func (rr *TLSA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad TLSA Usage", l} + return &ParseError{f, "bad TLSA Usage", l} } rr.Usage = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad TLSA Selector", l} + return &ParseError{f, "bad TLSA Selector", l} } rr.Selector = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad TLSA MatchingType", l} + return &ParseError{f, "bad TLSA MatchingType", l} } rr.MatchingType = uint8(i) // So this needs be e2 (i.e. different than e), because...??t s, e2 := endingToString(c, "bad TLSA Certificate", f) if e2 != nil { - return nil, e2 + return e2 } rr.Certificate = s - return rr, nil + return nil } -func setSMIMEA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(SMIMEA) - rr.Hdr = h - +func (rr *SMIMEA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad SMIMEA Usage", l} + return &ParseError{f, "bad SMIMEA Usage", l} } rr.Usage = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad SMIMEA Selector", l} + return &ParseError{f, "bad SMIMEA Selector", l} } rr.Selector = uint8(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { - return nil, &ParseError{f, "bad SMIMEA MatchingType", l} + return &ParseError{f, "bad SMIMEA MatchingType", l} } rr.MatchingType = uint8(i) // So this needs be e2 (i.e. different than e), because...??t s, e2 := endingToString(c, "bad SMIMEA Certificate", f) if e2 != nil { - return nil, e2 + return e2 } rr.Certificate = s - return rr, nil + return nil } -func setRFC3597(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(RFC3597) - rr.Hdr = h - +func (rr *RFC3597) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if l.token != "\\#" { - return nil, &ParseError{f, "bad RFC3597 Rdata", l} + return &ParseError{f, "bad RFC3597 Rdata", l} } c.Next() // zBlank l, _ = c.Next() rdlength, e := strconv.Atoi(l.token) if e != nil || l.err { - return nil, &ParseError{f, "bad RFC3597 Rdata ", l} + return &ParseError{f, "bad RFC3597 Rdata ", l} } s, e1 := endingToString(c, "bad RFC3597 Rdata", f) if e1 != nil { - return nil, e1 + return e1 } if rdlength*2 != len(s) { - return nil, &ParseError{f, "bad RFC3597 Rdata", l} + return &ParseError{f, "bad RFC3597 Rdata", l} } rr.Rdata = s - return rr, nil + return nil } -func setSPF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(SPF) - rr.Hdr = h - +func (rr *SPF) parse(c *zlexer, o, f string) *ParseError { s, e := endingToTxtSlice(c, "bad SPF Txt", f) if e != nil { - return nil, e + return e } rr.Txt = s - return rr, nil + return nil } -func setAVC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(AVC) - rr.Hdr = h - +func (rr *AVC) parse(c *zlexer, o, f string) *ParseError { s, e := endingToTxtSlice(c, "bad AVC Txt", f) if e != nil { - return nil, e + return e } rr.Txt = s - return rr, nil + return nil } -func setTXT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(TXT) - rr.Hdr = h - +func (rr *TXT) parse(c *zlexer, o, f string) *ParseError { // no zBlank reading here, because all this rdata is TXT s, e := endingToTxtSlice(c, "bad TXT Txt", f) if e != nil { - return nil, e + return e } rr.Txt = s - return rr, nil + return nil } // identical to setTXT -func setNINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NINFO) - rr.Hdr = h - +func (rr *NINFO) parse(c *zlexer, o, f string) *ParseError { s, e := endingToTxtSlice(c, "bad NINFO ZSData", f) if e != nil { - return nil, e + return e } rr.ZSData = s - return rr, nil + return nil } -func setURI(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(URI) - rr.Hdr = h - +func (rr *URI) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad URI Priority", l} + return &ParseError{f, "bad URI Priority", l} } rr.Priority = uint16(i) c.Next() // zBlank l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad URI Weight", l} + return &ParseError{f, "bad URI Weight", l} } rr.Weight = uint16(i) c.Next() // zBlank s, err := endingToTxtSlice(c, "bad URI Target", f) if err != nil { - return nil, err + return err } if len(s) != 1 { - return nil, &ParseError{f, "bad URI Target", l} + return &ParseError{f, "bad URI Target", l} } rr.Target = s[0] - return rr, nil + return nil } -func setDHCID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { +func (rr *DHCID) parse(c *zlexer, o, f string) *ParseError { // awesome record to parse! - rr := new(DHCID) - rr.Hdr = h - s, e := endingToString(c, "bad DHCID Digest", f) if e != nil { - return nil, e + return e } rr.Digest = s - return rr, nil + return nil } -func setNID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(NID) - rr.Hdr = h - +func (rr *NID) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad NID Preference", l} + return &ParseError{f, "bad NID Preference", l} } rr.Preference = uint16(i) c.Next() // zBlank l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { - return nil, err + return err } rr.NodeID = u - return rr, nil + return slurpRemainder(c, f) } -func setL32(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(L32) - rr.Hdr = h - +func (rr *L32) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad L32 Preference", l} + return &ParseError{f, "bad L32 Preference", l} } rr.Preference = uint16(i) c.Next() // zBlank l, _ = c.Next() // zString rr.Locator32 = net.ParseIP(l.token) if rr.Locator32 == nil || l.err { - return nil, &ParseError{f, "bad L32 Locator", l} + return &ParseError{f, "bad L32 Locator", l} } - return rr, nil + return slurpRemainder(c, f) } -func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(LP) - rr.Hdr = h - +func (rr *LP) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad LP Preference", l} + return &ParseError{f, "bad LP Preference", l} } rr.Preference = uint16(i) @@ -1945,98 +1762,83 @@ func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.Fqdn = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { - return nil, &ParseError{f, "bad LP Fqdn", l} + return &ParseError{f, "bad LP Fqdn", l} } rr.Fqdn = name - return rr, nil + return slurpRemainder(c, f) } -func setL64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(L64) - rr.Hdr = h - +func (rr *L64) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad L64 Preference", l} + return &ParseError{f, "bad L64 Preference", l} } rr.Preference = uint16(i) c.Next() // zBlank l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { - return nil, err + return err } rr.Locator64 = u - return rr, nil + return slurpRemainder(c, f) } -func setUID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(UID) - rr.Hdr = h - +func (rr *UID) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 32) if e != nil || l.err { - return nil, &ParseError{f, "bad UID Uid", l} + return &ParseError{f, "bad UID Uid", l} } rr.Uid = uint32(i) - return rr, nil + return slurpRemainder(c, f) } -func setGID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(GID) - rr.Hdr = h - +func (rr *GID) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 32) if e != nil || l.err { - return nil, &ParseError{f, "bad GID Gid", l} + return &ParseError{f, "bad GID Gid", l} } rr.Gid = uint32(i) - return rr, nil + return slurpRemainder(c, f) } -func setUINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(UINFO) - rr.Hdr = h - +func (rr *UINFO) parse(c *zlexer, o, f string) *ParseError { s, e := endingToTxtSlice(c, "bad UINFO Uinfo", f) if e != nil { - return nil, e + return e } if ln := len(s); ln == 0 { - return rr, nil + return nil } rr.Uinfo = s[0] // silently discard anything after the first character-string - return rr, nil + return nil } -func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(PX) - rr.Hdr = h - +func (rr *PX) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return slurpRemainder(c, f) } i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { - return nil, &ParseError{f, "bad PX Preference", l} + return &ParseError{f, "bad PX Preference", l} } rr.Preference = uint16(i) @@ -2045,7 +1847,7 @@ func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.Map822 = l.token map822, map822Ok := toAbsoluteName(l.token, o) if l.err || !map822Ok { - return nil, &ParseError{f, "bad PX Map822", l} + return &ParseError{f, "bad PX Map822", l} } rr.Map822 = map822 @@ -2054,56 +1856,50 @@ func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { rr.Mapx400 = l.token mapx400, mapx400Ok := toAbsoluteName(l.token, o) if l.err || !mapx400Ok { - return nil, &ParseError{f, "bad PX Mapx400", l} + return &ParseError{f, "bad PX Mapx400", l} } rr.Mapx400 = mapx400 - return rr, nil + return slurpRemainder(c, f) } -func setCAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(CAA) - rr.Hdr = h - +func (rr *CAA) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() if len(l.token) == 0 { // dynamic update rr. - return rr, nil + return nil } i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { - return nil, &ParseError{f, "bad CAA Flag", l} + return &ParseError{f, "bad CAA Flag", l} } rr.Flag = uint8(i) c.Next() // zBlank l, _ = c.Next() // zString if l.value != zString { - return nil, &ParseError{f, "bad CAA Tag", l} + return &ParseError{f, "bad CAA Tag", l} } rr.Tag = l.token c.Next() // zBlank s, e := endingToTxtSlice(c, "bad CAA Value", f) if e != nil { - return nil, e + return e } if len(s) != 1 { - return nil, &ParseError{f, "bad CAA Value", l} + return &ParseError{f, "bad CAA Value", l} } rr.Value = s[0] - return rr, nil + return nil } -func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { - rr := new(TKEY) - rr.Hdr = h - +func (rr *TKEY) parse(c *zlexer, o, f string) *ParseError { l, _ := c.Next() // Algorithm if l.value != zString { - return nil, &ParseError{f, "bad TKEY algorithm", l} + return &ParseError{f, "bad TKEY algorithm", l} } rr.Algorithm = l.token c.Next() // zBlank @@ -2112,13 +1908,13 @@ func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { - return nil, &ParseError{f, "bad TKEY key length", l} + return &ParseError{f, "bad TKEY key length", l} } rr.KeySize = uint16(i) c.Next() // zBlank l, _ = c.Next() if l.value != zString { - return nil, &ParseError{f, "bad TKEY key", l} + return &ParseError{f, "bad TKEY key", l} } rr.Key = l.token c.Next() // zBlank @@ -2127,84 +1923,15 @@ func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) { l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { - return nil, &ParseError{f, "bad TKEY otherdata length", l} + return &ParseError{f, "bad TKEY otherdata length", l} } rr.OtherLen = uint16(i) c.Next() // zBlank l, _ = c.Next() if l.value != zString { - return nil, &ParseError{f, "bad TKEY otherday", l} + return &ParseError{f, "bad TKEY otherday", l} } rr.OtherData = l.token - return rr, nil -} - -var typeToparserFunc = map[uint16]parserFunc{ - TypeAAAA: {setAAAA, false}, - TypeAFSDB: {setAFSDB, false}, - TypeA: {setA, false}, - TypeCAA: {setCAA, true}, - TypeCDS: {setCDS, true}, - TypeCDNSKEY: {setCDNSKEY, true}, - TypeCERT: {setCERT, true}, - TypeCNAME: {setCNAME, false}, - TypeCSYNC: {setCSYNC, true}, - TypeDHCID: {setDHCID, true}, - TypeDLV: {setDLV, true}, - TypeDNAME: {setDNAME, false}, - TypeKEY: {setKEY, true}, - TypeDNSKEY: {setDNSKEY, true}, - TypeDS: {setDS, true}, - TypeEID: {setEID, true}, - TypeEUI48: {setEUI48, false}, - TypeEUI64: {setEUI64, false}, - TypeGID: {setGID, false}, - TypeGPOS: {setGPOS, false}, - TypeHINFO: {setHINFO, true}, - TypeHIP: {setHIP, true}, - TypeKX: {setKX, false}, - TypeL32: {setL32, false}, - TypeL64: {setL64, false}, - TypeLOC: {setLOC, true}, - TypeLP: {setLP, false}, - TypeMB: {setMB, false}, - TypeMD: {setMD, false}, - TypeMF: {setMF, false}, - TypeMG: {setMG, false}, - TypeMINFO: {setMINFO, false}, - TypeMR: {setMR, false}, - TypeMX: {setMX, false}, - TypeNAPTR: {setNAPTR, false}, - TypeNID: {setNID, false}, - TypeNIMLOC: {setNIMLOC, true}, - TypeNINFO: {setNINFO, true}, - TypeNSAPPTR: {setNSAPPTR, false}, - TypeNSEC3PARAM: {setNSEC3PARAM, false}, - TypeNSEC3: {setNSEC3, true}, - TypeNSEC: {setNSEC, true}, - TypeNS: {setNS, false}, - TypeOPENPGPKEY: {setOPENPGPKEY, true}, - TypePTR: {setPTR, false}, - TypePX: {setPX, false}, - TypeSIG: {setSIG, true}, - TypeRKEY: {setRKEY, true}, - TypeRP: {setRP, false}, - TypeRRSIG: {setRRSIG, true}, - TypeRT: {setRT, false}, - TypeSMIMEA: {setSMIMEA, true}, - TypeSOA: {setSOA, false}, - TypeSPF: {setSPF, true}, - TypeAVC: {setAVC, true}, - TypeSRV: {setSRV, false}, - TypeSSHFP: {setSSHFP, true}, - TypeTALINK: {setTALINK, false}, - TypeTA: {setTA, true}, - TypeTLSA: {setTLSA, true}, - TypeTXT: {setTXT, true}, - TypeUID: {setUID, false}, - TypeUINFO: {setUINFO, true}, - TypeURI: {setURI, true}, - TypeX25: {setX25, false}, - TypeTKEY: {setTKEY, true}, + return nil } diff --git a/tsig.go b/tsig.go index e2e94bd5..afa462fa 100644 --- a/tsig.go +++ b/tsig.go @@ -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 { diff --git a/types.go b/types.go index c040c640..efa34244 100644 --- a/types.go +++ b/types.go @@ -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