Work on making IsDomainName better

This commit is contained in:
Miek Gieben 2013-09-10 13:13:10 +00:00
parent 2b6e9122bd
commit 47cc5b052d
4 changed files with 107 additions and 130 deletions

View File

@ -156,76 +156,44 @@ 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
// When false is returned the number of labels is not defined.
func IsDomainName(s string) (int, bool) {
// use PackDomainName
if buf == nil {
buf = make([]byte, 256)
}
// Preloop check for root label
if s == "." {
return 0, 1, true
lenmsg, err := PackDomainName(s, buf, 0, nil, false)
if err != nil {
return 0, false
}
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.
// There are no compression pointers, because the map was nil, so
// walk the binary name and count the length bits - this is the number
// of labels.
off := 0
labels := 0
Loop:
for {
if off >= lenmsg {
return labels, false
}
c := int(buf[off])
switch c & 0xC0 {
case 0x00:
if c == 0x00 {
// end of name
break
}
if partlen > 63 || partlen == 0 {
return 0, uint8(l), false
if off+c > lenmsg {
return labels, false
}
partlen = 0
labels++
off += c
}
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
return labels, true
}
// IsSubDomain checks if child is indeed a child of the parent. Both child and
@ -253,7 +221,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

View File

@ -222,7 +222,8 @@ 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)
x := CountLabel(rrset[0].Header().Name)
rr.Labels = uint8(x)
if strings.HasPrefix(rrset[0].Header().Name, "*") {
rr.Labels-- // wildcard, remove from label count

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