diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
commit | 3e45412327a2654a77944249962b3652e6142299 (patch) | |
tree | bc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/net/dnsclient.go | |
parent | c533680039762cacbc37db8dc7eed074c3e497be (diff) | |
download | golang-3e45412327a2654a77944249962b3652e6142299.tar.gz |
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/net/dnsclient.go')
-rw-r--r-- | src/pkg/net/dnsclient.go | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/src/pkg/net/dnsclient.go b/src/pkg/net/dnsclient.go index ea21117e3..f1cd47bb1 100644 --- a/src/pkg/net/dnsclient.go +++ b/src/pkg/net/dnsclient.go @@ -15,9 +15,9 @@ package net import ( - "once" "os" "rand" + "sync" "time" ) @@ -30,6 +30,9 @@ type DNSError struct { } func (e *DNSError) String() string { + if e == nil { + return "<nil>" + } s := "lookup " + e.Name if e.Server != "" { s += " on " + e.Server @@ -52,7 +55,7 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, os.Er out := new(dnsMsg) out.id = uint16(rand.Int()) ^ uint16(time.Nanoseconds()) out.question = []dnsQuestion{ - dnsQuestion{name, qtype, dnsClassINET}, + {name, qtype, dnsClassINET}, } out.recursion_desired = true msg, ok := out.Pack() @@ -189,42 +192,46 @@ var dnserr os.Error func loadConfig() { cfg, dnserr = dnsReadConfig() } func isDomainName(s string) bool { - // Requirements on DNS name: - // * must not be empty. - // * must be alphanumeric plus - and . - // * each of the dot-separated elements must begin - // and end with a letter or digit. - // RFC 1035 required the element to begin with a letter, - // but RFC 3696 says this has been relaxed to allow digits too. - // still, there must be a letter somewhere in the entire name. + // See RFC 1035, RFC 3696. if len(s) == 0 { return false } + if len(s) > 255 { + return false + } if s[len(s)-1] != '.' { // simplify checking loop: make name end in dot s += "." } last := byte('.') ok := false // ok once we've seen a letter + partlen := 0 for i := 0; i < len(s); i++ { c := s[i] switch { default: return false - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': + case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': ok = true + partlen++ case '0' <= c && c <= '9': // fine + partlen++ case c == '-': // byte before dash cannot be dot if last == '.' { return false } + partlen++ case c == '.': // byte before dot cannot be dot, dash if last == '.' || last == '-' { return false } + if partlen > 63 || partlen == 0 { + return false + } + partlen = 0 } last = c } @@ -232,11 +239,13 @@ func isDomainName(s string) bool { return ok } +var onceLoadConfig sync.Once + func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Error) { if !isDomainName(name) { return name, nil, &DNSError{Error: "invalid domain name", Name: name} } - once.Do(loadConfig) + onceLoadConfig.Do(loadConfig) if dnserr != nil || cfg == nil { err = dnserr return @@ -290,7 +299,7 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Erro // It returns the canonical name for the host and an array of that // host's addresses. func LookupHost(name string) (cname string, addrs []string, err os.Error) { - once.Do(loadConfig) + onceLoadConfig.Do(loadConfig) if dnserr != nil || cfg == nil { err = dnserr return @@ -317,9 +326,14 @@ type SRV struct { Weight uint16 } -func LookupSRV(name string) (cname string, addrs []*SRV, err os.Error) { +// LookupSRV tries to resolve an SRV query of the given service, +// protocol, and domain name, as specified in RFC 2782. In most cases +// the proto argument can be the same as the corresponding +// Addr.Network(). +func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) { + target := "_" + service + "._" + proto + "." + name var records []dnsRR - cname, records, err = lookup(name, dnsTypeSRV) + cname, records, err = lookup(target, dnsTypeSRV) if err != nil { return } @@ -330,3 +344,22 @@ func LookupSRV(name string) (cname string, addrs []*SRV, err os.Error) { } return } + +type MX struct { + Host string + Pref uint16 +} + +func LookupMX(name string) (entries []*MX, err os.Error) { + var records []dnsRR + _, records, err = lookup(name, dnsTypeMX) + if err != nil { + return + } + entries = make([]*MX, len(records)) + for i := 0; i < len(records); i++ { + r := records[i].(*dnsRR_MX) + entries[i] = &MX{r.Mx, r.Pref} + } + return +} |