Merge branch 'master' of github.com:miekg/dns

This commit is contained in:
Miek Gieben 2013-09-11 08:22:23 +01:00
commit ee8ace0477
14 changed files with 156 additions and 181 deletions

View File

@ -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

View File

@ -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>]<base64 secret>, 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>]<base64 secret>, 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)
}

View File

@ -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++ {

View File

@ -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

5
dns.go
View File

@ -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,

View File

@ -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

View File

@ -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"

View File

@ -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()
}
}

57
msg.go
View File

@ -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.

View File

@ -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()
}
}

View File

@ -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 {

2
xfr.go
View File

@ -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

View File

@ -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

View File

@ -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