Remove the Labels() function.

This is now handled inside IsDomainName, which really parses
the name and then (also) returns the number of labels found.
This commit is contained in:
Miek Gieben 2012-01-08 15:54:33 +01:00
parent e522a6daf7
commit ecfd5451a9
5 changed files with 57 additions and 79 deletions

View File

@ -197,84 +197,74 @@ func (dns *Msg) IsEdns0() (ok bool) {
} }
// IsDomainName checks if s is a valid domainname, it returns // IsDomainName checks if s is a valid domainname, it returns
// true and a length, when a domain name is valid. When false // the number of labels and true, when a domain name is valid. When false
// ithe returned length isn't specified. // the returned labelcount isn't specified.
func IsDomainName(s string) (bool, int) { // copied from net package. func IsDomainName(s string) (int, bool) { // copied from net package.
// See RFC 1035, RFC 3696. // See RFC 1035, RFC 3696.
if len(s) == 0 { if len(s) == 0 {
return false, 0 return 0, false
} }
if len(s) > 255 { // Not true...? if len(s) > 255 { // Not true...?
return false, 0 return 0, false
} }
if !Fqdn(s) { // simplify checking loop: make name end in dot s = Fqdn(s) // simplify checking loop: make name end in dot
s += "."
}
last := byte('.') last := byte('.')
ok := false // ok once we've seen a letter ok := false // ok once we've seen a letter
partlen := 0 partlen := 0
n := 0 labels := 0
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
c := s[i] c := s[i]
switch { switch {
default: default:
return false, 0 return 0, false
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*': case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*':
ok = true ok = true
partlen++ partlen++
n++ case c == '\\':
case c == '\\': // Ok
// Ok
case '0' <= c && c <= '9': case '0' <= c && c <= '9':
// fine // fine
partlen++ partlen++
n++
case c == '-': case c == '-':
// byte before dash cannot be dot // byte before dash cannot be dot
if last == '.' { if last == '.' {
return false, 0 return 0, false
} }
partlen++ partlen++
case c == '.': case c == '.':
// byte before dot cannot be dot, dash // byte before dot cannot be dot, dash
if last == '.' || last == '-' { if last == '.' || last == '-' {
return false, 0 return 0, false
}
if last == '\\' { // Ok, escaped dot.
partlen++
break
} }
if last == '\\' { // Ok, escaped dot.
partlen++
n++
break
}
if partlen > 63 || partlen == 0 { if partlen > 63 || partlen == 0 {
return false, 0 return 0, false
} }
partlen = 0 partlen = 0
n++ labels++
} }
last = c last = c
} }
return ok, n return labels, ok
} }
// Return the number of labels in a domain name. // IsFqdn checks if a domain name is fully qualified
// Need to add these kind of function in a structured way. TODO(mg) func IsFqdn(s string) bool {
func Labels(a string) (c uint8) { if len(s) == 0 {
// walk the string and count the dots return false // ?
// except when it is escaped
esc := false
for _, v := range a {
switch v {
case '.':
if esc {
esc = !esc
continue
}
c++
case '\\':
esc = true
}
} }
return return s[len(s)-1] == '.'
}
// Fqdns return the fully qualified domain name from s.
// Is s is already fq, then it behaves as the identity function.
func Fqdn(s string) string {
if IsFqdn(s) {
return s
}
return s + "."
} }

16
dns.go
View File

@ -219,12 +219,8 @@ func zoneMatch(pattern, zone string) (ok bool) {
if len(zone) == 0 { if len(zone) == 0 {
zone = "." zone = "."
} }
if pattern[len(pattern)-1] != '.' { pattern = Fqdn(pattern)
pattern += "." zone = Fqdn(zone)
}
if zone[len(zone)-1] != '.' {
zone += "."
}
i := 0 i := 0
for { for {
ok = pattern[len(pattern)-1-i] == zone[len(zone)-1-i] ok = pattern[len(pattern)-1-i] == zone[len(zone)-1-i]
@ -240,11 +236,3 @@ func zoneMatch(pattern, zone string) (ok bool) {
} }
return return
} }
// Fqdn checks if a domain name is fully qualified
func Fqdn(s string) bool {
if len(s) == 0 {
return false // ?
}
return s[len(s)-1] == '.'
}

View File

