aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/dnsmsg.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/dnsmsg.go')
-rw-r--r--libgo/go/net/dnsmsg.go164
1 files changed, 71 insertions, 93 deletions
diff --git a/libgo/go/net/dnsmsg.go b/libgo/go/net/dnsmsg.go
index 93078fe..afdb44c 100644
--- a/libgo/go/net/dnsmsg.go
+++ b/libgo/go/net/dnsmsg.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// DNS packet assembly. See RFC 1035.
+// DNS packet assembly. See RFC 1035.
//
// This is intended to support name resolution during Dial.
// It doesn't have to be blazing fast.
@@ -18,7 +18,7 @@
// generic pack/unpack routines.
//
// TODO(rsc): There are enough names defined in this file that they're all
-// prefixed with dns. Perhaps put this in its own package later.
+// prefixed with dns. Perhaps put this in its own package later.
package net
@@ -109,7 +109,7 @@ const (
// DNS queries.
type dnsQuestion struct {
- Name string `net:"domain-name"` // `net:"domain-name"` specifies encoding; see packers below
+ Name string
Qtype uint16
Qclass uint16
}
@@ -124,7 +124,7 @@ func (q *dnsQuestion) Walk(f func(v interface{}, name, tag string) bool) bool {
// There are many types of messages,
// but they all share the same header.
type dnsRR_Header struct {
- Name string `net:"domain-name"`
+ Name string
Rrtype uint16
Class uint16
Ttl uint32
@@ -152,7 +152,7 @@ type dnsRR interface {
type dnsRR_CNAME struct {
Hdr dnsRR_Header
- Cname string `net:"domain-name"`
+ Cname string
}
func (rr *dnsRR_CNAME) Header() *dnsRR_Header {
@@ -163,77 +163,10 @@ func (rr *dnsRR_CNAME) Walk(f func(v interface{}, name, tag string) bool) bool {
return rr.Hdr.Walk(f) && f(&rr.Cname, "Cname", "domain")
}
-type dnsRR_HINFO struct {
- Hdr dnsRR_Header
- Cpu string
- Os string
-}
-
-func (rr *dnsRR_HINFO) Header() *dnsRR_Header {
- return &rr.Hdr
-}
-
-func (rr *dnsRR_HINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
- return rr.Hdr.Walk(f) && f(&rr.Cpu, "Cpu", "") && f(&rr.Os, "Os", "")
-}
-
-type dnsRR_MB struct {
- Hdr dnsRR_Header
- Mb string `net:"domain-name"`
-}
-
-func (rr *dnsRR_MB) Header() *dnsRR_Header {
- return &rr.Hdr
-}
-
-func (rr *dnsRR_MB) Walk(f func(v interface{}, name, tag string) bool) bool {
- return rr.Hdr.Walk(f) && f(&rr.Mb, "Mb", "domain")
-}
-
-type dnsRR_MG struct {
- Hdr dnsRR_Header
- Mg string `net:"domain-name"`
-}
-
-func (rr *dnsRR_MG) Header() *dnsRR_Header {
- return &rr.Hdr
-}
-
-func (rr *dnsRR_MG) Walk(f func(v interface{}, name, tag string) bool) bool {
- return rr.Hdr.Walk(f) && f(&rr.Mg, "Mg", "domain")
-}
-
-type dnsRR_MINFO struct {
- Hdr dnsRR_Header
- Rmail string `net:"domain-name"`
- Email string `net:"domain-name"`
-}
-
-func (rr *dnsRR_MINFO) Header() *dnsRR_Header {
- return &rr.Hdr
-}
-
-func (rr *dnsRR_MINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
- return rr.Hdr.Walk(f) && f(&rr.Rmail, "Rmail", "domain") && f(&rr.Email, "Email", "domain")
-}
-
-type dnsRR_MR struct {
- Hdr dnsRR_Header
- Mr string `net:"domain-name"`
-}
-
-func (rr *dnsRR_MR) Header() *dnsRR_Header {
- return &rr.Hdr
-}
-
-func (rr *dnsRR_MR) Walk(f func(v interface{}, name, tag string) bool) bool {
- return rr.Hdr.Walk(f) && f(&rr.Mr, "Mr", "domain")
-}
-
type dnsRR_MX struct {
Hdr dnsRR_Header
Pref uint16
- Mx string `net:"domain-name"`
+ Mx string
}
func (rr *dnsRR_MX) Header() *dnsRR_Header {
@@ -246,7 +179,7 @@ func (rr *dnsRR_MX) Walk(f func(v interface{}, name, tag string) bool) bool {
type dnsRR_NS struct {
Hdr dnsRR_Header
- Ns string `net:"domain-name"`
+ Ns string
}
func (rr *dnsRR_NS) Header() *dnsRR_Header {
@@ -259,7 +192,7 @@ func (rr *dnsRR_NS) Walk(f func(v interface{}, name, tag string) bool) bool {
type dnsRR_PTR struct {
Hdr dnsRR_Header
- Ptr string `net:"domain-name"`
+ Ptr string
}
func (rr *dnsRR_PTR) Header() *dnsRR_Header {
@@ -272,8 +205,8 @@ func (rr *dnsRR_PTR) Walk(f func(v interface{}, name, tag string) bool) bool {
type dnsRR_SOA struct {
Hdr dnsRR_Header
- Ns string `net:"domain-name"`
- Mbox string `net:"domain-name"`
+ Ns string
+ Mbox string
Serial uint32
Refresh uint32
Retry uint32
@@ -315,7 +248,7 @@ func (rr *dnsRR_TXT) Walk(f func(v interface{}, name, tag string) bool) bool {
if !f(&txt, "Txt", "") {
return false
}
- // more bytes than rr.Hdr.Rdlength said there woudld be
+ // more bytes than rr.Hdr.Rdlength said there would be
if rr.Hdr.Rdlength-n < uint16(len(txt))+1 {
return false
}
@@ -330,7 +263,7 @@ type dnsRR_SRV struct {
Priority uint16
Weight uint16
Port uint16
- Target string `net:"domain-name"`
+ Target string
}
func (rr *dnsRR_SRV) Header() *dnsRR_Header {
@@ -347,7 +280,7 @@ func (rr *dnsRR_SRV) Walk(f func(v interface{}, name, tag string) bool) bool {
type dnsRR_A struct {
Hdr dnsRR_Header
- A uint32 `net:"ipv4"`
+ A uint32
}
func (rr *dnsRR_A) Header() *dnsRR_Header {
@@ -360,7 +293,7 @@ func (rr *dnsRR_A) Walk(f func(v interface{}, name, tag string) bool) bool {
type dnsRR_AAAA struct {
Hdr dnsRR_Header
- AAAA [16]byte `net:"ipv6"`
+ AAAA [16]byte
}
func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
@@ -376,17 +309,12 @@ func (rr *dnsRR_AAAA) Walk(f func(v interface{}, name, tag string) bool) bool {
// All the packers and unpackers take a (msg []byte, off int)
// and return (off1 int, ok bool). If they return ok==false, they
// also return off1==len(msg), so that the next unpacker will
-// also fail. This lets us avoid checks of ok until the end of a
+// also fail. This lets us avoid checks of ok until the end of a
// packing sequence.
// Map of constructors for each RR wire type.
var rr_mk = map[int]func() dnsRR{
dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) },
- dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) },
- dnsTypeMB: func() dnsRR { return new(dnsRR_MB) },
- dnsTypeMG: func() dnsRR { return new(dnsRR_MG) },
- dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) },
- dnsTypeMR: func() dnsRR { return new(dnsRR_MR) },
dnsTypeMX: func() dnsRR { return new(dnsRR_MX) },
dnsTypeNS: func() dnsRR { return new(dnsRR_NS) },
dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) },
@@ -399,13 +327,20 @@ var rr_mk = map[int]func() dnsRR{
// Pack a domain name s into msg[off:].
// Domain names are a sequence of counted strings
-// split at the dots. They end with a zero-length string.
+// split at the dots. They end with a zero-length string.
func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
// Add trailing dot to canonicalize name.
if n := len(s); n == 0 || s[n-1] != '.' {
s += "."
}
+ // Allow root domain.
+ if s == "." {
+ msg[off] = 0
+ off++
+ return off, true
+ }
+
// Each dot ends a segment of the name.
// We trade each dot byte for a length byte.
// There is also a trailing zero.
@@ -422,8 +357,13 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
if i-begin >= 1<<6 { // top two bits of length must be clear
return len(msg), false
}
+ if i-begin == 0 {
+ return len(msg), false
+ }
+
msg[off] = byte(i - begin)
off++
+
for j := begin; j < i; j++ {
msg[off] = s[j]
off++
@@ -440,8 +380,8 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
// In addition to the simple sequences of counted strings above,
// domain names are allowed to refer to strings elsewhere in the
// packet, to avoid repeating common suffixes when returning
-// many entries in a single domain. The pointers are marked
-// by a length byte with the top two bits set. Ignoring those
+// many entries in a single domain. The pointers are marked
+// by a length byte with the top two bits set. Ignoring those
// two bits, that byte and the next give a 14 bit offset from msg[0]
// where we should pick up the trail.
// Note that if we jump elsewhere in the packet,
@@ -494,6 +434,9 @@ Loop:
return "", len(msg), false
}
}
+ if len(s) == 0 {
+ s = "."
+ }
if ptr == 0 {
off1 = off
}
@@ -803,20 +746,32 @@ func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
// Pack it in: header and then the pieces.
off := 0
off, ok = packStruct(&dh, msg, off)
+ if !ok {
+ return nil, false
+ }
for i := 0; i < len(question); i++ {
off, ok = packStruct(&question[i], msg, off)
+ if !ok {
+ return nil, false
+ }
}
for i := 0; i < len(answer); i++ {
off, ok = packRR(answer[i], msg, off)
+ if !ok {
+ return nil, false
+ }
}
for i := 0; i < len(ns); i++ {
off, ok = packRR(ns[i], msg, off)
+ if !ok {
+ return nil, false
+ }
}
for i := 0; i < len(extra); i++ {
off, ok = packRR(extra[i], msg, off)
- }
- if !ok {
- return nil, false
+ if !ok {
+ return nil, false
+ }
}
return msg[0:off], true
}
@@ -848,6 +803,9 @@ func (dns *dnsMsg) Unpack(msg []byte) bool {
for i := 0; i < len(dns.question); i++ {
off, ok = unpackStruct(&dns.question[i], msg, off)
+ if !ok {
+ return false
+ }
}
for i := 0; i < int(dh.Ancount); i++ {
rec, off, ok = unpackRR(msg, off)
@@ -904,3 +862,23 @@ func (dns *dnsMsg) String() string {
}
return s
}
+
+// IsResponseTo reports whether m is an acceptable response to query.
+func (m *dnsMsg) IsResponseTo(query *dnsMsg) bool {
+ if !m.response {
+ return false
+ }
+ if m.id != query.id {
+ return false
+ }
+ if len(m.question) != len(query.question) {
+ return false
+ }
+ for i, q := range m.question {
+ q2 := query.question[i]
+ if !equalASCIILabel(q.Name, q2.Name) || q.Qtype != q2.Qtype || q.Qclass != q2.Qclass {
+ return false
+ }
+ }
+ return true
+}