diff --git a/TODO.markdown b/TODO.markdown index b479118a..16582cdd 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -1,10 +1,6 @@ # TODO * Support for on-the-fly-signing or check how to do it -* Test all rdata packing with zero rdata -- allowed for dynamic updates -* Actually mimic net/ ? Dial. Read/Write ? - - if I want this i need to work on something else than \*Client, because a single client - can have multiple oustanding qeuries * Ratelimiting? server side (rrl) * Ratelimiting? client side diff --git a/client.go b/client.go index 847af4f5..02c17396 100644 --- a/client.go +++ b/client.go @@ -31,16 +31,16 @@ type reply struct { // A Client defines parameter for a DNS client. A nil // Client is usable for sending queries. type Client struct { - Net string // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) - ReadTimeout time.Duration // the net.Conn.SetReadTimeout value for new connections (ns), defaults to 2 * 1e9 - WriteTimeout time.Duration // the net.Conn.SetWriteTimeout value for new connections (ns), defaults to 2 * 1e9 - TsigSecret map[string]string // secret(s) for Tsig map[], zonename must be fully qualified - Inflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass - group singleflight + Net string // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) + ReadTimeout time.Duration // the net.Conn.SetReadTimeout value for new connections (ns), defaults to 2 * 1e9 + WriteTimeout time.Duration // the net.Conn.SetWriteTimeout value for new connections (ns), defaults to 2 * 1e9 + TsigSecret map[string]string // secret(s) for Tsig map[], zonename must be fully qualified + SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass + group singleflight } func (c *Client) exchangeMerge(m *Msg, a string, s net.Conn) (r *Msg, rtt time.Duration, err error) { - if !c.Inflight { + if !c.SingleInflight { if s == nil { return c.exchange(m, a) } diff --git a/client_test.go b/client_test.go index 63b6f326..0d93e961 100644 --- a/client_test.go +++ b/client_test.go @@ -41,12 +41,12 @@ func TestClientEDNS0(t *testing.T) { } } -func TestInflight(t *testing.T) { +func TestSingleSingleInflight(t *testing.T) { m := new(Msg) m.SetQuestion("miek.nl.", TypeDNSKEY) c := new(Client) - c.Inflight = true + c.SingleInflight = true nr := 10 ch := make(chan time.Duration) for i := 0; i < nr; i++ { diff --git a/defaults.go b/defaults.go index 0b772505..f4b80341 100644 --- a/defaults.go +++ b/defaults.go @@ -156,76 +156,13 @@ func (dns *Msg) IsEdns0() *OPT { } // IsDomainName checks if s is a valid domainname, it returns -// the number of labels, total length and true, when a domain name is valid. -// Note that unfully qualified domain name is considered valid, in this case the +// the number of labels and true, when a domain name is valid. +// Note that non fully qualified domain name is considered valid, in this case the // last label is counted in the number of labels. -// When false is returned the labelcount and length are not defined. -func IsDomainName(s string) (uint8, uint8, bool) { // copied from net package. - // See RFC 1035, RFC 3696. - l := len(s) - if l == 0 || l > 255 { - return 0, 0, false - } - // Preloop check for root label - if s == "." { - return 0, 1, true - } - - last := byte('.') - ok := false // Ok once we've seen a letter or digit. - partlen := 0 - labels := uint8(0) - var c byte - for i := 0; i < l; i++ { - c = s[i] - switch { - default: - // anything escaped is legal - if last != '\\' { - return 0, uint8(l), false - } - partlen++ - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*' || c == '/': - ok = true - partlen++ - case c == '\\': // OK. - case c == '@': - if last != '\\' { - return 0, uint8(l), false - } - partlen++ - case '0' <= c && c <= '9': - ok = true - partlen++ - case c == '-': - if last == '.' { - return 0, uint8(l), false - } - partlen++ - case c == '.': - // byte before dot cannot be dot - if last == '.' { - return 0, uint8(l), false - } - if last == '\\' { // Ok, escaped dot. - partlen++ - c = 'A' // Make current value not scary. - break - } - if partlen > 63 || partlen == 0 { - return 0, uint8(l), false - } - partlen = 0 - labels++ - } - last = c - } - // If last isn't a dot, the name was unqualified, but we still want to count - // the last label. - if last == '.' { - return labels, uint8(l), ok - } - return labels + 1, uint8(l), ok +// When false is returned the number of labels is not defined. +func IsDomainName(s string) (labels int, ok bool) { + _, labels, err := packDomainName(s, nil, 0, nil, false) + return labels, err == nil } // IsSubDomain checks if child is indeed a child of the parent. Both child and @@ -253,7 +190,7 @@ func Fqdn(s string) string { return s + "." } -// Copied from the official Go code +// Copied from the official Go code. // ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP // address addr suitable for rDNS (PTR) record lookup or an error if it fails diff --git a/dns.go b/dns.go index ed7b87cf..cc442f17 100644 --- a/dns.go +++ b/dns.go @@ -61,7 +61,10 @@ // c := new(Client) // in, rtt, err := c.Exchange(m1, "127.0.0.1:53") // -// For asynchronous queries it is easy to wrap Exchange() in a goroutine. +// For asynchronous queries it is easy to wrap Exchange() in a goroutine. Suppressing +// multiple outstanding queries (with the same question, type and class) is as easy as setting: +// +// c.SingleInflight = true // // A dns message consists out of four sections. // The question section: in.Question, the answer section: in.Answer, diff --git a/dnssec.go b/dnssec.go index ea9e28cf..d8446cc9 100644 --- a/dnssec.go +++ b/dnssec.go @@ -220,7 +220,7 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error { rr.OrigTtl = rrset[0].Header().Ttl rr.TypeCovered = rrset[0].Header().Rrtype rr.TypeCovered = rrset[0].Header().Rrtype - rr.Labels, _, _ = IsDomainName(rrset[0].Header().Name) + rr.Labels = uint8(CountLabel(rrset[0].Header().Name)) if strings.HasPrefix(rrset[0].Header().Name, "*") { rr.Labels-- // wildcard, remove from label count diff --git a/dnssec_test.go b/dnssec_test.go index 21b11adc..7c6fdf70 100644 --- a/dnssec_test.go +++ b/dnssec_test.go @@ -174,7 +174,7 @@ func TestSignVerify(t *testing.T) { sig := new(RRSIG) sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} sig.TypeCovered = soa.Hdr.Rrtype - sig.Labels, _, _ = IsDomainName(soa.Hdr.Name) + sig.Labels = uint8(CountLabel(soa.Hdr.Name)) sig.OrigTtl = soa.Hdr.Ttl sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" diff --git a/labels_test.go b/labels_test.go index 2e335a78..0493d830 100644 --- a/labels_test.go +++ b/labels_test.go @@ -95,20 +95,21 @@ domainLoop: func TestIsDomainName(t *testing.T) { type ret struct { ok bool - lab uint8 - l uint8 + lab int } names := map[string]*ret{ - "www.example.com": &ret{true, 3, 15}, - "www.example.com.": &ret{true, 3, 16}, - "mi\\k.nl.": &ret{true, 2, 8}, - "mi\\k.nl": &ret{true, 2, 7}, + "..": &ret{false, 1}, + "@.": &ret{true, 1}, + "www.example.com": &ret{true, 3}, + "www.example.com.": &ret{true, 3}, + "mi\\k.nl.": &ret{true, 2}, + "mi\\k.nl": &ret{true, 2}, } for d, ok := range names { - l1, l2, k := IsDomainName(d) - if ok.ok != k || ok.lab != l1 || ok.l != l2 { - t.Logf("Got %v %d %d for %s ", k, l1, l2, d) - t.Logf(" %v %d %d for %s ", ok.ok, ok.lab, ok.l, d) + l, k := IsDomainName(d) + if ok.ok != k || ok.lab != l { + t.Logf(" got %v %d for %s ", k, l, d) + t.Logf("have %v %d for %s ", ok.ok, ok.lab, d) t.Fail() } } diff --git a/msg.go b/msg.go index d5ccd821..e647d6fa 100644 --- a/msg.go +++ b/msg.go @@ -212,14 +212,31 @@ var RcodeToString = map[int]string{ // map needs to hold a mapping between domain names and offsets // pointing into msg[]. func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) { - lenmsg := len(msg) + off1, _, err = packDomainName(s, msg, off, compression, compress) + return +} + +func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) { + // special case if msg == nil + lenmsg := 256 + if msg != nil { + lenmsg = len(msg) + } ls := len(s) if ls == 0 { // Ok, for instance when dealing with update RR without any rdata. - return off, nil + return off, 0, nil } - // If not fully qualified, error out - if s[ls-1] != '.' { - return lenmsg, ErrFqdn + // If not fully qualified, error out, but only if msg == nil #ugly + switch { + case msg == nil: + if s[ls-1] != '.' { + s += "." + ls++ + } + case msg != nil: + if s[ls-1] != '.' { + return lenmsg, 0, ErrFqdn + } } // Each dot ends a segment of the name. // We trade each dot byte for a length byte. @@ -239,7 +256,7 @@ func PackDomainName(s string, msg []byte, off int, compression map[string]int, c } ls-- if off+1 > lenmsg { - return lenmsg, ErrBuf + return lenmsg, labels, ErrBuf } // check for \DDD if i+2 < ls && bs[i] >= '0' && bs[i] <= '9' && @@ -255,22 +272,30 @@ func PackDomainName(s string, msg []byte, off int, compression map[string]int, c } if bs[i] == '.' { + if i > 0 && bs[i-1] == '.' { + // two dots back to back is not legal + return lenmsg, labels, ErrRdata + } if i-begin >= 1<<6 { // top two bits of length must be clear - return lenmsg, ErrRdata + return lenmsg, labels, ErrRdata } // off can already (we're in a loop) be bigger than len(msg) // this happens when a name isn't fully qualified if off+1 > lenmsg { - return lenmsg, ErrBuf + return lenmsg, labels, ErrBuf + } + if msg != nil { + msg[off] = byte(i - begin) } - msg[off] = byte(i - begin) offset := off off++ for j := begin; j < i; j++ { if off+1 > lenmsg { - return lenmsg, ErrBuf + return lenmsg, labels, ErrBuf + } + if msg != nil { + msg[off] = bs[j] } - msg[off] = bs[j] off++ } // Dont try to compress '.' @@ -294,24 +319,28 @@ func PackDomainName(s string, msg []byte, off int, compression map[string]int, c } } } + labels++ begin = i + 1 } } // Root label is special if len(bs) == 1 && bs[0] == '.' { - return off, nil + return off, labels, nil } // If we did compression and we find something add the pointer here if pointer != -1 { // We have two bytes (14 bits) to put the pointer in + // if msg == nil, we will never do compression msg[nameoffset], msg[nameoffset+1] = packUint16(uint16(pointer ^ 0xC000)) off = nameoffset + 1 goto End } - msg[off] = 0 + if msg != nil { + msg[off] = 0 + } End: off++ - return off, nil + return off, labels, nil } // Unpack a domain name. diff --git a/parse_test.go b/parse_test.go index 7a6ac5c2..98ce5f77 100644 --- a/parse_test.go +++ b/parse_test.go @@ -267,7 +267,8 @@ func TestParseFailure(t *testing.T) { "miek.nl. IN AAAA ::x", "miek.nl. IN MX a0 miek.nl.", "miek.nl aap IN MX mx.miek.nl.", - "miek.nl. IN CNAME ", + // "miek.nl. IN CNAME ", // actually valid nowadays, zero size rdata + "miek.nl. IN CNAME ..", "miek.nl. PA MX 10 miek.nl.", "miek.nl. ) IN MX 10 miek.nl.", } @@ -275,7 +276,7 @@ func TestParseFailure(t *testing.T) { for _, s := range tests { _, err := NewRR(s) if err == nil { - t.Log("Should have triggered an error") + t.Logf("Should have triggered an error: \"%s\"", s) t.Fail() } } diff --git a/server.go b/server.go index 5314138b..a6eeff43 100644 --- a/server.go +++ b/server.go @@ -174,7 +174,7 @@ func (mux *ServeMux) match(q string, t uint16) Handler { for { l := len(q[off:]) for i := 0; i < l; i++ { - b[i] = q[off+i] | ( 'a' - 'A') + b[i] = q[off+i] | ('a' - 'A') } if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key if t != TypeDS { diff --git a/xfr.go b/xfr.go index 7655c1b1..77ea7e0f 100644 --- a/xfr.go +++ b/xfr.go @@ -70,7 +70,7 @@ func (w *reply) axfrIn(q *Msg, c chan *Envelope) { } first = !first // only one answer that is SOA, receive more - if (len(in.Answer) == 1) { + if len(in.Answer) == 1 { w.tsigTimersOnly = true c <- &Envelope{in.Answer, nil} continue diff --git a/zscan.go b/zscan.go index 6a6bdbc4..102bcefc 100644 --- a/zscan.go +++ b/zscan.go @@ -88,6 +88,7 @@ func (e *ParseError) Error() (s string) { type lex struct { token string // text of the token + length int // lenght of the token err bool // when true, token text has lexer error value uint8 // value: _STRING, _BLANK, etc. line int // line in the file @@ -179,11 +180,11 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) { if origin == "" { origin = "." } - if _, _, ok := IsDomainName(origin); !ok { + origin = Fqdn(origin) + if _, ok := IsDomainName(origin); !ok { t <- Token{Error: &ParseError{f, "bad initial origin name", lex{}}} return } - origin = Fqdn(origin) st := _EXPECT_OWNER_DIR // initial state var h RR_Header @@ -212,14 +213,14 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) { st = _EXPECT_OWNER_BL break } - _, ld, ok := IsDomainName(l.token) + if h.Name[l.length-1] != '.' { + h.Name = appendOrigin(h.Name, origin) + } + _, ok := IsDomainName(l.token) if !ok { t <- Token{Error: &ParseError{f, "bad owner name", l}} return } - if h.Name[ld-1] != '.' { - h.Name = appendOrigin(h.Name, origin) - } prevName = h.Name st = _EXPECT_OWNER_BL case _DIRTTL: @@ -273,12 +274,12 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) { case _BLANK: l := <-c if l.value == _STRING { - if _, _, ok := IsDomainName(l.token); !ok { + if _, ok := IsDomainName(l.token); !ok { t <- Token{Error: &ParseError{f, "bad origin name", l}} return } // a new origin is specified. - if !IsFqdn(l.token) { + if l.token[l.length-1] != '.' { if origin != "." { // Prevent .. endings neworigin = l.token + "." + origin } else { @@ -342,11 +343,11 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) { if e, _ := slurpRemainder(c, f); e != nil { t <- Token{Error: e} } - if _, _, ok := IsDomainName(l.token); !ok { + if _, ok := IsDomainName(l.token); !ok { t <- Token{Error: &ParseError{f, "bad origin name", l}} return } - if !IsFqdn(l.token) { + if l.token[l.length-1] != '.' { if origin != "." { // Prevent .. endings origin = l.token + "." + origin } else { @@ -527,6 +528,7 @@ func zlexer(s *scan, c chan lex) { // If we have a string and its the first, make it an owner l.value = _OWNER l.token = string(str[:stri]) + l.length = stri // escape $... start with a \ not a $, so this will work switch l.token { case "$TTL": @@ -543,7 +545,7 @@ func zlexer(s *scan, c chan lex) { } else { l.value = _STRING l.token = string(str[:stri]) - + l.length = stri if !rrtype { if t, ok := StringToType[l.token]; ok { l.value = _RRTYPE @@ -589,6 +591,7 @@ func zlexer(s *scan, c chan lex) { if !space && !commt { l.value = _BLANK l.token = " " + l.length = 1 debug.Printf("[5 %+v]", l.token) c <- l } @@ -610,6 +613,7 @@ func zlexer(s *scan, c chan lex) { if stri > 0 { l.value = _STRING l.token = string(str[:stri]) + l.length = stri debug.Printf("[4 %+v]", l.token) c <- l stri = 0 @@ -640,6 +644,7 @@ func zlexer(s *scan, c chan lex) { owner = true l.value = _NEWLINE l.token = "\n" + l.length = 1 l.comment = string(com[:comi]) debug.Printf("[3 %+v %+v]", l.token, l.comment) c <- l @@ -657,6 +662,7 @@ func zlexer(s *scan, c chan lex) { if stri != 0 { l.value = _STRING l.token = string(str[:stri]) + l.length = stri if !rrtype { if t, ok := StringToType[strings.ToUpper(l.token)]; ok { l.value = _RRTYPE @@ -669,6 +675,7 @@ func zlexer(s *scan, c chan lex) { } l.value = _NEWLINE l.token = "\n" + l.length = 1 debug.Printf("[1 %+v]", l.token) c <- l stri = 0 @@ -710,12 +717,14 @@ func zlexer(s *scan, c chan lex) { if stri != 0 { l.value = _STRING l.token = string(str[:stri]) + l.length = stri debug.Printf("[%+v]", l.token) c <- l stri = 0 } l.value = _QUOTE l.token = "\"" + l.length = 1 c <- l quote = !quote case '(', ')': @@ -761,10 +770,10 @@ func zlexer(s *scan, c chan lex) { } x, err = s.tokenText() } - // Hmm. if stri > 0 { // Send remainder l.token = string(str[:stri]) + l.length = stri l.value = _STRING debug.Printf("[%+v]", l.token) c <- l diff --git a/zscan_rr.go b/zscan_rr.go index db4068b5..4fd9b3ef 100644 --- a/zscan_rr.go +++ b/zscan_rr.go @@ -271,11 +271,11 @@ func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Ns = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad NS Ns", l} } - if rr.Ns[ld-1] != '.' { + if rr.Ns[l.length-1] != '.' { rr.Ns = appendOrigin(rr.Ns, o) } return rr, nil @@ -291,11 +291,11 @@ func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Ptr = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad PTR Ptr", l} } - if rr.Ptr[ld-1] != '.' { + if rr.Ptr[l.length-1] != '.' { rr.Ptr = appendOrigin(rr.Ptr, o) } return rr, nil @@ -310,11 +310,11 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if l.token == "@" { rr.Mbox = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad RP Mbox", l} } - if rr.Mbox[ld-1] != '.' { + if rr.Mbox[l.length-1] != '.' { rr.Mbox = appendOrigin(rr.Mbox, o) } } @@ -325,14 +325,13 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Txt = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad RP Txt", l} } - if rr.Txt[ld-1] != '.' { + if rr.Txt[l.length-1] != '.' { rr.Txt = appendOrigin(rr.Txt, o) } - return rr, nil } @@ -346,11 +345,11 @@ func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Mr = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MR Mr", l} } - if rr.Mr[ld-1] != '.' { + if rr.Mr[l.length-1] != '.' { rr.Mr = appendOrigin(rr.Mr, o) } return rr, nil @@ -366,11 +365,11 @@ func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Mb = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MB Mb", l} } - if rr.Mb[ld-1] != '.' { + if rr.Mb[l.length-1] != '.' { rr.Mb = appendOrigin(rr.Mb, o) } return rr, nil @@ -386,11 +385,11 @@ func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Mg = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MG Mg", l} } - if rr.Mg[ld-1] != '.' { + if rr.Mg[l.length-1] != '.' { rr.Mg = appendOrigin(rr.Mg, o) } return rr, nil @@ -418,11 +417,11 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if l.token == "@" { rr.Rmail = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MINFO Rmail", l} } - if rr.Rmail[ld-1] != '.' { + if rr.Rmail[l.length-1] != '.' { rr.Rmail = appendOrigin(rr.Rmail, o) } } @@ -433,11 +432,11 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Email = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MINFO Email", l} } - if rr.Email[ld-1] != '.' { + if rr.Email[l.length-1] != '.' { rr.Email = appendOrigin(rr.Email, o) } return rr, nil @@ -453,11 +452,11 @@ func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Mf = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MF Mf", l} } - if rr.Mf[ld-1] != '.' { + if rr.Mf[l.length-1] != '.' { rr.Mf = appendOrigin(rr.Mf, o) } return rr, nil @@ -473,11 +472,11 @@ func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Md = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MD Md", l} } - if rr.Md[ld-1] != '.' { + if rr.Md[l.length-1] != '.' { rr.Md = appendOrigin(rr.Md, o) } return rr, nil @@ -500,11 +499,11 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Mx = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad MX Mx", l} } - if rr.Mx[ld-1] != '.' { + if rr.Mx[l.length-1] != '.' { rr.Mx = appendOrigin(rr.Mx, o) } return rr, nil @@ -527,11 +526,11 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Host = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad RT Host", l} } - if rr.Host[ld-1] != '.' { + if rr.Host[l.length-1] != '.' { rr.Host = appendOrigin(rr.Host, o) } return rr, nil @@ -554,11 +553,11 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Hostname = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad AFSDB Hostname", l} } - if rr.Hostname[ld-1] != '.' { + if rr.Hostname[l.length-1] != '.' { rr.Hostname = appendOrigin(rr.Hostname, o) } return rr, nil @@ -590,11 +589,11 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Exchanger = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad KX Exchanger", l} } - if rr.Exchanger[ld-1] != '.' { + if rr.Exchanger[l.length-1] != '.' { rr.Exchanger = appendOrigin(rr.Exchanger, o) } return rr, nil @@ -610,11 +609,11 @@ func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Target = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad CNAME Target", l} } - if rr.Target[ld-1] != '.' { + if rr.Target[l.length-1] != '.' { rr.Target = appendOrigin(rr.Target, o) } return rr, nil @@ -630,11 +629,11 @@ func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Target = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad CNAME Target", l} } - if rr.Target[ld-1] != '.' { + if rr.Target[l.length-1] != '.' { rr.Target = appendOrigin(rr.Target, o) } return rr, nil @@ -650,11 +649,11 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if l.token == "@" { rr.Ns = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad SOA Ns", l} } - if rr.Ns[ld-1] != '.' { + if rr.Ns[l.length-1] != '.' { rr.Ns = appendOrigin(rr.Ns, o) } } @@ -664,11 +663,11 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if l.token == "@" { rr.Mbox = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad SOA Mbox", l} } - if rr.Mbox[ld-1] != '.' { + if rr.Mbox[l.length-1] != '.' { rr.Mbox = appendOrigin(rr.Mbox, o) } } @@ -743,11 +742,11 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Target = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad SRV Target", l} } - if rr.Target[ld-1] != '.' { + if rr.Target[l.length-1] != '.' { rr.Target = appendOrigin(rr.Target, o) } return rr, nil @@ -834,11 +833,11 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Replacement = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad NAPTR Replacement", l} } - if rr.Replacement[ld-1] != '.' { + if rr.Replacement[l.length-1] != '.' { rr.Replacement = appendOrigin(rr.Replacement, o) } return rr, nil @@ -853,11 +852,11 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if l.token == "@" { rr.PreviousName = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad TALINK PreviousName", l} } - if rr.PreviousName[ld-1] != '.' { + if rr.PreviousName[l.length-1] != '.' { rr.PreviousName = appendOrigin(rr.PreviousName, o) } } @@ -868,11 +867,11 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.NextName = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad TALINK NextName", l} } - if rr.NextName[ld-1] != '.' { + if rr.NextName[l.length-1] != '.' { rr.NextName = appendOrigin(rr.NextName, o) } return rr, nil @@ -1036,11 +1035,11 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { xs = append(xs, o) continue } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad HIP RendezvousServers", l}, "" } - if l.token[ld-1] != '.' { + if l.token[l.length-1] != '.' { l.token = appendOrigin(l.token, o) } xs = append(xs, l.token) @@ -1144,11 +1143,11 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { if l.token == "@" { rr.SignerName = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad RRSIG SignerName", l}, "" } - if rr.SignerName[ld-1] != '.' { + if rr.SignerName[l.length-1] != '.' { rr.SignerName = appendOrigin(rr.SignerName, o) } } @@ -1169,11 +1168,11 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { if l.token == "@" { rr.NextDomain = o } else { - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad NSEC NextDomain", l}, "" } - if rr.NextDomain[ld-1] != '.' { + if rr.NextDomain[l.length-1] != '.' { rr.NextDomain = appendOrigin(rr.NextDomain, o) } } @@ -1861,11 +1860,11 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.Fqdn = o return rr, nil } - _, ld, ok := IsDomainName(l.token) + _, ok := IsDomainName(l.token) if !ok { return nil, &ParseError{f, "bad LP Fqdn", l} } - if rr.Fqdn[ld-1] != '.' { + if rr.Fqdn[l.length-1] != '.' { rr.Fqdn = appendOrigin(rr.Fqdn, o) } return rr, nil