@ -188,9 +188,9 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) error {
s.OrigTtl = rrset[0].Header().Ttl s.OrigTtl = rrset[0].Header().Ttl
s.TypeCovered = rrset[0].Header().Rrtype s.TypeCovered = rrset[0].Header().Rrtype
s.TypeCovered = rrset[0].Header().Rrtype s.TypeCovered = rrset[0].Header().Rrtype
s.Labels = Labels(rrset[0].Header().Name) s.Labels, _ := IsDomainName(rrset[0].Header().Name)
if strings.HasPrefix(rrset[0].Header().Name, "*") { if strings.HasPrefix(rrset[0].Header().Name, "*") {
s.Labels-- // wildcards, remove from label count s.Labels-- // wildcard, remove from label count
} }
sigwire := new(rrsigWireFmt) sigwire := new(rrsigWireFmt)

View File

@ -147,11 +147,11 @@ func parseZone(r io.Reader, t chan Token) {
st = _EXPECT_OWNER_DIR st = _EXPECT_OWNER_DIR
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{"bad owner name", l}}
return return
} }
if !Fqdn(h.Name) { if !IsFqdn(h.Name) {
h.Name += origin h.Name += origin
} }
st = _EXPECT_OWNER_BL st = _EXPECT_OWNER_BL
@ -191,7 +191,7 @@ func parseZone(r io.Reader, t chan Token) {
t <- Token{Error: &ParseError{"Expecting $ORIGIN value, not this...", l}} t <- Token{Error: &ParseError{"Expecting $ORIGIN value, not this...", l}}
return return
} }
if !Fqdn(l.token) { if !IsFqdn(l.token) {
origin = l.token + origin // Append old origin if the new one isn't a fqdn origin = l.token + origin // Append old origin if the new one isn't a fqdn
} else { } else {
origin = l.token origin = l.token

View File

@ -123,10 +123,10 @@ func setNS(h RR_Header, c chan lex, o string) (RR, *ParseError) {
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{"bad NS Ns", l}
} }
if !Fqdn(rr.Ns) { if !IsFqdn(rr.Ns) {
rr.Ns += o rr.Ns += o
} }
return rr, nil return rr, nil
@ -145,10 +145,10 @@ func setMX(h RR_Header, c chan lex, o string) (RR, *ParseError) {
<-c // _BLANK <-c // _BLANK
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{"bad MX Mx", l}
} }
if !Fqdn(rr.Mx) { if !IsFqdn(rr.Mx) {
rr.Mx += o rr.Mx += o
} }
return rr, nil return rr, nil
@ -160,10 +160,10 @@ func setCNAME(h RR_Header, c chan lex, o string) (RR, *ParseError) {
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{"bad CNAME", l}
} }
if !Fqdn(rr.Cname) { if !IsFqdn(rr.Cname) {
rr.Cname += o rr.Cname += o
} }
return rr, nil return rr, nil
@ -176,19 +176,19 @@ func setSOA(h RR_Header, c chan lex, o string) (RR, *ParseError) {
l := <-c l := <-c
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{"bad SOA mname", l}
} }
if !Fqdn(rr.Ns) { if !IsFqdn(rr.Ns) {
rr.Ns += o rr.Ns += o
} }
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{"bad SOA rname", l}
} }
if !Fqdn(rr.Mbox) { if !IsFqdn(rr.Mbox) {
rr.Mbox += o rr.Mbox += o
} }
<-c // _BLANK <-c // _BLANK
@ -274,10 +274,10 @@ func setRRSIG(h RR_Header, c chan lex, o string) (RR, *ParseError) {
<-c // _BLANK <-c // _BLANK
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{"bad RRSIG signername", l}
} }
if !Fqdn(rr.SignerName) { if !IsFqdn(rr.SignerName) {
rr.SignerName += o rr.SignerName += o
} }
// Get the remaining data until we see a NEWLINE // Get the remaining data until we see a NEWLINE
@ -304,10 +304,10 @@ func setNSEC(h RR_Header, c chan lex, o string) (RR, *ParseError) {
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{"bad NSEC nextdomain", l}
} }
if !Fqdn(rr.NextDomain) { if !IsFqdn(rr.NextDomain) {
rr.NextDomain += o rr.NextDomain += o
} }
@ -364,10 +364,10 @@ func setNSEC3(h RR_Header, c chan lex, o string) (RR, *ParseError) {
l = <-c l = <-c
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{"bad NSEC nextdomain", l}
} }
if !Fqdn(rr.NextDomain) { if !IsFqdn(rr.NextDomain) {
rr.NextDomain += o rr.NextDomain += o
} }