support $INCLUDE

ParseZone now needs a filename to report the
correct file
This commit is contained in:
Miek Gieben 2012-01-21 23:36:54 +01:00
parent 37f396a05b
commit add6f10462
4 changed files with 152 additions and 114 deletions

View File

@ -5,6 +5,7 @@ things that need to be fixed.
* Parsing * Parsing
* $INCLUDE * $INCLUDE
* TXT record isn't parsed correctly
* Speed, we can always go faster. A simple reflect server now hits 30K qps * Speed, we can always go faster. A simple reflect server now hits 30K qps
* Add handy zone data structure (r/b tree)? * Add handy zone data structure (r/b tree)?
* Use the Exchange structure to deal with errors when resolving, esp. Timeout * 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 * 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. settings just like that -- need to look at them.
-edns NSID is another -edns NSID is another
## Examples to add ## Examples to add
* Nameserver, with a small zone, 1 KSK and online signing; * Nameserver, with a small zone, 1 KSK and online signing;

View File

@ -10,8 +10,8 @@ import (
) )
// ReadPrivateKey reads a private key from the io.Reader q. // ReadPrivateKey reads a private key from the io.Reader q.
func ReadPrivateKey(q io.Reader) (PrivateKey, error) { func ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
m, e := parseKey(q) m, e := parseKey(q, file)
if m == nil { if m == nil {
return nil, e 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, // 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. // 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 var s scanner.Scanner
m := make(map[string]string) m := make(map[string]string)
c := make(chan lex) c := make(chan lex)
@ -108,7 +108,7 @@ func parseKey(r io.Reader) (map[string]string, error) {
k = l.token k = l.token
case _VALUE: case _VALUE:
if k == "" { 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") //println("Setting", strings.ToLower(k), "to", l.token, "b")
m[strings.ToLower(k)] = l.token m[strings.ToLower(k)] = l.token

116
zscan.go
View File

@ -3,6 +3,7 @@ package dns
import ( import (
"fmt" "fmt"
"io" "io"
"os"
"strconv" "strconv"
"strings" "strings"
"text/scanner" "text/scanner"
@ -48,21 +49,26 @@ const (
_EXPECT_DIRTTL // Directive $TTL _EXPECT_DIRTTL // Directive $TTL
_EXPECT_DIRORIGIN_BL // Space after directive $ORIGIN _EXPECT_DIRORIGIN_BL // Space after directive $ORIGIN
_EXPECT_DIRORIGIN // 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 // ParseError contains the parse error and the location in the io.Reader
// where the error occured. // where the error occured.
type ParseError struct { type ParseError struct {
err string file string
lex lex err string
lex lex
} }
func (e *ParseError) Error() string { func (e *ParseError) Error() (s string) {
va := strconv.Itoa(e.lex.value) // va := strconv.Itoa(e.lex.value)
s := e.err + ": `" + e.lex.token + "' (value: " + va + ") at line: " + if e.file != "" {
strconv.Itoa(e.lex.line) + " and column: " + s = e.file + ": "
strconv.Itoa(e.lex.column) }
return s s += e.err + ": `" + e.lex.token + "' at line: " +
strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
return
} }
type lex struct { type lex struct {
@ -86,9 +92,9 @@ type Token struct {
func NewRR(s string) (RR, error) { func NewRR(s string) (RR, error) {
t := make(chan Token) t := make(chan Token)
if s[len(s)-1] != '\n' { // We need a closing newline if s[len(s)-1] != '\n' { // We need a closing newline
t = ParseZone(strings.NewReader(s + "\n")) t = ParseZone(strings.NewReader(s+"\n"), "")
} else { } else {
t = ParseZone(strings.NewReader(s)) t = ParseZone(strings.NewReader(s), "")
} }
r := <-t r := <-t
if r.Error != nil { 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 // 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. // 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) t := make(chan Token)
go parseZone(r, t) go parseZone(r, file, t, 0)
return t return t
} }
func parseZone(r io.Reader, t chan Token) { func parseZone(r io.Reader, f string, t chan Token, include int) {
defer close(t) defer func() {
if include == 0 {
close(t)
}
}()
var s scanner.Scanner var s scanner.Scanner
c := make(chan lex) c := make(chan lex)
s.Init(r) s.Init(r)
@ -133,7 +143,7 @@ func parseZone(r io.Reader, t chan Token) {
} }
// Lexer spotted an error already // Lexer spotted an error already
if l.err != "" { if l.err != "" {
t <- Token{Error: &ParseError{l.err, l}} t <- Token{Error: &ParseError{f, l.err, l}}
return return
} }
@ -148,7 +158,7 @@ func parseZone(r io.Reader, t chan Token) {
case _OWNER: case _OWNER:
h.Name = l.token h.Name = l.token
if _, ok := IsDomainName(l.token); !ok { if _, ok := IsDomainName(l.token); !ok {
t <- Token{Error: &ParseError{"bad owner name", l}} t <- Token{Error: &ParseError{f, "bad owner name", l}}
return return
} }
if !IsFqdn(h.Name) { if !IsFqdn(h.Name) {
@ -159,22 +169,46 @@ func parseZone(r io.Reader, t chan Token) {
st = _EXPECT_DIRTTL_BL st = _EXPECT_DIRTTL_BL
case _DIRORIGIN: case _DIRORIGIN:
st = _EXPECT_DIRORIGIN_BL st = _EXPECT_DIRORIGIN_BL
case _DIRINCLUDE:
st = _EXPECT_DIRINCLUDE_BL
default: default:
t <- Token{Error: &ParseError{"Error at the start", l}} t <- Token{Error: &ParseError{f, "Error at the start", l}}
return 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: case _EXPECT_DIRTTL_BL:
if l.value != _BLANK { 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 return
} }
st = _EXPECT_DIRTTL st = _EXPECT_DIRTTL
case _EXPECT_DIRTTL: case _EXPECT_DIRTTL:
if l.value != _STRING { 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 return
} }
if ttl, ok := stringToTtl(l, t); !ok { if ttl, ok := stringToTtl(l, f, t); !ok {
return return
} else { } else {
defttl = ttl defttl = ttl
@ -182,13 +216,13 @@ func parseZone(r io.Reader, t chan Token) {
st = _EXPECT_OWNER_DIR st = _EXPECT_OWNER_DIR
case _EXPECT_DIRORIGIN_BL: case _EXPECT_DIRORIGIN_BL:
if l.value != _BLANK { 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 return
} }
st = _EXPECT_DIRORIGIN st = _EXPECT_DIRORIGIN
case _EXPECT_DIRORIGIN: case _EXPECT_DIRORIGIN:
if l.value != _STRING { 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 return
} }
if !IsFqdn(l.token) { if !IsFqdn(l.token) {
@ -198,7 +232,7 @@ func parseZone(r io.Reader, t chan Token) {
} }
case _EXPECT_OWNER_BL: case _EXPECT_OWNER_BL:
if l.value != _BLANK { if l.value != _BLANK {
t <- Token{Error: &ParseError{"No blank after owner", l}} t <- Token{Error: &ParseError{f, "No blank after owner", l}}
return return
} }
st = _EXPECT_ANY st = _EXPECT_ANY
@ -210,30 +244,30 @@ func parseZone(r io.Reader, t chan Token) {
case _CLASS: case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)] h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok { if !ok {
t <- Token{Error: &ParseError{"Unknown class", l}} t <- Token{Error: &ParseError{f, "Unknown class", l}}
return return
} }
st = _EXPECT_ANY_NOCLASS_BL st = _EXPECT_ANY_NOCLASS_BL
case _STRING: // TTL is this case case _STRING: // TTL is this case
if ttl, ok := stringToTtl(l, t); !ok { if ttl, ok := stringToTtl(l, f, t); !ok {
return return
} else { } else {
h.Ttl = ttl h.Ttl = ttl
} }
st = _EXPECT_ANY_NOTTL_BL st = _EXPECT_ANY_NOTTL_BL
default: 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 return
} }
case _EXPECT_ANY_NOCLASS_BL: case _EXPECT_ANY_NOCLASS_BL:
if l.value != _BLANK { if l.value != _BLANK {
t <- Token{Error: &ParseError{"No blank before NOCLASS", l}} t <- Token{Error: &ParseError{f, "No blank before NOCLASS", l}}
return return
} }
st = _EXPECT_ANY_NOCLASS st = _EXPECT_ANY_NOCLASS
case _EXPECT_ANY_NOTTL_BL: case _EXPECT_ANY_NOTTL_BL:
if l.value != _BLANK { if l.value != _BLANK {
t <- Token{Error: &ParseError{"No blank before NOTTL", l}} t <- Token{Error: &ParseError{f, "No blank before NOTTL", l}}
return return
} }
st = _EXPECT_ANY_NOTTL st = _EXPECT_ANY_NOTTL
@ -242,7 +276,7 @@ func parseZone(r io.Reader, t chan Token) {
case _CLASS: case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)] h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok { if !ok {
t <- Token{Error: &ParseError{"Unknown class", l}} t <- Token{Error: &ParseError{f, "Unknown class", l}}
return return
} }
st = _EXPECT_RRTYPE_BL st = _EXPECT_RRTYPE_BL
@ -253,7 +287,7 @@ func parseZone(r io.Reader, t chan Token) {
case _EXPECT_ANY_NOCLASS: case _EXPECT_ANY_NOCLASS:
switch l.value { switch l.value {
case _STRING: // TTL case _STRING: // TTL
if ttl, ok := stringToTtl(l, t); !ok { if ttl, ok := stringToTtl(l, f, t); !ok {
return return
} else { } else {
h.Ttl = ttl h.Ttl = ttl
@ -263,25 +297,25 @@ func parseZone(r io.Reader, t chan Token) {
h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA st = _EXPECT_RDATA
default: 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 return
} }
case _EXPECT_RRTYPE_BL: case _EXPECT_RRTYPE_BL:
if l.value != _BLANK { if l.value != _BLANK {
t <- Token{Error: &ParseError{"No blank after", l}} t <- Token{Error: &ParseError{f, "No blank after", l}}
return return
} }
st = _EXPECT_RRTYPE st = _EXPECT_RRTYPE
case _EXPECT_RRTYPE: case _EXPECT_RRTYPE:
if l.value != _RRTYPE { if l.value != _RRTYPE {
t <- Token{Error: &ParseError{"Unknown RR type", l}} t <- Token{Error: &ParseError{f, "Unknown RR type", l}}
return return
} }
h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA st = _EXPECT_RDATA
case _EXPECT_RDATA: case _EXPECT_RDATA:
// I could save my token here...? l // 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 != nil {
// If e.lex is nil than we have encounter a unknown RR type // If e.lex is nil than we have encounter a unknown RR type
// in that case we substitute our current lex token // 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.value = _OWNER
l.token = str l.token = str
// escape $... start with a \ not a $, so this will work // escape $... start with a \ not a $, so this will work
if str == "$TTL" { switch str {
case "$TTL":
l.value = _DIRTTL l.value = _DIRTTL
} case "$ORIGIN":
if str == "$ORIGIN" {
l.value = _DIRORIGIN l.value = _DIRORIGIN
} case "$INCLUDE":
l.value = _DIRINCLUDE
}
c <- l c <- l
} else { } else {
l.value = _STRING 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 { 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 return 0, false
} else { } else {
return uint32(ttl), true return uint32(ttl), true

View File

@ -13,62 +13,62 @@ import (
// or immediately a _NEWLINE. If this is not the case we flag // or immediately a _NEWLINE. If this is not the case we flag
// an *ParseError: garbage after rdata. // 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 var r RR
e := new(ParseError) e := new(ParseError)
switch h.Rrtype { switch h.Rrtype {
case TypeA: case TypeA:
r, e = setA(h, c) r, e = setA(h, c, f)
goto Slurp goto Slurp
case TypeAAAA: case TypeAAAA:
r, e = setAAAA(h, c) r, e = setAAAA(h, c, f)
goto Slurp goto Slurp
case TypeNS: case TypeNS:
r, e = setNS(h, c, o) r, e = setNS(h, c, o, f)
goto Slurp goto Slurp
case TypeMX: case TypeMX:
r, e = setMX(h, c, o) r, e = setMX(h, c, o, f)
goto Slurp goto Slurp
case TypeCNAME: case TypeCNAME:
r, e = setCNAME(h, c, o) r, e = setCNAME(h, c, o, f)
goto Slurp goto Slurp
case TypeSOA: case TypeSOA:
r, e = setSOA(h, c, o) r, e = setSOA(h, c, o, f)
goto Slurp goto Slurp
case TypeSSHFP: case TypeSSHFP:
r, e = setSSHFP(h, c) r, e = setSSHFP(h, c, f)
goto Slurp goto Slurp
case TypeDNSKEY: case TypeDNSKEY:
// These types have a variable ending either chunks of txt or chunks/base64 or hex. // 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 // 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. // 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: case TypeRRSIG:
return setRRSIG(h, c, o) return setRRSIG(h, c, o, f)
case TypeNSEC: case TypeNSEC:
return setNSEC(h, c, o) return setNSEC(h, c, o, f)
case TypeNSEC3: case TypeNSEC3:
return setNSEC3(h, c, o) return setNSEC3(h, c, o, f)
case TypeDS: case TypeDS:
return setDS(h, c) return setDS(h, c, f)
case TypeTXT: case TypeTXT:
return setTXT(h, c) return setTXT(h, c, f)
default: default:
// Don't the have the token the holds the RRtype, but we substitute that in the // Don't the have the token the holds the RRtype, but we substitute that in the
// calling function when lex is empty. // calling function when lex is empty.
return nil, &ParseError{"Unknown RR type", lex{}} return nil, &ParseError{f, "Unknown RR type", lex{}}
} }
Slurp: Slurp:
if e != nil { if e != nil {
return nil, e return nil, e
} }
if se := slurpRemainder(c); se != nil { if se := slurpRemainder(c, f); se != nil {
return nil, se return nil, se
} }
return r, e return r, e
} }
func slurpRemainder(c chan lex) *ParseError { func slurpRemainder(c chan lex, f string) *ParseError {
l := <-c l := <-c
if _DEBUG { if _DEBUG {
fmt.Printf("%v\n", l) fmt.Printf("%v\n", l)
@ -80,7 +80,7 @@ func slurpRemainder(c chan lex) *ParseError {
fmt.Printf("%v\n", l) fmt.Printf("%v\n", l)
} }
if l.value != _NEWLINE && l.value != _EOF { if l.value != _NEWLINE && l.value != _EOF {
return &ParseError{"garbage after rdata", l} return &ParseError{f, "garbage after rdata", l}
} }
// Ok // Ok
case _NEWLINE: case _NEWLINE:
@ -88,43 +88,43 @@ func slurpRemainder(c chan lex) *ParseError {
case _EOF: case _EOF:
// Ok // Ok
default: default:
return &ParseError{"garbage after directly rdata", l} return &ParseError{f, "garbage after directly rdata", l}
} }
return nil 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 := new(RR_A)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
rr.A = net.ParseIP(l.token) rr.A = net.ParseIP(l.token)
if rr.A == nil { if rr.A == nil {
return nil, &ParseError{"bad A", l} return nil, &ParseError{f, "bad A", l}
} }
return rr, nil 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 := new(RR_AAAA)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
rr.AAAA = net.ParseIP(l.token) rr.AAAA = net.ParseIP(l.token)
if rr.AAAA == nil { if rr.AAAA == nil {
return nil, &ParseError{"bad AAAA", l} return nil, &ParseError{f, "bad AAAA", l}
} }
return rr, nil 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 := new(RR_NS)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
rr.Ns = l.token rr.Ns = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.Ns) {
rr.Ns += o rr.Ns += o
@ -132,13 +132,13 @@ func setNS(h RR_Header, c chan lex, o string) (RR, *ParseError) {
return rr, nil 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 := new(RR_MX)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if i, e := strconv.Atoi(l.token); e != nil { 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 { } else {
rr.Pref = uint16(i) rr.Pref = uint16(i)
} }
@ -146,7 +146,7 @@ func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) {
l = <-c // _STRING l = <-c // _STRING
rr.Mx = l.token rr.Mx = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.Mx) {
rr.Mx += o rr.Mx += o
@ -154,14 +154,14 @@ func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) {
return rr, nil 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 := new(RR_CNAME)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
rr.Cname = l.token rr.Cname = l.token
if _, ok := IsDomainName(l.token); !ok { if _, ok := IsDomainName(l.token); !ok {
return nil, &ParseError{"bad CNAME", l} return nil, &ParseError{f, "bad CNAME", l}
} }
if !IsFqdn(rr.Cname) { if !IsFqdn(rr.Cname) {
rr.Cname += o rr.Cname += o
@ -169,7 +169,7 @@ func setCNAME(h RR_Header, c chan lex, o string) (RR, *ParseError) {
return rr, nil 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 := new(RR_SOA)
rr.Hdr = h rr.Hdr = h
@ -177,7 +177,7 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) {
rr.Ns = l.token rr.Ns = l.token
<-c // _BLANK <-c // _BLANK
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.Ns) {
rr.Ns += o rr.Ns += o
@ -186,7 +186,7 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) {
l = <-c l = <-c
rr.Mbox = l.token rr.Mbox = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.Mbox) {
rr.Mbox += o 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++ { for i := 0; i < 5; i++ {
l = <-c l = <-c
if j, e = strconv.Atoi(l.token); e != nil { 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 { switch i {
case 0: case 0:
@ -220,54 +220,54 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) {
return rr, nil 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 := new(RR_RRSIG)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if t, ok := Str_rr[strings.ToUpper(l.token)]; !ok { if t, ok := Str_rr[strings.ToUpper(l.token)]; !ok {
return nil, &ParseError{"bad RRSIG", l} return nil, &ParseError{f, "bad RRSIG", l}
} else { } else {
rr.TypeCovered = t rr.TypeCovered = t
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := strconv.Atoi(l.token); err != nil { if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{"bad RRSIG", l} return nil, &ParseError{f, "bad RRSIG", l}
} else { } else {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := strconv.Atoi(l.token); err != nil { if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{"bad RRSIG", l} return nil, &ParseError{f, "bad RRSIG", l}
} else { } else {
rr.Labels = uint8(i) rr.Labels = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := strconv.Atoi(l.token); err != nil { if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{"bad RRSIG", l} return nil, &ParseError{f, "bad RRSIG", l}
} else { } else {
rr.OrigTtl = uint32(i) rr.OrigTtl = uint32(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := dateToTime(l.token); err != nil { if i, err := dateToTime(l.token); err != nil {
return nil, &ParseError{"bad RRSIG expiration", l} return nil, &ParseError{f, "bad RRSIG expiration", l}
} else { } else {
rr.Expiration = i rr.Expiration = i
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := dateToTime(l.token); err != nil { if i, err := dateToTime(l.token); err != nil {
return nil, &ParseError{"bad RRSIG inception", l} return nil, &ParseError{f, "bad RRSIG inception", l}
} else { } else {
rr.Inception = i rr.Inception = i
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, err := strconv.Atoi(l.token); err != nil { 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 { } else {
rr.KeyTag = uint16(i) rr.KeyTag = uint16(i)
} }
@ -275,7 +275,7 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) {
l = <-c l = <-c
rr.SignerName = l.token rr.SignerName = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.SignerName) {
rr.SignerName += o rr.SignerName += o
@ -290,7 +290,7 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) {
case _BLANK: case _BLANK:
// Ok // Ok
default: default:
return nil, &ParseError{"bad RRSIG signature", l} return nil, &ParseError{f, "bad RRSIG signature", l}
} }
l = <-c l = <-c
} }
@ -298,14 +298,14 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) {
return rr, nil 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 := new(RR_NSEC)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
rr.NextDomain = l.token rr.NextDomain = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.NextDomain) {
rr.NextDomain += o rr.NextDomain += o
@ -319,39 +319,39 @@ func setNSEC(h RR_Header, c chan lex, o string) (RR, *ParseError) {
// Ok // Ok
case _STRING: case _STRING:
if k, ok := Str_rr[strings.ToUpper(l.token)]; !ok { 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 { } else {
rr.TypeBitMap = append(rr.TypeBitMap, k) rr.TypeBitMap = append(rr.TypeBitMap, k)
} }
default: default:
return nil, &ParseError{"bad NSEC garbage in type bitmap", l} return nil, &ParseError{f, "bad NSEC garbage in type bitmap", l}
} }
l = <-c l = <-c
} }
return rr, nil 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 := new(RR_NSEC3)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad NSEC3", l} return nil, &ParseError{f, "bad NSEC3", l}
} else { } else {
rr.Hash = uint8(i) rr.Hash = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad NSEC3", l} return nil, &ParseError{f, "bad NSEC3", l}
} else { } else {
rr.Flags = uint8(i) rr.Flags = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad NSEC3", l} return nil, &ParseError{f, "bad NSEC3", l}
} else { } else {
rr.Iterations = uint16(i) 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.HashLength = uint8(len(l.token))
rr.NextDomain = l.token rr.NextDomain = l.token
if _, ok := IsDomainName(l.token); !ok { 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) { if !IsFqdn(rr.NextDomain) {
rr.NextDomain += o rr.NextDomain += o
@ -379,12 +379,12 @@ func setNSEC3(h RR_Header, c chan lex, o string) (RR, *ParseError) {
// Ok // Ok
case _STRING: case _STRING:
if k, ok := Str_rr[strings.ToUpper(l.token)]; !ok { if k, ok := Str_rr[strings.ToUpper(l.token)]; !ok {
return nil, &ParseError{"bad NSEC3", l} return nil, &ParseError{f, "bad NSEC3", l}
} else { } else {
rr.TypeBitMap = append(rr.TypeBitMap, k) rr.TypeBitMap = append(rr.TypeBitMap, k)
} }
default: default:
return nil, &ParseError{"bad NSEC3", l} return nil, &ParseError{f, "bad NSEC3", l}
} }
l = <-c 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 := new(RR_SSHFP)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad SSHFP", l} return nil, &ParseError{f, "bad SSHFP", l}
} else { } else {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad SSHFP", l} return nil, &ParseError{f, "bad SSHFP", l}
} else { } else {
rr.Type = uint8(i) rr.Type = uint8(i)
} }
@ -440,27 +440,27 @@ func setSSHFP(h RR_Header, c chan lex) (RR, *ParseError) {
return rr, nil 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 := new(RR_DNSKEY)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DNSKEY", l} return nil, &ParseError{f, "bad DNSKEY", l}
} else { } else {
rr.Flags = uint16(i) rr.Flags = uint16(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c // _STRING l = <-c // _STRING
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DNSKEY", l} return nil, &ParseError{f, "bad DNSKEY", l}
} else { } else {
rr.Protocol = uint8(i) rr.Protocol = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c // _STRING l = <-c // _STRING
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DNSKEY", l} return nil, &ParseError{f, "bad DNSKEY", l}
} else { } else {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
} }
@ -473,7 +473,7 @@ func setDNSKEY(h RR_Header, c chan lex) (RR, *ParseError) {
case _BLANK: case _BLANK:
// Ok // Ok
default: default:
return nil, &ParseError{"bad DNSKEY", l} return nil, &ParseError{f, "bad DNSKEY", l}
} }
l = <-c l = <-c
} }
@ -482,26 +482,26 @@ func setDNSKEY(h RR_Header, c chan lex) (RR, *ParseError) {
} }
// DLV and TA are the same // 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 := new(RR_DS)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DS", l} return nil, &ParseError{f, "bad DS", l}
} else { } else {
rr.KeyTag = uint16(i) rr.KeyTag = uint16(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DS", l} return nil, &ParseError{f, "bad DS", l}
} else { } else {
rr.Algorithm = uint8(i) rr.Algorithm = uint8(i)
} }
<-c // _BLANK <-c // _BLANK
l = <-c l = <-c
if i, e := strconv.Atoi(l.token); e != nil { if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{"bad DS", l} return nil, &ParseError{f, "bad DS", l}
} else { } else {
rr.DigestType = uint8(i) rr.DigestType = uint8(i)
} }
@ -515,7 +515,7 @@ func setDS(h RR_Header, c chan lex) (RR, *ParseError) {
case _BLANK: case _BLANK:
// Ok // Ok
default: default:
return nil, &ParseError{"bad DS", l} return nil, &ParseError{f, "bad DS", l}
} }
l = <-c l = <-c
} }
@ -523,7 +523,7 @@ func setDS(h RR_Header, c chan lex) (RR, *ParseError) {
return rr, nil 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 := new(RR_TXT)
rr.Hdr = h rr.Hdr = h
@ -537,7 +537,7 @@ func setTXT(h RR_Header, c chan lex) (RR, *ParseError) {
case _BLANK: case _BLANK:
s += l.token s += l.token
default: default:
return nil, &ParseError{"bad TXT", l} return nil, &ParseError{f, "bad TXT", l}
} }
l = <-c l = <-c
} }