diff --git a/TODO.markdown b/TODO.markdown index 3e630321..a8ae21f1 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -5,6 +5,7 @@ things that need to be fixed. * Parsing * $INCLUDE + * TXT record isn't parsed correctly * Speed, we can always go faster. A simple reflect server now hits 30K qps * Add handy zone data structure (r/b tree)? * Use the Exchange structure to deal with errors when resolving, esp. Timeout @@ -13,6 +14,7 @@ things that need to be fixed. * SaltLength in NSEC3 is ugly to set, should be automatically done. There are prolly a few more settings just like that -- need to look at them. -edns NSID is another + ## Examples to add * Nameserver, with a small zone, 1 KSK and online signing; diff --git a/kscan.go b/kscan.go index bf1010c5..a48f2bfe 100644 --- a/kscan.go +++ b/kscan.go @@ -10,8 +10,8 @@ import ( ) // ReadPrivateKey reads a private key from the io.Reader q. -func ReadPrivateKey(q io.Reader) (PrivateKey, error) { - m, e := parseKey(q) +func ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) { + m, e := parseKey(q, file) if m == nil { return nil, e } @@ -91,7 +91,7 @@ func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) { // parseKey reads a private key from r. It returns a map[string]string, // with the key-value pairs, or an error when the file is not correct. -func parseKey(r io.Reader) (map[string]string, error) { +func parseKey(r io.Reader, file string) (map[string]string, error) { var s scanner.Scanner m := make(map[string]string) c := make(chan lex) @@ -108,7 +108,7 @@ func parseKey(r io.Reader) (map[string]string, error) { k = l.token case _VALUE: if k == "" { - return nil, &ParseError{"No key seen", l} + return nil, &ParseError{file, "No key seen", l} } //println("Setting", strings.ToLower(k), "to", l.token, "b") m[strings.ToLower(k)] = l.token diff --git a/zscan.go b/zscan.go index 96855649..708f5401 100644 --- a/zscan.go +++ b/zscan.go @@ -3,6 +3,7 @@ package dns import ( "fmt" "io" + "os" "strconv" "strings" "text/scanner" @@ -48,21 +49,26 @@ const ( _EXPECT_DIRTTL // Directive $TTL _EXPECT_DIRORIGIN_BL // Space after directive $ORIGIN _EXPECT_DIRORIGIN // Directive $ORIGIN + _EXPECT_DIRINCLUDE_BL // Space after directive $INCLUDE + _EXPECT_DIRINCLUDE // Directive $INCLUDE ) // ParseError contains the parse error and the location in the io.Reader // where the error occured. type ParseError struct { - err string - lex lex + file string + err string + lex lex } -func (e *ParseError) Error() string { - va := strconv.Itoa(e.lex.value) - s := e.err + ": `" + e.lex.token + "' (value: " + va + ") at line: " + - strconv.Itoa(e.lex.line) + " and column: " + - strconv.Itoa(e.lex.column) - return s +func (e *ParseError) Error() (s string) { + // va := strconv.Itoa(e.lex.value) + if e.file != "" { + s = e.file + ": " + } + s += e.err + ": `" + e.lex.token + "' at line: " + + strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column) + return } type lex struct { @@ -86,9 +92,9 @@ type Token struct { func NewRR(s string) (RR, error) { t := make(chan Token) if s[len(s)-1] != '\n' { // We need a closing newline - t = ParseZone(strings.NewReader(s + "\n")) + t = ParseZone(strings.NewReader(s+"\n"), "") } else { - t = ParseZone(strings.NewReader(s)) + t = ParseZone(strings.NewReader(s), "") } r := <-t if r.Error != nil { @@ -99,14 +105,18 @@ func NewRR(s string) (RR, error) { // ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error // on the returned channel. The channel t is closed by ParseZone when the end of r is reached. -func ParseZone(r io.Reader) chan Token { +func ParseZone(r io.Reader, file string) chan Token { t := make(chan Token) - go parseZone(r, t) + go parseZone(r, file, t, 0) return t } -func parseZone(r io.Reader, t chan Token) { - defer close(t) +func parseZone(r io.Reader, f string, t chan Token, include int) { + defer func() { + if include == 0 { + close(t) + } + }() var s scanner.Scanner c := make(chan lex) s.Init(r) @@ -133,7 +143,7 @@ func parseZone(r io.Reader, t chan Token) { } // Lexer spotted an error already if l.err != "" { - t <- Token{Error: &ParseError{l.err, l}} + t <- Token{Error: &ParseError{f, l.err, l}} return } @@ -148,7 +158,7 @@ func parseZone(r io.Reader, t chan Token) { case _OWNER: h.Name = l.token if _, ok := IsDomainName(l.token); !ok { - t <- Token{Error: &ParseError{"bad owner name", l}} + t <- Token{Error: &ParseError{f, "bad owner name", l}} return } if !IsFqdn(h.Name) { @@ -159,22 +169,46 @@ func parseZone(r io.Reader, t chan Token) { st = _EXPECT_DIRTTL_BL case _DIRORIGIN: st = _EXPECT_DIRORIGIN_BL + case _DIRINCLUDE: + st = _EXPECT_DIRINCLUDE_BL default: - t <- Token{Error: &ParseError{"Error at the start", l}} + t <- Token{Error: &ParseError{f, "Error at the start", l}} return } + case _EXPECT_DIRINCLUDE_BL: + if l.value != _BLANK { + t <- Token{Error: &ParseError{f, "No blank after $INCLUDE-directive", l}} + return + } + st = _EXPECT_DIRINCLUDE + case _EXPECT_DIRINCLUDE: + if l.value != _STRING { + t <- Token{Error: &ParseError{f, "Expecting $INCLUDE value, not this...", l}} + return + } + // Start with the new file + r1, e1 := os.Open(l.token) + if e1 != nil { + t <- Token{Error: &ParseError{f, "Failed to open `" + l.token + "'", l}} + return + } + if include+1 > 8 { + t <- Token{Error: &ParseError{f, "Too deeply nested $INCLUDE", l}} + } + parseZone(r1, l.token, t, include+1) + st = _EXPECT_OWNER_DIR case _EXPECT_DIRTTL_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank after $-directive", l}} + t <- Token{Error: &ParseError{f, "No blank after $TTL-directive", l}} return } st = _EXPECT_DIRTTL case _EXPECT_DIRTTL: if l.value != _STRING { - t <- Token{Error: &ParseError{"Expecting $TTL value, not this...", l}} + t <- Token{Error: &ParseError{f, "Expecting $TTL value, not this...", l}} return } - if ttl, ok := stringToTtl(l, t); !ok { + if ttl, ok := stringToTtl(l, f, t); !ok { return } else { defttl = ttl @@ -182,13 +216,13 @@ func parseZone(r io.Reader, t chan Token) { st = _EXPECT_OWNER_DIR case _EXPECT_DIRORIGIN_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank after $-directive", l}} + t <- Token{Error: &ParseError{f, "No blank after $ORIGIN-directive", l}} return } st = _EXPECT_DIRORIGIN case _EXPECT_DIRORIGIN: if l.value != _STRING { - t <- Token{Error: &ParseError{"Expecting $ORIGIN value, not this...", l}} + t <- Token{Error: &ParseError{f, "Expecting $ORIGIN value, not this...", l}} return } if !IsFqdn(l.token) { @@ -198,7 +232,7 @@ func parseZone(r io.Reader, t chan Token) { } case _EXPECT_OWNER_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank after owner", l}} + t <- Token{Error: &ParseError{f, "No blank after owner", l}} return } st = _EXPECT_ANY @@ -210,30 +244,30 @@ func parseZone(r io.Reader, t chan Token) { case _CLASS: h.Class, ok = Str_class[strings.ToUpper(l.token)] if !ok { - t <- Token{Error: &ParseError{"Unknown class", l}} + t <- Token{Error: &ParseError{f, "Unknown class", l}} return } st = _EXPECT_ANY_NOCLASS_BL case _STRING: // TTL is this case - if ttl, ok := stringToTtl(l, t); !ok { + if ttl, ok := stringToTtl(l, f, t); !ok { return } else { h.Ttl = ttl } st = _EXPECT_ANY_NOTTL_BL default: - t <- Token{Error: &ParseError{"Expecting RR type, TTL or class, not this...", l}} + t <- Token{Error: &ParseError{f, "Expecting RR type, TTL or class, not this...", l}} return } case _EXPECT_ANY_NOCLASS_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank before NOCLASS", l}} + t <- Token{Error: &ParseError{f, "No blank before NOCLASS", l}} return } st = _EXPECT_ANY_NOCLASS case _EXPECT_ANY_NOTTL_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank before NOTTL", l}} + t <- Token{Error: &ParseError{f, "No blank before NOTTL", l}} return } st = _EXPECT_ANY_NOTTL @@ -242,7 +276,7 @@ func parseZone(r io.Reader, t chan Token) { case _CLASS: h.Class, ok = Str_class[strings.ToUpper(l.token)] if !ok { - t <- Token{Error: &ParseError{"Unknown class", l}} + t <- Token{Error: &ParseError{f, "Unknown class", l}} return } st = _EXPECT_RRTYPE_BL @@ -253,7 +287,7 @@ func parseZone(r io.Reader, t chan Token) { case _EXPECT_ANY_NOCLASS: switch l.value { case _STRING: // TTL - if ttl, ok := stringToTtl(l, t); !ok { + if ttl, ok := stringToTtl(l, f, t); !ok { return } else { h.Ttl = ttl @@ -263,25 +297,25 @@ func parseZone(r io.Reader, t chan Token) { h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] st = _EXPECT_RDATA default: - t <- Token{Error: &ParseError{"Expecting RR type or TTL, not this...", l}} + t <- Token{Error: &ParseError{f, "Expecting RR type or TTL, not this...", l}} return } case _EXPECT_RRTYPE_BL: if l.value != _BLANK { - t <- Token{Error: &ParseError{"No blank after", l}} + t <- Token{Error: &ParseError{f, "No blank after", l}} return } st = _EXPECT_RRTYPE case _EXPECT_RRTYPE: if l.value != _RRTYPE { - t <- Token{Error: &ParseError{"Unknown RR type", l}} + t <- Token{Error: &ParseError{f, "Unknown RR type", l}} return } h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] st = _EXPECT_RDATA case _EXPECT_RDATA: // I could save my token here...? l - r, e := setRR(h, c, origin) + r, e := setRR(h, c, origin, f) if e != nil { // If e.lex is nil than we have encounter a unknown RR type // in that case we substitute our current lex token @@ -347,12 +381,14 @@ func zlexer(s scanner.Scanner, c chan lex) { l.value = _OWNER l.token = str // escape $... start with a \ not a $, so this will work - if str == "$TTL" { + switch str { + case "$TTL": l.value = _DIRTTL - } - if str == "$ORIGIN" { + case "$ORIGIN": l.value = _DIRORIGIN - } + case "$INCLUDE": + l.value = _DIRINCLUDE + } c <- l } else { l.value = _STRING @@ -502,9 +538,9 @@ func zlexer(s scanner.Scanner, c chan lex) { } } -func stringToTtl(l lex, t chan Token) (uint32, bool) { +func stringToTtl(l lex, f string, t chan Token) (uint32, bool) { if ttl, ok := strconv.Atoi(l.token); ok != nil { - t <- Token{Error: &ParseError{"Not a TTL", l}} + t <- Token{Error: &ParseError{f, "Not a TTL", l}} return 0, false } else { return uint32(ttl), true diff --git a/zscan_rr.go b/zscan_rr.go index 14e2f4fe..d84d4aaa 100644 --- a/zscan_rr.go +++ b/zscan_rr.go @@ -13,62 +13,62 @@ import ( // or immediately a _NEWLINE. If this is not the case we flag // an *ParseError: garbage after rdata. -func setRR(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { var r RR e := new(ParseError) switch h.Rrtype { case TypeA: - r, e = setA(h, c) + r, e = setA(h, c, f) goto Slurp case TypeAAAA: - r, e = setAAAA(h, c) + r, e = setAAAA(h, c, f) goto Slurp case TypeNS: - r, e = setNS(h, c, o) + r, e = setNS(h, c, o, f) goto Slurp case TypeMX: - r, e = setMX(h, c, o) + r, e = setMX(h, c, o, f) goto Slurp case TypeCNAME: - r, e = setCNAME(h, c, o) + r, e = setCNAME(h, c, o, f) goto Slurp case TypeSOA: - r, e = setSOA(h, c, o) + r, e = setSOA(h, c, o, f) goto Slurp case TypeSSHFP: - r, e = setSSHFP(h, c) + r, e = setSSHFP(h, c, f) goto Slurp case TypeDNSKEY: // These types have a variable ending either chunks of txt or chunks/base64 or hex. // They need to search for the end of the RR themselves, hence they look for the ending // newline. Thus there is no need to slurp the remainder, because there is none. - return setDNSKEY(h, c) + return setDNSKEY(h, c, f) case TypeRRSIG: - return setRRSIG(h, c, o) + return setRRSIG(h, c, o, f) case TypeNSEC: - return setNSEC(h, c, o) + return setNSEC(h, c, o, f) case TypeNSEC3: - return setNSEC3(h, c, o) + return setNSEC3(h, c, o, f) case TypeDS: - return setDS(h, c) + return setDS(h, c, f) case TypeTXT: - return setTXT(h, c) + return setTXT(h, c, f) default: // Don't the have the token the holds the RRtype, but we substitute that in the // calling function when lex is empty. - return nil, &ParseError{"Unknown RR type", lex{}} + return nil, &ParseError{f, "Unknown RR type", lex{}} } Slurp: if e != nil { return nil, e } - if se := slurpRemainder(c); se != nil { + if se := slurpRemainder(c, f); se != nil { return nil, se } return r, e } -func slurpRemainder(c chan lex) *ParseError { +func slurpRemainder(c chan lex, f string) *ParseError { l := <-c if _DEBUG { fmt.Printf("%v\n", l) @@ -80,7 +80,7 @@ func slurpRemainder(c chan lex) *ParseError { fmt.Printf("%v\n", l) } if l.value != _NEWLINE && l.value != _EOF { - return &ParseError{"garbage after rdata", l} + return &ParseError{f, "garbage after rdata", l} } // Ok case _NEWLINE: @@ -88,43 +88,43 @@ func slurpRemainder(c chan lex) *ParseError { case _EOF: // Ok default: - return &ParseError{"garbage after directly rdata", l} + return &ParseError{f, "garbage after directly rdata", l} } return nil } -func setA(h RR_Header, c chan lex) (RR, *ParseError) { +func setA(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_A) rr.Hdr = h l := <-c rr.A = net.ParseIP(l.token) if rr.A == nil { - return nil, &ParseError{"bad A", l} + return nil, &ParseError{f, "bad A", l} } return rr, nil } -func setAAAA(h RR_Header, c chan lex) (RR, *ParseError) { +func setAAAA(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_AAAA) rr.Hdr = h l := <-c rr.AAAA = net.ParseIP(l.token) if rr.AAAA == nil { - return nil, &ParseError{"bad AAAA", l} + return nil, &ParseError{f, "bad AAAA", l} } return rr, nil } -func setNS(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_NS) rr.Hdr = h l := <-c rr.Ns = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad NS Ns", l} + return nil, &ParseError{f, "bad NS Ns", l} } if !IsFqdn(rr.Ns) { rr.Ns += o @@ -132,13 +132,13 @@ func setNS(h RR_Header, c chan lex, o string) (RR, *ParseError) { return rr, nil } -func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_MX) rr.Hdr = h l := <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad MX Pref", l} + return nil, &ParseError{f, "bad MX Pref", l} } else { rr.Pref = uint16(i) } @@ -146,7 +146,7 @@ func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) { l = <-c // _STRING rr.Mx = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad MX Mx", l} + return nil, &ParseError{f, "bad MX Mx", l} } if !IsFqdn(rr.Mx) { rr.Mx += o @@ -154,14 +154,14 @@ func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) { return rr, nil } -func setCNAME(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_CNAME) rr.Hdr = h l := <-c rr.Cname = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad CNAME", l} + return nil, &ParseError{f, "bad CNAME", l} } if !IsFqdn(rr.Cname) { rr.Cname += o @@ -169,7 +169,7 @@ func setCNAME(h RR_Header, c chan lex, o string) (RR, *ParseError) { return rr, nil } -func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_SOA) rr.Hdr = h @@ -177,7 +177,7 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) { rr.Ns = l.token <-c // _BLANK if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad SOA mname", l} + return nil, &ParseError{f, "bad SOA mname", l} } if !IsFqdn(rr.Ns) { rr.Ns += o @@ -186,7 +186,7 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) { l = <-c rr.Mbox = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad SOA rname", l} + return nil, &ParseError{f, "bad SOA rname", l} } if !IsFqdn(rr.Mbox) { rr.Mbox += o @@ -198,7 +198,7 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) { for i := 0; i < 5; i++ { l = <-c if j, e = strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad SOA zone parameter", l} + return nil, &ParseError{f, "bad SOA zone parameter", l} } switch i { case 0: @@ -220,54 +220,54 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) { return rr, nil } -func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_RRSIG) rr.Hdr = h l := <-c if t, ok := Str_rr[strings.ToUpper(l.token)]; !ok { - return nil, &ParseError{"bad RRSIG", l} + return nil, &ParseError{f, "bad RRSIG", l} } else { rr.TypeCovered = t } <-c // _BLANK l = <-c if i, err := strconv.Atoi(l.token); err != nil { - return nil, &ParseError{"bad RRSIG", l} + return nil, &ParseError{f, "bad RRSIG", l} } else { rr.Algorithm = uint8(i) } <-c // _BLANK l = <-c if i, err := strconv.Atoi(l.token); err != nil { - return nil, &ParseError{"bad RRSIG", l} + return nil, &ParseError{f, "bad RRSIG", l} } else { rr.Labels = uint8(i) } <-c // _BLANK l = <-c if i, err := strconv.Atoi(l.token); err != nil { - return nil, &ParseError{"bad RRSIG", l} + return nil, &ParseError{f, "bad RRSIG", l} } else { rr.OrigTtl = uint32(i) } <-c // _BLANK l = <-c if i, err := dateToTime(l.token); err != nil { - return nil, &ParseError{"bad RRSIG expiration", l} + return nil, &ParseError{f, "bad RRSIG expiration", l} } else { rr.Expiration = i } <-c // _BLANK l = <-c if i, err := dateToTime(l.token); err != nil { - return nil, &ParseError{"bad RRSIG inception", l} + return nil, &ParseError{f, "bad RRSIG inception", l} } else { rr.Inception = i } <-c // _BLANK l = <-c if i, err := strconv.Atoi(l.token); err != nil { - return nil, &ParseError{"bad RRSIG keytag", l} + return nil, &ParseError{f, "bad RRSIG keytag", l} } else { rr.KeyTag = uint16(i) } @@ -275,7 +275,7 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) { l = <-c rr.SignerName = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad RRSIG signername", l} + return nil, &ParseError{f, "bad RRSIG signername", l} } if !IsFqdn(rr.SignerName) { rr.SignerName += o @@ -290,7 +290,7 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) { case _BLANK: // Ok default: - return nil, &ParseError{"bad RRSIG signature", l} + return nil, &ParseError{f, "bad RRSIG signature", l} } l = <-c } @@ -298,14 +298,14 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) { return rr, nil } -func setNSEC(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_NSEC) rr.Hdr = h l := <-c rr.NextDomain = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad NSEC nextdomain", l} + return nil, &ParseError{f, "bad NSEC nextdomain", l} } if !IsFqdn(rr.NextDomain) { rr.NextDomain += o @@ -319,39 +319,39 @@ func setNSEC(h RR_Header, c chan lex, o string) (RR, *ParseError) { // Ok case _STRING: if k, ok := Str_rr[strings.ToUpper(l.token)]; !ok { - return nil, &ParseError{"bad NSEC non RR in type bitmap", l} + return nil, &ParseError{f, "bad NSEC non RR in type bitmap", l} } else { rr.TypeBitMap = append(rr.TypeBitMap, k) } default: - return nil, &ParseError{"bad NSEC garbage in type bitmap", l} + return nil, &ParseError{f, "bad NSEC garbage in type bitmap", l} } l = <-c } return rr, nil } -func setNSEC3(h RR_Header, c chan lex, o string) (RR, *ParseError) { +func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr := new(RR_NSEC3) rr.Hdr = h l := <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad NSEC3", l} + return nil, &ParseError{f, "bad NSEC3", l} } else { rr.Hash = uint8(i) } <-c // _BLANK l = <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad NSEC3", l} + return nil, &ParseError{f, "bad NSEC3", l} } else { rr.Flags = uint8(i) } <-c // _BLANK l = <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad NSEC3", l} + return nil, &ParseError{f, "bad NSEC3", l} } else { rr.Iterations = uint16(i) } @@ -365,7 +365,7 @@ func setNSEC3(h RR_Header, c chan lex, o string) (RR, *ParseError) { rr.HashLength = uint8(len(l.token)) rr.NextDomain = l.token if _, ok := IsDomainName(l.token); !ok { - return nil, &ParseError{"bad NSEC nextdomain", l} + return nil, &ParseError{f, "bad NSEC nextdomain", l} } if !IsFqdn(rr.NextDomain) { rr.NextDomain += o @@ -379,12 +379,12 @@ func setNSEC3(h RR_Header, c chan lex, o string) (RR, *ParseError) { // Ok case _STRING: if k, ok := Str_rr[strings.ToUpper(l.token)]; !ok { - return nil, &ParseError{"bad NSEC3", l} + return nil, &ParseError{f, "bad NSEC3", l} } else { rr.TypeBitMap = append(rr.TypeBitMap, k) } default: - return nil, &ParseError{"bad NSEC3", l} + return nil, &ParseError{f, "bad NSEC3", l} } l = <-c } @@ -417,20 +417,20 @@ func setNSEC3PARAM(h RR_Header, c chan lex) (RR, *ParseError) { } */ -func setSSHFP(h RR_Header, c chan lex) (RR, *ParseError) { +func setSSHFP(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_SSHFP) rr.Hdr = h l := <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad SSHFP", l} + return nil, &ParseError{f, "bad SSHFP", l} } else { rr.Algorithm = uint8(i) } <-c // _BLANK l = <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad SSHFP", l} + return nil, &ParseError{f, "bad SSHFP", l} } else { rr.Type = uint8(i) } @@ -440,27 +440,27 @@ func setSSHFP(h RR_Header, c chan lex) (RR, *ParseError) { return rr, nil } -func setDNSKEY(h RR_Header, c chan lex) (RR, *ParseError) { +func setDNSKEY(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_DNSKEY) rr.Hdr = h l := <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DNSKEY", l} + return nil, &ParseError{f, "bad DNSKEY", l} } else { rr.Flags = uint16(i) } <-c // _BLANK l = <-c // _STRING if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DNSKEY", l} + return nil, &ParseError{f, "bad DNSKEY", l} } else { rr.Protocol = uint8(i) } <-c // _BLANK l = <-c // _STRING if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DNSKEY", l} + return nil, &ParseError{f, "bad DNSKEY", l} } else { rr.Algorithm = uint8(i) } @@ -473,7 +473,7 @@ func setDNSKEY(h RR_Header, c chan lex) (RR, *ParseError) { case _BLANK: // Ok default: - return nil, &ParseError{"bad DNSKEY", l} + return nil, &ParseError{f, "bad DNSKEY", l} } l = <-c } @@ -482,26 +482,26 @@ func setDNSKEY(h RR_Header, c chan lex) (RR, *ParseError) { } // DLV and TA are the same -func setDS(h RR_Header, c chan lex) (RR, *ParseError) { +func setDS(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_DS) rr.Hdr = h l := <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DS", l} + return nil, &ParseError{f, "bad DS", l} } else { rr.KeyTag = uint16(i) } <-c // _BLANK l = <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DS", l} + return nil, &ParseError{f, "bad DS", l} } else { rr.Algorithm = uint8(i) } <-c // _BLANK l = <-c if i, e := strconv.Atoi(l.token); e != nil { - return nil, &ParseError{"bad DS", l} + return nil, &ParseError{f, "bad DS", l} } else { rr.DigestType = uint8(i) } @@ -515,7 +515,7 @@ func setDS(h RR_Header, c chan lex) (RR, *ParseError) { case _BLANK: // Ok default: - return nil, &ParseError{"bad DS", l} + return nil, &ParseError{f, "bad DS", l} } l = <-c } @@ -523,7 +523,7 @@ func setDS(h RR_Header, c chan lex) (RR, *ParseError) { return rr, nil } -func setTXT(h RR_Header, c chan lex) (RR, *ParseError) { +func setTXT(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr := new(RR_TXT) rr.Hdr = h @@ -537,7 +537,7 @@ func setTXT(h RR_Header, c chan lex) (RR, *ParseError) { case _BLANK: s += l.token default: - return nil, &ParseError{"bad TXT", l} + return nil, &ParseError{f, "bad TXT", l} } l = <-c }